Compare commits
673
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6ed5016d1 | ||
|
|
d4e151d4be | ||
|
|
efee4f9e1a | ||
|
|
a3257b33b4 | ||
|
|
96007bd230 | ||
|
|
554d9ecb06 | ||
|
|
a12a5b3a15 | ||
|
|
a79e2f85bc | ||
|
|
a2190fdde0 | ||
|
|
849415a78e | ||
|
|
d33f5428b6 | ||
|
|
c73b01d549 | ||
|
|
4286bc37b3 | ||
|
|
d4ecb88fb4 | ||
|
|
57a8955795 | ||
|
|
ac53b1f97a | ||
|
|
4b83a10475 | ||
|
|
7e957a2841 | ||
|
|
38c0e70bbc | ||
|
|
94c40cce7d | ||
|
|
0059050440 | ||
|
|
f7be890eb9 | ||
|
|
59ae971a07 | ||
|
|
cfcd5efa2c | ||
|
|
fb1e85893c | ||
|
|
084972577e | ||
|
|
94df5ca048 | ||
|
|
6142a7afbb | ||
|
|
d2e0c57676 | ||
|
|
e48d8d8715 | ||
|
|
7de333e1ea | ||
|
|
2123afc4b0 | ||
|
|
ea91fa1723 | ||
|
|
4dcdec7a35 | ||
|
|
196f1914a3 | ||
|
|
ea4c7a4a37 | ||
|
|
c22fec97b4 | ||
|
|
989a0456c0 | ||
|
|
8c79a94a8c | ||
|
|
a7a6a820c0 | ||
|
|
1fa09a690e | ||
|
|
b0a84970f2 | ||
|
|
b2a115f935 | ||
|
|
9dfed0a211 | ||
|
|
5283676be7 | ||
|
|
a82509f0e0 | ||
|
|
64c92ce91d | ||
|
|
b7426e73d8 | ||
|
|
969bfd6945 | ||
|
|
200487a6fc | ||
|
|
3f330e78c5 | ||
|
|
05726c6a5a | ||
|
|
fcace22393 | ||
|
|
b95462ea38 | ||
|
|
42cd32f376 | ||
|
|
55d6dd4dce | ||
|
|
7017e24adf | ||
|
|
a4d597d426 | ||
|
|
b51376ba0d | ||
|
|
c72b5d7912 | ||
|
|
462a5bc84b | ||
|
|
3edbc71787 | ||
|
|
ee67736ac5 | ||
|
|
8bb6b7a942 | ||
|
|
c1c0d960eb | ||
|
|
a25e2ad101 | ||
|
|
7ee8bd47c8 | ||
|
|
b72ed66bb3 | ||
|
|
589bd8d29f | ||
|
|
7f7c425e34 | ||
|
|
062ea5e968 | ||
|
|
87e187c225 | ||
|
|
c0f15d8212 | ||
|
|
499de6e836 | ||
|
|
e72d117a62 | ||
|
|
abede79a4c | ||
|
|
fa415318ff | ||
|
|
718959b920 | ||
|
|
6d0ebc3a1b | ||
|
|
5f5cb965e3 | ||
|
|
86090c295c | ||
|
|
6983587f28 | ||
|
|
5e87baf174 | ||
|
|
fc93bbd7c5 | ||
|
|
ce832ad6f4 | ||
|
|
a5d53eee77 | ||
|
|
4dd63da62b | ||
|
|
2e8dd294de | ||
|
|
8917ceb08a | ||
|
|
87f116daee | ||
|
|
9e91746488 | ||
|
|
5b4ed1a0c3 | ||
|
|
56731e34cc | ||
|
|
026e5f5679 | ||
|
|
e75c160579 | ||
|
|
5d613396e1 | ||
|
|
da551f9d3c | ||
|
|
47e4861fdb | ||
|
|
1a85a89440 | ||
|
|
7ab412a8f7 | ||
|
|
5a14174a81 | ||
|
|
5e00b93783 | ||
|
|
31d9b023e6 | ||
|
|
103e503a47 | ||
|
|
1952cb0e78 | ||
|
|
69340f4ddf | ||
|
|
c52bf2200e | ||
|
|
8dccee69f2 | ||
|
|
c7a6fdd879 | ||
|
|
8bcdaf4cda | ||
|
|
3eb1359504 | ||
|
|
39cf8ad4d6 | ||
|
|
faef98f0ae | ||
|
|
710e2daa27 | ||
|
|
06ea3924fa | ||
|
|
965e2d8972 | ||
|
|
73de2fed43 | ||
|
|
536859e067 | ||
|
|
54bfaef473 | ||
|
|
e2cad707a7 | ||
|
|
ec8d9798ab | ||
|
|
e629c1e81a | ||
|
|
25feed793c | ||
|
|
2867367e16 | ||
|
|
50b408e74d | ||
|
|
8f531c7c05 | ||
|
|
350d16fee1 | ||
|
|
c052c66266 | ||
|
|
e2032df236 | ||
|
|
9ece19869d | ||
|
|
22abc8160c | ||
|
|
b1a7a22bf9 | ||
|
|
c4b38cc0dc | ||
|
|
44d6d931d5 | ||
|
|
7f1e47d7fd | ||
|
|
0eddfa4073 | ||
|
|
83a034ce91 | ||
|
|
5ab5aa01a2 | ||
|
|
b22f9156b5 | ||
|
|
bab5e2018b | ||
|
|
3f7692ce75 | ||
|
|
b69fb3b0e5 | ||
|
|
83af6e74f6 | ||
|
|
b9908003ba | ||
|
|
1f9af79215 | ||
|
|
e31e40a7ef | ||
|
|
81f6b3cc15 | ||
|
|
8adb208a91 | ||
|
|
545c3a17d2 | ||
|
|
ad76988f63 | ||
|
|
d2bbd7e1fc | ||
|
|
fb1ebb3bdf | ||
|
|
b2489537ef | ||
|
|
382a7ea411 | ||
|
|
1ae2b4c153 | ||
|
|
e8875e817e | ||
|
|
4a01c880f3 | ||
|
|
f7f00dc7bb | ||
|
|
d151b6e923 | ||
|
|
8f8e9c1061 | ||
|
|
b40358a723 | ||
|
|
01f0934da3 | ||
|
|
df7755dbc4 | ||
|
|
9073234040 | ||
|
|
053cd0fa27 | ||
|
|
961dc88dc7 | ||
|
|
b16607a844 | ||
|
|
d0d804631c | ||
|
|
3e778a88dc | ||
|
|
dbb09c9c79 | ||
|
|
06f44b67de | ||
|
|
1861852852 | ||
|
|
3ee0eee80d | ||
|
|
69ce870a81 | ||
|
|
d8467c3206 | ||
|
|
de87f40a01 | ||
|
|
f22fb56afd | ||
|
|
f2627e6ebf | ||
|
|
24e6a13d93 | ||
|
|
b56050ad1c | ||
|
|
cff83ed062 | ||
|
|
8ecce874b0 | ||
|
|
00e319b3c6 | ||
|
|
05559f3ea0 | ||
|
|
4b3b5c322a | ||
|
|
b1280c8285 | ||
|
|
1e0e1c7859 | ||
|
|
ec2bb81ec8 | ||
|
|
fe95c6fcbc | ||
|
|
853ec8f69c | ||
|
|
b68c090ee5 | ||
|
|
cb9b811730 | ||
|
|
98b5260d93 | ||
|
|
613262f7a5 | ||
|
|
9ae6f5201c | ||
|
|
cfb75fcf8f | ||
|
|
ae6ccdfb52 | ||
|
|
9e73c6a462 | ||
|
|
24c017bc2b | ||
|
|
3188f23439 | ||
|
|
33e528c569 | ||
|
|
e10945eeda | ||
|
|
47b2a2fdcb | ||
|
|
860938f26c | ||
|
|
5766d84804 | ||
|
|
6362c022b5 | ||
|
|
a6118c14dd | ||
|
|
d384fb35f1 | ||
|
|
3ed3714e79 | ||
|
|
3893b26d30 | ||
|
|
1ba0ad234b | ||
|
|
9f6a5aac39 | ||
|
|
129274a8e6 | ||
|
|
3fadda15fd | ||
|
|
7ea7edc1e2 | ||
|
|
dad953b45b | ||
|
|
ed1363b035 | ||
|
|
b2ab4f49d9 | ||
|
|
a60379b40f | ||
|
|
7db2a58f9d | ||
|
|
7279556bf7 | ||
|
|
52cc2ef7df | ||
|
|
a218da93a6 | ||
|
|
10fe82dea8 | ||
|
|
b0de4dfbf3 | ||
|
|
cd0e2e41a8 | ||
|
|
dc3330d55e | ||
|
|
a016feab2a | ||
|
|
68446ccf65 | ||
|
|
c7aec5cfcb | ||
|
|
f58144d785 | ||
|
|
415b902f53 | ||
|
|
165b131b27 | ||
|
|
0cff5895c7 | ||
|
|
31881f8e5a | ||
|
|
346af6118d | ||
|
|
bcbc3bb146 | ||
|
|
d7440cfe54 | ||
|
|
801606e37f | ||
|
|
01e7b8caee | ||
|
|
e883ef5c5e | ||
|
|
2f391cde5b | ||
|
|
3620314dca | ||
|
|
9bdd1ed387 | ||
|
|
37dc8bf110 | ||
|
|
3754043f8b | ||
|
|
1ee45b6135 | ||
|
|
a51410c722 | ||
|
|
91173d2434 | ||
|
|
8dd33c285e | ||
|
|
6a7385823a | ||
|
|
9053b343d1 | ||
|
|
6562107578 | ||
|
|
8f5bedc12a | ||
|
|
3044f3bdf7 | ||
|
|
5eb8fb64c7 | ||
|
|
ae84e16b9b | ||
|
|
5e5cc1c587 | ||
|
|
a3aa84b983 | ||
|
|
49374c8e7c | ||
|
|
8f4eeba092 | ||
|
|
66cceb0f34 | ||
|
|
b34fc98c9c | ||
|
|
e4ada295e2 | ||
|
|
805e8fbee7 | ||
|
|
24fafe5a34 | ||
|
|
df4cea8e00 | ||
|
|
52b25b8b15 | ||
|
|
b65db3cdad | ||
|
|
020d2e4e68 | ||
|
|
5ccef2de5e | ||
|
|
4ce2924380 | ||
|
|
f5b345636c | ||
|
|
c533c584da | ||
|
|
c1ebda9274 | ||
|
|
1b2c0e8f8b | ||
|
|
df6b9023f1 | ||
|
|
0702a97b6d | ||
|
|
c552a22af8 | ||
|
|
fbdcd04096 | ||
|
|
89d0723eb3 | ||
|
|
f163a270d1 | ||
|
|
e04314608f | ||
|
|
61c91c3542 | ||
|
|
2a9f3c7568 | ||
|
|
2640b7d77d | ||
|
|
2b229cd1e7 | ||
|
|
d098ee671e | ||
|
|
2c3c685522 | ||
|
|
b96e6ee9ce | ||
|
|
1a6266e2ec | ||
|
|
c70ec7676e | ||
|
|
5e97391d53 | ||
|
|
8eebd814ae | ||
|
|
bd754d1103 | ||
|
|
e362d06b5a | ||
|
|
45a4dd7009 | ||
|
|
ff53e5e841 | ||
|
|
cd0ed05eb8 | ||
|
|
89f41a4500 | ||
|
|
38fdc91444 | ||
|
|
f8f523eb9c | ||
|
|
5a0da4e158 | ||
|
|
4f7b589cbd | ||
|
|
e5bf54ca02 | ||
|
|
866a11fd89 | ||
|
|
b10effa3c7 | ||
|
|
1f1ca510f4 | ||
|
|
06151c0592 | ||
|
|
12a799a2fd | ||
|
|
e91a37684a | ||
|
|
b4a0e74457 | ||
|
|
11ba5e733e | ||
|
|
315c463eec | ||
|
|
62bfbd6822 | ||
|
|
290c2e3d42 | ||
|
|
c67daf885c | ||
|
|
c3944128eb | ||
|
|
c63d2a9bc6 | ||
|
|
e00998f9e3 | ||
|
|
61a5098776 | ||
|
|
9203c81084 | ||
|
|
8864696783 | ||
|
|
99d338f50a | ||
|
|
2b28ff6c18 | ||
|
|
6d3795f1f4 | ||
|
|
c0b84a88d3 | ||
|
|
5b0d799a00 | ||
|
|
9e6ecbc558 | ||
|
|
c3de7f12f0 | ||
|
|
473fdf8466 | ||
|
|
47c0ec01eb | ||
|
|
6410cb54b6 | ||
|
|
b8ff3d3050 | ||
|
|
d474a502a8 | ||
|
|
06e1b3663d | ||
|
|
38ff2c24e4 | ||
|
|
2689bbdcd2 | ||
|
|
c7b4465adf | ||
|
|
3f6913ab39 | ||
|
|
31ffa306eb | ||
|
|
13ab03c459 | ||
|
|
dd2e3a6556 | ||
|
|
4608683bde | ||
|
|
1f96ccea68 | ||
|
|
c055be1146 | ||
|
|
a316eaae9d | ||
|
|
996c4ac4d5 | ||
|
|
560e4a4040 | ||
|
|
d98ce18f9e | ||
|
|
0fd1739ce5 | ||
|
|
cf43566bde | ||
|
|
24a9712e91 | ||
|
|
03f5b5e78b | ||
|
|
9552fbc033 | ||
|
|
74a4a60195 | ||
|
|
ef35999091 | ||
|
|
cba44d7eb1 | ||
|
|
c5b72e5a64 | ||
|
|
863c288e0d | ||
|
|
a97512cc7b | ||
|
|
0884654c1e | ||
|
|
5b4440f767 | ||
|
|
cfbea6e894 | ||
|
|
774a7d697f | ||
|
|
dbb08acba3 | ||
|
|
6db201c1de | ||
|
|
54cd8324ed | ||
|
|
562e2b5cb2 | ||
|
|
ca2647d4d9 | ||
|
|
bbdc64582a | ||
|
|
dabae31bfd | ||
|
|
5b42a6ad35 | ||
|
|
870ae13b4c | ||
|
|
4c32a21f28 | ||
|
|
2ea603e59e | ||
|
|
3e485e3841 | ||
|
|
7766b3f118 | ||
|
|
8db3b01284 | ||
|
|
4fbd2e5eba | ||
|
|
53d3d5ac1c | ||
|
|
35de756120 | ||
|
|
f89cf31982 | ||
|
|
8976a40dc8 | ||
|
|
7669aeb218 | ||
|
|
6e996221b2 | ||
|
|
117c0c1306 | ||
|
|
e56d7bc2d5 | ||
|
|
85ec66a9e2 | ||
|
|
ba14ead8fc | ||
|
|
1211d27011 | ||
|
|
904a1b7805 | ||
|
|
66a8c659b4 | ||
|
|
f1a437500e | ||
|
|
29ced0b460 | ||
|
|
e45265ac71 | ||
|
|
cc3c339cc3 | ||
|
|
6f95989569 | ||
|
|
14f0c5a5fb | ||
|
|
0167a42990 | ||
|
|
1d65c4791c | ||
|
|
8a1fe6e5b1 | ||
|
|
437f7ef807 | ||
|
|
2b3683d4a4 | ||
|
|
6c84153cdb | ||
|
|
ccce5a2848 | ||
|
|
5673620fbd | ||
|
|
41d6940b89 | ||
|
|
84150bec8c | ||
|
|
5a311d14c9 | ||
|
|
0f152a4b30 | ||
|
|
45d8b537a3 | ||
|
|
dc41be5715 | ||
|
|
a85cf66419 | ||
|
|
6e82e917ac | ||
|
|
8dfdccd4aa | ||
|
|
82833cc06a | ||
|
|
aac3799b14 | ||
|
|
0d1c9ff0f1 | ||
|
|
f8eec8a056 | ||
|
|
ee6f26d473 | ||
|
|
de62d2d972 | ||
|
|
955e233c46 | ||
|
|
0bafa4c7d5 | ||
|
|
045529dc38 | ||
|
|
5ca3e4d90f | ||
|
|
9048d41f72 | ||
|
|
d731c4797c | ||
|
|
4a931ca134 | ||
|
|
3398b15d8a | ||
|
|
1e98ecbd21 | ||
|
|
a9c7c2bb46 | ||
|
|
ba2c71de67 | ||
|
|
15d2aed343 | ||
|
|
0284eaf9a2 | ||
|
|
c9c240cb29 | ||
|
|
64aa39fe4b | ||
|
|
485c609791 | ||
|
|
61457bc24d | ||
|
|
2217925285 | ||
|
|
28fe7458ca | ||
|
|
2cb88624f3 | ||
|
|
d2ae780996 | ||
|
|
bd129f1229 | ||
|
|
f3cd2db1ce | ||
|
|
418ea41e22 | ||
|
|
bcc1c8a474 | ||
|
|
496fdee10e | ||
|
|
c8fc91a3bd | ||
|
|
48cccc2678 | ||
|
|
9d66eeae51 | ||
|
|
7ab20d07f9 | ||
|
|
b0aa1b8a3e | ||
|
|
13ffe8a8d0 | ||
|
|
01420c56ff | ||
|
|
15bb7b94ad | ||
|
|
d65ef297a9 | ||
|
|
4062c493cb | ||
|
|
786ab51bd1 | ||
|
|
6cb2e3a3cf | ||
|
|
cf0e0ce4b2 | ||
|
|
9c21a4481a | ||
|
|
7a6c69d773 | ||
|
|
4f10a75386 | ||
|
|
9c26f4d01b | ||
|
|
b3bbe260c6 | ||
|
|
69a4ecdbde | ||
|
|
dbba734672 | ||
|
|
1c57ec4df1 | ||
|
|
f4fa0bd25a | ||
|
|
c2595b533d | ||
|
|
65316075fa | ||
|
|
46955dd933 | ||
|
|
024ed575fc | ||
|
|
871d7068da | ||
|
|
efbb75ec01 | ||
|
|
57c9ea9471 | ||
|
|
448f8f4ba5 | ||
|
|
5a5cd1daeb | ||
|
|
d7365c4b66 | ||
|
|
b6c448b630 | ||
|
|
87e1f9998e | ||
|
|
bdff40b4bc | ||
|
|
0b4f918208 | ||
|
|
df609d442c | ||
|
|
5730e39b32 | ||
|
|
83e9bc8ff6 | ||
|
|
a830e4729f | ||
|
|
e3ff090915 | ||
|
|
c5b6032184 | ||
|
|
cb80c6d417 | ||
|
|
b9ff2388db | ||
|
|
07b766e4d2 | ||
|
|
d19ef2607d | ||
|
|
af0b7391c9 | ||
|
|
9ea980c603 | ||
|
|
2741551c18 | ||
|
|
b06003990c | ||
|
|
377d219220 | ||
|
|
0f20f79a5e | ||
|
|
f658ae4d64 | ||
|
|
4e7192264c | ||
|
|
69ecf00999 | ||
|
|
cbb7189328 | ||
|
|
a05ff9c41a | ||
|
|
62b80a6438 | ||
|
|
4f76724e3e | ||
|
|
e20061d921 | ||
|
|
f133200c7f | ||
|
|
98d01d7933 | ||
|
|
0a3509faad | ||
|
|
070f2a2045 | ||
|
|
7a56e1695d | ||
|
|
bbfef16889 | ||
|
|
ba0211698f | ||
|
|
9f9d44e87d | ||
|
|
349eba7053 | ||
|
|
b28d671975 | ||
|
|
7d5cc9b080 | ||
|
|
dce802d153 | ||
|
|
6d646e3baf | ||
|
|
05b07c2bfe | ||
|
|
e653ad328f | ||
|
|
6b7a04176b | ||
|
|
ac44f4c553 | ||
|
|
b52386622c | ||
|
|
b47caa7667 | ||
|
|
071a9ab34b | ||
|
|
e49ad9da6a | ||
|
|
b508d7b252 | ||
|
|
817521bb08 | ||
|
|
f60e8a2910 | ||
|
|
a557678513 | ||
|
|
9ff68ecba3 | ||
|
|
48e0cf0808 | ||
|
|
c14e57cfd5 | ||
|
|
01addaea7c | ||
|
|
9002e63961 | ||
|
|
098bdb5e3a | ||
|
|
2514a2342b | ||
|
|
4600d6e4ca | ||
|
|
c217741924 | ||
|
|
1180a5ff97 | ||
|
|
71399105ee | ||
|
|
3bca206e45 | ||
|
|
044e9639e9 | ||
|
|
2cde42971e | ||
|
|
c6c320a2ff | ||
|
|
757cbd0f49 | ||
|
|
d70ff8d3d6 | ||
|
|
7ba2acefda | ||
|
|
03a1d10fe4 | ||
|
|
39f55cee5d | ||
|
|
5227d118fc | ||
|
|
16e095104f | ||
|
|
e6531daa41 | ||
|
|
7bf753e6c2 | ||
|
|
22610c2d0a | ||
|
|
4b86b981b3 | ||
|
|
615748548b | ||
|
|
13c9dffc3d | ||
|
|
fa8868d42a | ||
|
|
d382887b95 | ||
|
|
74265b25d7 | ||
|
|
2211abbd72 | ||
|
|
e5fe6a3106 | ||
|
|
86e4280680 | ||
|
|
e4afa67cd0 | ||
|
|
19c1f2f8c6 | ||
|
|
088c399b9f | ||
|
|
f1f775268f | ||
|
|
09af8db1fe | ||
|
|
def34a329d | ||
|
|
97a264d0b8 | ||
|
|
cbbec5c688 | ||
|
|
8880d7c5d7 | ||
|
|
ce04dd9ff2 | ||
|
|
e37185223f | ||
|
|
1bb3233fb2 | ||
|
|
0a11831ab0 | ||
|
|
9f1a1d7a1b | ||
|
|
c0566a91b2 | ||
|
|
827cdbecc7 | ||
|
|
d1e0af0dbf | ||
|
|
46a85b8e65 | ||
|
|
5db3b9c0b9 | ||
|
|
8f182a5877 | ||
|
|
8d88d2cea0 | ||
|
|
4ebb30c957 | ||
|
|
3486244137 | ||
|
|
7c15ee6c01 | ||
|
|
a4dd3cc49b | ||
|
|
ca5c3bc21d | ||
|
|
5cd6bf3d46 | ||
|
|
f1d4aa1862 | ||
|
|
75db3b3cbd | ||
|
|
777d330f8e | ||
|
|
8697561ed6 | ||
|
|
aafa3d7256 | ||
|
|
5531566e2f | ||
|
|
5da5c202f5 | ||
|
|
e2d7b1ee59 | ||
|
|
9d6a709fae | ||
|
|
639b586e85 | ||
|
|
bed81eed76 | ||
|
|
2d19796250 | ||
|
|
55b4279709 | ||
|
|
dfb04b4971 | ||
|
|
14632bae15 | ||
|
|
71c419a818 | ||
|
|
d5fef8729a | ||
|
|
8b74e63195 | ||
|
|
8639cf0ff6 | ||
|
|
3d760b8f15 | ||
|
|
8d08ede22d | ||
|
|
6352400598 | ||
|
|
30c440439e | ||
|
|
9ddedd0b78 | ||
|
|
9b356e53b4 | ||
|
|
4db5d37578 | ||
|
|
65564f1afc | ||
|
|
13d4c463cd | ||
|
|
7ba90904d8 | ||
|
|
3e75d64e0d | ||
|
|
3baad78bb7 | ||
|
|
a30f2227c4 | ||
|
|
cf2cfad746 | ||
|
|
972325b04a | ||
|
|
17736cc985 | ||
|
|
910a3e7a7f | ||
|
|
ac17bc4b64 | ||
|
|
399a3daa4c | ||
|
|
afd42f8a9a | ||
|
|
5d3a3a6f11 | ||
|
|
077700910b | ||
|
|
84814f3476 | ||
|
|
c450f57e8d | ||
|
|
6ba7ce5e7f | ||
|
|
d823daeea4 | ||
|
|
7c8a54b35a | ||
|
|
5bc861b5ec | ||
|
|
2f600207f7 | ||
|
|
b67bc33c49 | ||
|
|
03f659ebb3 | ||
|
|
96843cd2be | ||
|
|
af7a5630ac | ||
|
|
512149e491 | ||
|
|
aada0a805a | ||
|
|
9e935449ae | ||
|
|
d5b4ae7e53 | ||
|
|
995f1f1eaf | ||
|
|
02410df2d7 | ||
|
|
0d8f14e050 | ||
|
|
c2d2985e92 | ||
|
|
02f56dd0ec | ||
|
|
88263df9c2 | ||
|
|
71890d662a | ||
|
|
081c9f44ae | ||
|
|
c60e5841f7 | ||
|
|
96e082cb5d | ||
|
|
152574ebb3 | ||
|
|
b5f42ad715 | ||
|
|
86b0c6db3e | ||
|
|
3aed0b2e5f | ||
|
|
9c228c082f | ||
|
|
aa7bed137b | ||
|
|
1b4ffb6f1f | ||
|
|
e2e6ec40b7 | ||
|
|
8a9fa1efdc | ||
|
|
60d1434c40 | ||
|
|
d5efae6419 | ||
|
|
8489d50024 | ||
|
|
7af2580512 |
@@ -1,28 +0,0 @@
|
||||
inputs:
|
||||
all:
|
||||
description: 'Install all binaries'
|
||||
default: false
|
||||
version:
|
||||
description: 'Vega version'
|
||||
gobin:
|
||||
description: 'GOBIN path'
|
||||
default: '/home/runner/go/bin'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Install Vega binaries
|
||||
shell: bash
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ inputs.version }}/vega-linux-amd64.zip' -q
|
||||
unzip vega-linux-amd64.zip -d ${{ inputs.gobin }}
|
||||
|
||||
- name: Checkout vegawallet-dummy
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: 'vegaprotocol/vegawallet-dummy'
|
||||
path: './dummy'
|
||||
|
||||
- name: Install vegawallet-dummy binaries
|
||||
shell: bash
|
||||
run: go install
|
||||
working-directory: ./dummy
|
||||
@@ -1,25 +1,17 @@
|
||||
inputs:
|
||||
github-token:
|
||||
description: 'github token'
|
||||
outputs:
|
||||
token:
|
||||
description: 'api-token of wallet'
|
||||
value: ${{ steps.generate-api-token.outputs.api-token }}
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Checkout capsule
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: vegaprotocol/vegacapsule
|
||||
ref: main
|
||||
token: ${{ inputs.github-token }}
|
||||
path: './capsule'
|
||||
|
||||
- name: Build capsule
|
||||
run: go install
|
||||
- name: Vegacapsule version
|
||||
shell: bash
|
||||
working-directory: capsule
|
||||
run: vegacapsule version
|
||||
|
||||
- name: Login to docker
|
||||
- name: Vega wallet version
|
||||
shell: bash
|
||||
run: echo -n ${{ inputs.github-token }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
|
||||
run: vega wallet software version
|
||||
|
||||
- name: Start nomad
|
||||
shell: bash
|
||||
@@ -28,3 +20,32 @@ runs:
|
||||
- name: Bootstrap network
|
||||
shell: bash
|
||||
run: vegacapsule network bootstrap --config-path=./frontend-monorepo/vegacapsule/config.hcl --force
|
||||
|
||||
- name: Initialize wallet
|
||||
shell: bash
|
||||
run: vega wallet init -f --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import wallet
|
||||
shell: bash
|
||||
run: vega wallet import -w capsule_wallet --recovery-phrase-file ./frontend-monorepo/vegacapsule/recovery -p ./frontend-monorepo/vegacapsule/passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Generate second public key
|
||||
shell: bash
|
||||
run: vega wallet key generate -w capsule_wallet -p ./frontend-monorepo/vegacapsule/passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import network
|
||||
shell: bash
|
||||
run: vega wallet network import --force --from-file ./frontend-monorepo/vegacapsule/wallet-config.toml --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Init api-token
|
||||
shell: bash
|
||||
run: vega wallet api-token init --home ~/.vegacapsule/testnet/wallet --passphrase-file ./frontend-monorepo/vegacapsule/passphrase
|
||||
|
||||
- name: Generate api-token
|
||||
id: generate-api-token
|
||||
shell: bash
|
||||
run: echo api-token=$(vega wallet api-token generate --wallet-name capsule_wallet --tokens-passphrase-file ./frontend-monorepo/vegacapsule/passphrase --wallet-passphrase-file ./frontend-monorepo/vegacapsule/passphrase --home ~/.vegacapsule/testnet/wallet | grep -Eo '[a-zA-Z0-9]{64}') >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Start service using capsule network
|
||||
shell: bash
|
||||
run: vega wallet service run -n DV --load-tokens --tokens-passphrase-file ./frontend-monorepo/vegacapsule/passphrase --no-version-check --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
inputs:
|
||||
passphrase:
|
||||
description: 'Wallet password'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Create passphrase
|
||||
shell: bash
|
||||
run: echo "${{ inputs.passphrase }}" > ./passphrase
|
||||
|
||||
- name: Initialize wallet
|
||||
shell: bash
|
||||
run: vega wallet init -f --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import wallet
|
||||
shell: bash
|
||||
run: vega wallet import -w capsule_wallet --recovery-phrase-file ./frontend-monorepo/vegacapsule/recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import network
|
||||
shell: bash
|
||||
run: vega wallet network import --force --from-file ./frontend-monorepo/vegacapsule/wallet-config.toml --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Start service using capsule network
|
||||
shell: bash
|
||||
run: vegawallet-dummy service run --network DV --wallet capsule_wallet --passphrase-file ./passphrase --home ~/.vegacapsule/testnet/wallet &
|
||||
@@ -1,35 +0,0 @@
|
||||
inputs:
|
||||
recovery:
|
||||
description: 'Recovery phrase'
|
||||
passphrase:
|
||||
description: 'Wallet password'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Create passphrase
|
||||
shell: bash
|
||||
run: echo "${{ inputs.passphrase }}" > ./passphrase
|
||||
|
||||
- name: Create recovery
|
||||
shell: bash
|
||||
run: echo "${{ inputs.recovery }}" > ./recovery
|
||||
|
||||
- name: Initialize wallet
|
||||
shell: bash
|
||||
run: vega wallet init -f --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import wallet
|
||||
shell: bash
|
||||
run: vega wallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Create public key 2
|
||||
shell: bash
|
||||
run: vega wallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import network
|
||||
shell: bash
|
||||
run: vega wallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml" --force --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Start service using stagnet3 network
|
||||
shell: bash
|
||||
run: vegawallet-dummy service run --network stagnet3 --wallet UI_Trading_Test --passphrase-file ./passphrase --home ~/.vegacapsule/testnet/wallet &
|
||||
@@ -1,60 +0,0 @@
|
||||
name: Cypress tests -- manual trigger
|
||||
|
||||
# This workflow runs the frontend tests against chosen branch
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
project:
|
||||
description: 'Project'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- console-lite-e2e
|
||||
- explorer-e2e
|
||||
- liquidity-provision-dashboard-e2e
|
||||
- stats-e2e
|
||||
- token-e2e
|
||||
- trading-e2e
|
||||
tags:
|
||||
description: 'Test tags to run'
|
||||
required: true
|
||||
type: string
|
||||
default: '@smoke, @regression, @slow'
|
||||
skip-nx-cache:
|
||||
description: 'Add --skip-nx-cache to cypress test'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
env:
|
||||
GOBIN: /home/runner/go/bin
|
||||
VEGA_VERSION: 'v0.62.1'
|
||||
|
||||
jobs:
|
||||
manual:
|
||||
name: Run Cypress tests -- manual trigger
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set tags
|
||||
run: echo TAGS="--env.grepTags '[ ${{ github.event.inputs.tags }} ]'" >> $GITHUB_ENV
|
||||
|
||||
- name: Set --skip-nx-cache flag
|
||||
if: ${{ github.event.inputs.skip-nx-cache == 'true' }}
|
||||
run: echo SKIP_NX_CACHE="--skip-nx-cache" >> $GITHUB_ENV
|
||||
|
||||
outputs:
|
||||
vega-version: ${{env.VEGA_VERSION}}
|
||||
gobin: ${{env.GOBIN}}
|
||||
skip-cache: ${{env.SKIP_NX_CACHE}}
|
||||
tags: ${{env.TAGS}}
|
||||
|
||||
dispatch:
|
||||
needs: manual
|
||||
uses: ./.github/workflows/tests-dispatcher.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
project: ${{ inputs.project }}
|
||||
vega-version: ${{needs.manual.outputs.vega-version}}
|
||||
gobin: ${{needs.manual.outputs.gobin}}
|
||||
skip-cache: ${{needs.manual.outputs.skip-cache}}
|
||||
tags: ${{needs.manual.outputs.tags}}
|
||||
@@ -1,19 +0,0 @@
|
||||
name: Cypress tests -- night run
|
||||
|
||||
# This workflow runs the frontend tests against latest develop of the core to preempt breaking changes
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 4 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
nightly:
|
||||
uses: ./.github/workflows/tests-dispatcher.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
project: '[console-lite-e2e, explorer-e2e, liquidity-provision-dashboard-e2e, stats-e2e, token-e2e, trading-e2e]'
|
||||
vega-version: 'v0.62.1'
|
||||
gobin: /home/runner/go/bin
|
||||
tags: --env.grepTags '[ @smoke, @regression, @slow ]'
|
||||
night-run: true
|
||||
@@ -1,70 +0,0 @@
|
||||
name: Cypress tests - PR
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- main
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
|
||||
env:
|
||||
GOBIN: /home/runner/go/bin
|
||||
VEGA_VERSION: 'v0.62.1'
|
||||
|
||||
jobs:
|
||||
pr:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout front ends
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
frontend-monorepo/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
# Check SHAs
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v2
|
||||
with:
|
||||
working-directory: frontend-monorepo
|
||||
main-branch-name: ${{ github.base_ref || github.ref_name }}
|
||||
set-environment-variables-for-job: true
|
||||
|
||||
# See affected projects
|
||||
- name: See affected apps
|
||||
run: echo AFFECTED=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects) >> $GITHUB_ENV
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
outputs:
|
||||
projects: ${{ env.AFFECTED }}
|
||||
vega-version: ${{ env.VEGA_VERSION }}
|
||||
gobin: ${{ env.GOBIN }}
|
||||
|
||||
dispatch:
|
||||
needs: pr
|
||||
uses: ./.github/workflows/tests-dispatcher.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
project: ${{ needs.pr.outputs.projects }}
|
||||
vega-version: ${{needs.pr.outputs.vega-version}}
|
||||
gobin: ${{needs.pr.outputs.gobin}}
|
||||
tags: "--env.grepTags='@smoke'"
|
||||
@@ -1,85 +0,0 @@
|
||||
name: Cypress - console-lite
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
trigger:
|
||||
required: true
|
||||
type: string
|
||||
default: 'false'
|
||||
vega-version:
|
||||
required: true
|
||||
type: string
|
||||
gobin:
|
||||
required: false
|
||||
type: string
|
||||
default: /home/runner/go/bin
|
||||
skip-cache:
|
||||
required: false
|
||||
type: string
|
||||
tags:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
console-lite-e2e:
|
||||
if: ${{ inputs.trigger == 'true' }}
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
# Add GOBIN to PATH
|
||||
- name: Add GOBIN to PATH
|
||||
run: echo ${{ inputs.gobin }} >> $GITHUB_PATH
|
||||
|
||||
# Checkout front ends
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
frontend-monorepo/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
#######
|
||||
## Build and run Vegacapsule network
|
||||
#######
|
||||
|
||||
- name: Install Vega binaries
|
||||
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
|
||||
with:
|
||||
version: ${{ inputs.vega-version }}
|
||||
gobin: ${{ inputs.gobin }}
|
||||
|
||||
######
|
||||
## Setup a Vega wallet for our user
|
||||
######
|
||||
|
||||
- name: Set up Vegawallet
|
||||
uses: ./frontend-monorepo/.github/actions/setup-vegawallet
|
||||
with:
|
||||
recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
|
||||
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
|
||||
|
||||
# To make sure that all Cypress binaries are installed properly
|
||||
- name: Install cypress bins
|
||||
run: yarn cypress install
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: npx nx run console-lite-e2e:e2e ${{ inputs.skip-cache }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ inputs.tags }}
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
|
||||
@@ -1,111 +0,0 @@
|
||||
name: Cypress - explorer
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
trigger:
|
||||
required: true
|
||||
type: string
|
||||
default: 'false'
|
||||
vega-version:
|
||||
required: true
|
||||
type: string
|
||||
gobin:
|
||||
required: false
|
||||
type: string
|
||||
default: /home/runner/go/bin
|
||||
skip-cache:
|
||||
required: false
|
||||
type: string
|
||||
tags:
|
||||
required: false
|
||||
type: string
|
||||
night-run:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
explorer-e2e:
|
||||
if: ${{ inputs.trigger == 'true' }}
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
# Add GOBIN to PATH
|
||||
- name: Add GOBIN to PATH
|
||||
run: echo ${{ inputs.gobin }} >> $GITHUB_PATH
|
||||
|
||||
# Checkout front ends
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
frontend-monorepo/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
#######
|
||||
## Build and run Vegacapsule network
|
||||
#######
|
||||
|
||||
- name: Install Vega binaries
|
||||
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
|
||||
with:
|
||||
version: ${{ inputs.vega-version }}
|
||||
gobin: ${{ inputs.gobin }}
|
||||
|
||||
- name: Build and run Vegacapsule network
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
with:
|
||||
github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
|
||||
######
|
||||
## Setup a Vega wallet for our user
|
||||
######
|
||||
|
||||
- name: Set up Vegawallet for docker
|
||||
uses: ./frontend-monorepo/.github/actions/setup-vegawallet-docker
|
||||
with:
|
||||
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
######
|
||||
|
||||
# To make sure that all Cypress binaries are installed properly
|
||||
- name: Install cypress bins
|
||||
run: yarn cypress install
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: npx nx run explorer-e2e:e2e ${{ inputs.skip-cache }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ inputs.tags }}
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
|
||||
CYPRESS_NIGHTLY_RUN: ${{ inputs.night-run }}
|
||||
|
||||
######
|
||||
## Upload logs
|
||||
######
|
||||
|
||||
- name: Logs
|
||||
run: vegacapsule network logs > vega-capsule-logs.txt
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: logs
|
||||
path: ./vega-capsule-logs.txt
|
||||
@@ -1,47 +0,0 @@
|
||||
name: Cypress - liquidity provision dashboard
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
trigger:
|
||||
required: true
|
||||
type: string
|
||||
default: 'false'
|
||||
|
||||
jobs:
|
||||
liquidity-provision-dashboard-e2e:
|
||||
timeout-minutes: 10
|
||||
if: ${{ inputs.trigger == 'true' }}
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
# Checkout front ends
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
frontend-monorepo/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
# To make sure that all Cypress binaries are installed properly
|
||||
- name: Install cypress bins
|
||||
run: yarn cypress install
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: npx nx run liquidity-provision-dashboard-e2e:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
@@ -18,6 +18,10 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Run Cypress tests
|
||||
uses: cypress-io/github-action@v4
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
name: Cypress tests -- manual trigger
|
||||
|
||||
# This workflow runs the frontend tests against chosen branch
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
project:
|
||||
description: 'Project'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- explorer-e2e
|
||||
- token-e2e
|
||||
- trading-e2e
|
||||
tags:
|
||||
description: 'Test tags to run'
|
||||
required: true
|
||||
type: string
|
||||
default: '@smoke @regression @slow'
|
||||
skip-nx-cache:
|
||||
description: 'Skip NX cache'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
jobs:
|
||||
manual:
|
||||
uses: ./.github/workflows/cypress-run.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
projects: '["${{inputs.project}}"]'
|
||||
skip-cache: ${{inputs.skip-nx-cache}}
|
||||
tags: ${{inputs.tags}}
|
||||
@@ -0,0 +1,14 @@
|
||||
name: Cypress tests -- night run
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 4 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
nightly:
|
||||
uses: ./.github/workflows/cypress-run.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
projects: '["explorer-e2e","token-e2e","trading-e2e"]'
|
||||
tags: '@smoke @regression @slow'
|
||||
@@ -0,0 +1,78 @@
|
||||
name: Cypress tests - PR
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- main
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
jobs:
|
||||
pr:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
|
||||
- name: Remove package.json & yarn.lock to avoid installing everything
|
||||
run: rm package.json yarn.lock
|
||||
|
||||
- name: Install nx
|
||||
run: yarn add nx
|
||||
|
||||
# Check SHAs
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v2
|
||||
with:
|
||||
main-branch-name: ${{ github.base_ref || github.ref_name }}
|
||||
set-environment-variables-for-job: true
|
||||
|
||||
# See affected apps
|
||||
- name: See affected apps
|
||||
run: |
|
||||
affected=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)
|
||||
echo -n "Affected projects: $affected"
|
||||
projects=""
|
||||
if [[ $affected == *"token"* ]]; then projects+='"token-e2e" '; fi
|
||||
if [[ $affected == *"trading"* ]]; then projects+='"trading-e2e" '; fi
|
||||
if [[ $affected == *"explorer"* ]]; then projects+='"explorer-e2e" '; fi
|
||||
if [[ -z "$projects" ]]; then projects+='"token-e2e" "trading-e2e" "explorer-e2e" '; fi
|
||||
projects=${projects%?}
|
||||
projects=[${projects// /,}]
|
||||
echo PROJECTS=$projects >> $GITHUB_ENV
|
||||
|
||||
outputs:
|
||||
projects: ${{ env.PROJECTS }}
|
||||
|
||||
run:
|
||||
needs: pr
|
||||
if: ${{ needs.pr.outputs.projects != '[]' }}
|
||||
uses: ./.github/workflows/cypress-run.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
projects: ${{ needs.pr.outputs.projects }}
|
||||
tags: '@smoke @regression'
|
||||
|
||||
# Report single result at the end, to avoid mess with required checks in PR
|
||||
result:
|
||||
if: ${{ always() }}
|
||||
needs: run
|
||||
runs-on: ubuntu-latest
|
||||
name: Cypress result
|
||||
steps:
|
||||
- run: |
|
||||
result="${{ needs.run.result }}"
|
||||
if [[ $result == "success" || $result == "skipped" ]]; then
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,93 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
projects:
|
||||
required: true
|
||||
type: string
|
||||
skip-cache:
|
||||
required: false
|
||||
type: boolean
|
||||
tags:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
project: ${{ fromJSON(inputs.projects) }}
|
||||
runs-on: self-hosted-runner
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
# Checks if skip cache was requested
|
||||
- name: Set skip-nx-cache flag
|
||||
if: ${{ inputs.skip-cache == true }}
|
||||
run: echo "SKIP_CACHE=--skip-nx-cache" >> $GITHUB_ENV
|
||||
|
||||
# Checkout front ends
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
frontend-monorepo/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock', 'frontend-monorepo/package.json') }}
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
# Make sure that all Cypress binaries are installed properly
|
||||
- name: Install cypress bins
|
||||
run: yarn cypress install
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
######
|
||||
## Setup Vegacapsule and Vega wallet
|
||||
######
|
||||
|
||||
- name: Run Vegacapsule network and Vega wallet
|
||||
id: setup-vega
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
|
||||
######
|
||||
## Run some 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 }}"
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}
|
||||
|
||||
######
|
||||
## Upload logs
|
||||
######
|
||||
|
||||
# Artifact path is not valid: /ganache-1/capsule-logscolletor.stderr-2022-12-22T10:20:30Z.log. Contains the following character: Colon :
|
||||
- name: Rename files to allow archive
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
while read -r file; do
|
||||
mv "${file}" "$(echo ${file} | sed 's|:|-|g')"
|
||||
done< <(find /home/runner/.vegacapsule/testnet/logs -type f)
|
||||
|
||||
- name: Print logs files
|
||||
if: ${{ always() }}
|
||||
run: ls -alsh /home/runner/.vegacapsule/testnet/logs/
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: logs-${{ matrix.project }}
|
||||
path: /home/runner/.vegacapsule/testnet/logs
|
||||
@@ -1,47 +0,0 @@
|
||||
name: Cypress - stats
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
trigger:
|
||||
required: true
|
||||
type: string
|
||||
default: 'false'
|
||||
|
||||
jobs:
|
||||
stats-e2e:
|
||||
runs-on: self-hosted
|
||||
if: ${{ inputs.trigger == 'true' }}
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
# Checkout front ends
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
frontend-monorepo/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
# To make sure that all Cypress binaries are installed properly
|
||||
- name: Install cypress bins
|
||||
run: yarn cypress install
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: npx nx run stats-e2e:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
@@ -1,106 +0,0 @@
|
||||
name: Cypress - token
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
trigger:
|
||||
required: true
|
||||
type: string
|
||||
default: 'false'
|
||||
vega-version:
|
||||
required: true
|
||||
type: string
|
||||
gobin:
|
||||
required: false
|
||||
type: string
|
||||
default: /home/runner/go/bin
|
||||
skip-cache:
|
||||
required: false
|
||||
type: string
|
||||
tags:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
token-e2e:
|
||||
if: ${{ inputs.trigger == 'true' }}
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
# Add GOBIN to PATH
|
||||
- name: Add GOBIN to PATH
|
||||
run: echo ${{ inputs.gobin }} >> $GITHUB_PATH
|
||||
|
||||
# Checkout front ends
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
frontend-monorepo/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
#######
|
||||
## Build and run Vegacapsule network
|
||||
#######
|
||||
|
||||
- name: Install Vega binaries
|
||||
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
|
||||
with:
|
||||
version: ${{ inputs.vega-version }}
|
||||
gobin: ${{ inputs.gobin }}
|
||||
|
||||
- name: Build and run Vegacapsule network
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
with:
|
||||
github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
|
||||
######
|
||||
## Setup a Vega wallet for our user
|
||||
######
|
||||
|
||||
- name: Set up Vegawallet for docker
|
||||
uses: ./frontend-monorepo/.github/actions/setup-vegawallet-docker
|
||||
with:
|
||||
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
######
|
||||
|
||||
# To make sure that all Cypress binaries are installed properly
|
||||
- name: Install cypress bins
|
||||
run: yarn cypress install
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: npx nx run token-e2e:e2e ${{ inputs.skip-cache }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ inputs.tags }}
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
|
||||
|
||||
######
|
||||
## Upload logs
|
||||
######
|
||||
|
||||
- name: Logs
|
||||
run: vegacapsule network logs > vega-capsule-logs.txt
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: logs
|
||||
path: ./vega-capsule-logs.txt
|
||||
@@ -1,86 +0,0 @@
|
||||
name: Cypress - trading
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
trigger:
|
||||
required: true
|
||||
type: string
|
||||
default: 'false'
|
||||
vega-version:
|
||||
required: true
|
||||
type: string
|
||||
gobin:
|
||||
required: false
|
||||
type: string
|
||||
default: /home/runner/go/bin
|
||||
skip-cache:
|
||||
required: false
|
||||
type: string
|
||||
tags:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
trading-e2e:
|
||||
if: ${{ inputs.trigger == 'true' }}
|
||||
timeout-minutes: 30
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
# Add GOBIN to PATH
|
||||
- name: Add GOBIN to PATH
|
||||
run: echo ${{ inputs.gobin }} >> $GITHUB_PATH
|
||||
|
||||
# Checkout front ends
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
frontend-monorepo/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
#######
|
||||
## Build and run Vegacapsule network
|
||||
#######
|
||||
|
||||
- name: Install Vega binaries
|
||||
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
|
||||
with:
|
||||
version: ${{ inputs.vega-version }}
|
||||
gobin: ${{ inputs.gobin }}
|
||||
|
||||
######
|
||||
## Setup a Vega wallet for our user
|
||||
######
|
||||
|
||||
- name: Set up Vegawallet
|
||||
uses: ./frontend-monorepo/.github/actions/setup-vegawallet
|
||||
with:
|
||||
recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
|
||||
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
|
||||
|
||||
# To make sure that all Cypress binaries are installed properly
|
||||
- name: Install cypress bins
|
||||
run: yarn cypress install
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: npx nx run trading-e2e:e2e ${{ inputs.skip-cache }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ inputs.tags }}
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
|
||||
@@ -8,14 +8,16 @@ jobs:
|
||||
lint_pr:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Use Node.js 16
|
||||
id: Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.14.0
|
||||
- name: Install commitlint cli and config
|
||||
run: npm install @commitlint/cli @commitlint/config-conventional
|
||||
- name: Create config
|
||||
run: echo "module.exports = {extends:['@commitlint/config-conventional']};" > commitlint.config.js
|
||||
- name: Install root dependencies
|
||||
run: yarn install
|
||||
- name: Check PR title
|
||||
run: echo "${{ github.event.pull_request.title }}" | npx commitlint
|
||||
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
|
||||
|
||||
@@ -4,7 +4,7 @@ name: Publish docker containers
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+-pre[0-9]+'
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+-*'
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
project:
|
||||
required: true
|
||||
type: string
|
||||
vega-version:
|
||||
required: true
|
||||
type: string
|
||||
gobin:
|
||||
required: false
|
||||
type: string
|
||||
default: /home/runner/go/bin
|
||||
skip-cache:
|
||||
required: false
|
||||
type: string
|
||||
tags:
|
||||
required: false
|
||||
type: string
|
||||
night-run:
|
||||
required: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
run-console-lite-e2e:
|
||||
uses: ./.github/workflows/cypress-console-lite-e2e.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
trigger: ${{ contains(inputs.project, 'console-lite-e2e') || contains(inputs.project, 'console-lite') }}
|
||||
vega-version: ${{ inputs.vega-version }}
|
||||
gobin: ${{ inputs.gobin }}
|
||||
skip-cache: ${{ inputs.skip-cache }}
|
||||
tags: ${{ inputs.tags }}
|
||||
|
||||
run-explorer-e2e:
|
||||
uses: ./.github/workflows/cypress-explorer-e2e.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
trigger: ${{ contains(inputs.project, 'explorer-e2e') || contains(inputs.project, 'explorer') }}
|
||||
vega-version: ${{ inputs.vega-version }}
|
||||
gobin: ${{ inputs.gobin }}
|
||||
skip-cache: ${{ inputs.skip-cache }}
|
||||
tags: ${{ inputs.tags }}
|
||||
night-run: ${{ inputs.night-run }}
|
||||
|
||||
run-liquidity-e2e:
|
||||
uses: ./.github/workflows/cypress-liquidity-provision-dashboard-e2e.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
trigger: ${{ contains(inputs.project, 'liquidity-provision-dashboard-e2e') || contains(inputs.project, 'liquidity-provision-dashboard') }}
|
||||
|
||||
run-stats-e2e:
|
||||
uses: ./.github/workflows/cypress-stats-e2e.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
trigger: ${{ contains(inputs.project, 'stats-e2e') || contains(inputs.project, 'stats') }}
|
||||
|
||||
run-token-e2e:
|
||||
uses: ./.github/workflows/cypress-token-e2e.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
trigger: ${{ contains(inputs.project, 'token-e2e') || contains(inputs.project, 'token') }}
|
||||
vega-version: ${{ inputs.vega-version }}
|
||||
gobin: ${{ inputs.gobin }}
|
||||
skip-cache: ${{ inputs.skip-cache }}
|
||||
tags: ${{ inputs.tags }}
|
||||
|
||||
run-trading-e2e:
|
||||
uses: ./.github/workflows/cypress-trading-e2e.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
trigger: ${{ contains(inputs.project, 'trading-e2e') || contains(inputs.project, 'trading') }}
|
||||
vega-version: ${{ inputs.vega-version }}
|
||||
gobin: ${{ inputs.gobin }}
|
||||
skip-cache: ${{ inputs.skip-cache }}
|
||||
tags: ${{ inputs.tags }}
|
||||
@@ -1 +1,2 @@
|
||||
* @vegaprotocol/frontend
|
||||
*.graphql @vegaprotocol/core
|
||||
|
||||
@@ -22,10 +22,6 @@ The utility dApp for interacting with the Vega token and using its' utility. Thi
|
||||
|
||||
The block explorer for the Vega network, showing details of raw chain states and the state of markets on the Vega network.
|
||||
|
||||
### [Stats](./apps/stats)
|
||||
|
||||
An application for the status of the Vega network. Showing block height and other network activity.
|
||||
|
||||
### [Static](./apps/static)
|
||||
|
||||
Hosting for static content being shared across apps, for example fonts.
|
||||
@@ -88,12 +84,12 @@ Run `nx test my-app` to execute the unit tests with [Jest](https://jestjs.io), o
|
||||
|
||||
### Using wallet
|
||||
|
||||
To run tests locally using your own wallets you can add the following environment variables to `cypress.json`
|
||||
To run tests locally using your own wallets make sure you have generated at least two public keys and update the following environment variables in `cypress.config.js` to match your wallet.
|
||||
|
||||
1. Change `TRADING_TEST_VEGA_WALLET_NAME` to your Vega wallet name
|
||||
2. Add `TRADING_TEST_VEGA_WALLET_PASSPHRASE` as your wallet passphrase
|
||||
3. Add `ETH_WALLET_MNEMONIC` as your Ethereum wallet mnemonic
|
||||
4. Use [vegawallet-dummy](https://github.com/vegaprotocol/vegawallet-dummy) to avoid being prompted in CLI during test execution.
|
||||
1. Set `VEGA_PUBLIC_KEY` and `TRUNCATED_VEGA_PUBLIC_KEY` to your first public key.
|
||||
2. Set `VEGA_PUBLIC_KEY2` and `TRUNCATED_VEGA_PUBLIC_KEY2` to your second public key.
|
||||
3. Set `TRADING_TEST_VEGA_WALLET_PASSPHRASE` as your wallet passphrase
|
||||
4. Add `ETH_WALLET_MNEMONIC` as your Ethereum wallet mnemonic
|
||||
|
||||
### Formatting
|
||||
|
||||
@@ -156,6 +152,23 @@ In order to run the bootstrap command to generate and start a new network, we mu
|
||||
vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl
|
||||
```
|
||||
|
||||
In order to setup and run vegawallet for e2e capsule tests, in a separate terminal window:
|
||||
|
||||
1. cd into `./vegacapsule`
|
||||
2. run:
|
||||
|
||||
```bash
|
||||
bash setup-vegawallet.sh
|
||||
```
|
||||
|
||||
3. copy generated `api-token` and paste the token into `CYPRESS_VEGA_WALLET_API_TOKEN` environment variable in either `apps/token-e2e/.env` or `apps/explorer-e2e/.env` depending on which project needs testing.
|
||||
|
||||
Note: The script is only needed if capsule was built for first time or fresh. To run existing wallet service for capsule:
|
||||
|
||||
```bash
|
||||
vega wallet service run -n DV --load-tokens --tokens-passphrase-file passphrase --no-version-check --automatic-consent --home ~/.vegacapsule/testnet/wallet
|
||||
```
|
||||
|
||||
# 📑 License
|
||||
|
||||
[MIT](./LICENSE)
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
CYPRESS_VEGA_ENV=STAGNET3
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": ["plugin:cypress/recommended", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
module.exports = defineConfig({
|
||||
projectId: 'et4snf',
|
||||
|
||||
e2e: {
|
||||
setupNodeEvents(on, config) {
|
||||
require('cypress-grep/src/plugin')(config);
|
||||
return config;
|
||||
},
|
||||
baseUrl: 'http://localhost:4200',
|
||||
fileServerFolder: '.',
|
||||
fixturesFolder: false,
|
||||
specPattern: './src/integration/*.ts',
|
||||
excludeSpecPattern: '**/*.js',
|
||||
modifyObstructiveCode: false,
|
||||
supportFile: './src/support/index.js',
|
||||
video: false,
|
||||
videoUploadOnPasses: false,
|
||||
videosFolder: '../../dist/cypress/apps/console-lite-e2e/videos',
|
||||
screenshotsFolder: '../../dist/cypress/apps/console-lite-e2e/screenshots',
|
||||
chromeWebSecurity: false,
|
||||
viewportWidth: 1440,
|
||||
viewportHeight: 900,
|
||||
},
|
||||
env: {
|
||||
TRADING_TEST_VEGA_WALLET_NAME: 'UI_Trading_Test',
|
||||
ETHEREUM_PROVIDER_URL:
|
||||
'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
||||
VEGA_PUBLIC_KEY:
|
||||
'47836c253520d2661bf5bed6339c0de08fd02cf5d4db0efee3b4373f20c7d278',
|
||||
VEGA_PUBLIC_KEY2:
|
||||
'1a18cdcaaa4f44a57b35a4e9b77e0701c17a476f2b407620f8c17371740cf2e4',
|
||||
TRUNCATED_VEGA_PUBLIC_KEY: '47836c…c7d278',
|
||||
TRUNCATED_VEGA_PUBLIC_KEY2: '1a18cd…0cf2e4',
|
||||
ETHEREUM_WALLET_ADDRESS: '0x265Cc6d39a1B53d0d92068443009eE7410807158',
|
||||
ETHERSCAN_URL: 'https://sepolia.etherscan.io',
|
||||
tsConfig: 'tsconfig.json',
|
||||
TAGS: 'not @todo and not @ignore and not @manual',
|
||||
TRADING_TEST_VEGA_WALLET_PASSPHRASE: '123',
|
||||
ETH_WALLET_MNEMONIC:
|
||||
'ugly gallery notice network true range brave clarify flat logic someone chunk',
|
||||
grepTags: '@regression @smoke @slow',
|
||||
grepFilterSpecs: true,
|
||||
grepOmitFiltered: true,
|
||||
},
|
||||
});
|
||||
-1
@@ -1 +0,0 @@
|
||||
declare module '*.scss';
|
||||
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "apps/console-lite-e2e/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"e2e": {
|
||||
"executor": "@nrwl/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/console-lite-e2e/cypress.config.js",
|
||||
"devServerTarget": "console-lite:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "console-lite:serve:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/console-lite-e2e/**/*.{js,ts}"]
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"outputs": [],
|
||||
"options": {
|
||||
"command": "yarn tsc --project ./apps/console-lite-e2e/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"implicitDependencies": ["console-lite"]
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
generateSimpleMarkets,
|
||||
generateMarketsCandles,
|
||||
} from '../support/mocks/generate-markets';
|
||||
|
||||
describe('simple trading app', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
});
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
it('render', () => {
|
||||
cy.get('#root').should('exist');
|
||||
});
|
||||
});
|
||||
@@ -1,30 +0,0 @@
|
||||
describe('console lite header', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.setItem('theme', 'dark');
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
it('logo should linked home', () => {
|
||||
cy.get('span').contains('Markets').click();
|
||||
cy.location('pathname').should('eq', '/markets');
|
||||
cy.getByTestId('header').find('a').click();
|
||||
cy.location('pathname').should('eq', '/');
|
||||
});
|
||||
|
||||
it('theme switcher should switch theme', () => {
|
||||
cy.get('#root').children().eq(0).as('Container');
|
||||
cy.get('@Container').should('have.css', 'background-color', 'rgb(8, 8, 8)');
|
||||
cy.getByTestId('theme-switcher').click();
|
||||
cy.get('@Container').should(
|
||||
'have.css',
|
||||
'background-color',
|
||||
'rgb(255, 255, 255)'
|
||||
);
|
||||
});
|
||||
|
||||
it('wallet connector should open a dialog', () => {
|
||||
cy.get('[role="dialog"]').should('not.exist');
|
||||
cy.getByTestId('connect-vega-wallet').click();
|
||||
cy.get('[role="dialog"]').should('be.visible');
|
||||
});
|
||||
});
|
||||
@@ -1,137 +0,0 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import type { MarketsQuery } from '@vegaprotocol/market-list';
|
||||
import {
|
||||
generateLongListMarkets,
|
||||
generateSimpleMarkets,
|
||||
generateMarketsCandles,
|
||||
} from '../support/mocks/generate-markets';
|
||||
|
||||
describe('market list', { tags: '@smoke' }, () => {
|
||||
describe('simple url', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
});
|
||||
cy.visit('/markets');
|
||||
});
|
||||
|
||||
it('selects menus', () => {
|
||||
cy.get('[aria-label="Sidebar Navigation Menu"] [aria-current]').should(
|
||||
'have.text',
|
||||
'Markets'
|
||||
);
|
||||
cy.getByTestId('state-trigger').should('have.text', 'Active');
|
||||
cy.get('[aria-label="Future"]').click();
|
||||
cy.get('[data-testid="market-assets-menu"] a.active').should(
|
||||
'have.text',
|
||||
'All'
|
||||
);
|
||||
});
|
||||
|
||||
it('navigation should make possibly shortest url', () => {
|
||||
cy.location('pathname').should('equal', '/markets');
|
||||
|
||||
cy.getByTestId('state-trigger').click();
|
||||
cy.get('[role=menuitemcheckbox]').contains('All').click();
|
||||
cy.location('pathname').should('equal', '/markets/all');
|
||||
|
||||
cy.get('[aria-label="Future"]').click();
|
||||
cy.location('pathname').should('eq', '/markets/all/Future');
|
||||
let asset = '';
|
||||
cy.getByTestId('market-assets-menu')
|
||||
.children()
|
||||
.then((children) => {
|
||||
if (children.length > 1) {
|
||||
asset = children[1].innerText;
|
||||
if (asset) {
|
||||
cy.wrap(children[1]).click();
|
||||
cy.location('pathname').should(
|
||||
'match',
|
||||
new RegExp(`/markets/all/Future/${asset}`, 'i')
|
||||
);
|
||||
cy.get('a').contains('All Markets').click();
|
||||
cy.location('pathname').should('eq', '/markets/all');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cy.getByTestId('state-trigger').click();
|
||||
cy.get('[role=menuitemcheckbox]').contains('Active').click();
|
||||
cy.location('pathname').should('equal', '/markets');
|
||||
});
|
||||
});
|
||||
|
||||
describe('url params should select filters', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
});
|
||||
});
|
||||
|
||||
it('suspended status', () => {
|
||||
cy.visit('/markets/Suspended');
|
||||
cy.getByTestId('state-trigger').should('have.text', 'Suspended');
|
||||
});
|
||||
|
||||
it('last asset (if exists)', () => {
|
||||
cy.visit('/markets');
|
||||
cy.wait('@Markets').then((filters) => {
|
||||
const data: MarketsQuery | undefined = filters?.response?.body?.data;
|
||||
if (data?.marketsConnection?.edges.length) {
|
||||
const asset =
|
||||
data?.marketsConnection?.edges[0].node.tradableInstrument.instrument
|
||||
.product.settlementAsset.symbol;
|
||||
cy.visit(`/markets/Suspended/Future/${asset}`);
|
||||
cy.getByTestId('market-assets-menu')
|
||||
.find('a.active')
|
||||
.should('have.text', asset);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('Future product', () => {
|
||||
cy.visit('/markets/Suspended/Future');
|
||||
cy.getByTestId('market-products-menu')
|
||||
.find('a.active')
|
||||
.should('have.text', 'Future');
|
||||
});
|
||||
});
|
||||
|
||||
describe('long list of results should be handled properly', () => {
|
||||
it('handles 1000 markets', () => {
|
||||
cy.viewport(1440, 900);
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateLongListMarkets(1000));
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
});
|
||||
performance.mark('start-1k');
|
||||
cy.visit('/markets');
|
||||
cy.get('.ag-center-cols-container', { timeout: 50000 }).then(() => {
|
||||
performance.mark('end-1k');
|
||||
performance.measure('load-1k', 'start-1k', 'end-1k');
|
||||
const measure = performance.getEntriesByName('load-1k')[0];
|
||||
expect(measure.duration).lte(20000);
|
||||
cy.log(`Ag-grid 1k load took ${measure.duration} milliseconds.`);
|
||||
|
||||
cy.get('.ag-root').should('have.attr', 'aria-rowcount', '1001');
|
||||
cy.get('.ag-center-cols-container')
|
||||
.find('[role="row"]')
|
||||
.its('length')
|
||||
.then((length) => expect(length).to.be.closeTo(20, 3));
|
||||
cy.get('.ag-cell-label-container').eq(4).click();
|
||||
cy.get('body').then(($body) => {
|
||||
for (let i = 0; i < 15; i++) {
|
||||
cy.wrap($body).realPress('Tab', { pressDelay: 100 });
|
||||
}
|
||||
});
|
||||
cy.focused().parent('.ag-row').should('have.attr', 'row-index', '14');
|
||||
cy.get('.ag-center-cols-container')
|
||||
.find('[role="row"]')
|
||||
.its('length')
|
||||
.then((length) => expect(length).to.be.closeTo(26, 2));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,156 +0,0 @@
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
generateMarket,
|
||||
generateMarketData,
|
||||
generateMarketsCandles,
|
||||
generateMarketsData,
|
||||
generateSimpleMarkets,
|
||||
} from '../support/mocks/generate-markets';
|
||||
import { generateMarketTags } from '../support/mocks/generate-market-tags';
|
||||
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
|
||||
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
|
||||
import { generatePartyBalance } from '../support/mocks/generate-party-balance';
|
||||
import { generatePartyMarketData } from '../support/mocks/generate-party-market-data';
|
||||
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
|
||||
import { generateMarketNames } from '../support/mocks/generate-market-names';
|
||||
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
|
||||
import type { Market, MarketsQuery } from '@vegaprotocol/market-list';
|
||||
import { generateChainId } from '../support/mocks/generate-chain-id';
|
||||
import { generateStatistics } from '../support/mocks/generate-statistics';
|
||||
|
||||
describe('market selector', { tags: '@smoke' }, () => {
|
||||
let markets: Market[];
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Statistics', generateStatistics());
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'MarketData', generateMarketData());
|
||||
aliasQuery(req, 'Market', generateMarket());
|
||||
aliasQuery(req, 'MarketTags', generateMarketTags());
|
||||
aliasQuery(req, 'MarketPositions', generateMarketPositions());
|
||||
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
|
||||
aliasQuery(req, 'PartyBalance', generatePartyBalance());
|
||||
aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
|
||||
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
|
||||
aliasQuery(req, 'MarketNames', generateMarketNames());
|
||||
aliasQuery(req, 'MarketDepth', generateMarketDepth());
|
||||
});
|
||||
|
||||
cy.visit('/markets');
|
||||
cy.wait('@Markets').then((response) => {
|
||||
const data: MarketsQuery | undefined = response?.response?.body?.data;
|
||||
if (data?.marketsConnection?.edges.length) {
|
||||
markets = data?.marketsConnection?.edges.map((edge) => edge.node);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should be properly rendered', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('input[placeholder="Search"]').should(
|
||||
'have.value',
|
||||
markets[0].tradableInstrument.instrument.name
|
||||
);
|
||||
cy.getByTestId('arrow-button').click();
|
||||
cy.getByTestId('market-pane').should('be.visible');
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.first()
|
||||
.should('contain.text', markets[0].tradableInstrument.instrument.name);
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.first()
|
||||
.click();
|
||||
cy.getByTestId('market-pane').should('not.be.visible');
|
||||
}
|
||||
});
|
||||
|
||||
it('typing should change list', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('input[placeholder="Search"]').type('{backspace}');
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.should('have.length.at.least', 1);
|
||||
cy.get('input[placeholder="Search"]').clear();
|
||||
cy.get('input[placeholder="Search"]').type('aa');
|
||||
const filtered = markets.filter(
|
||||
(market) =>
|
||||
market.state === 'STATE_ACTIVE' &&
|
||||
market.tradableInstrument.instrument.name.match(/aa/i)
|
||||
);
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.should('have.length', filtered.length);
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.last()
|
||||
.click();
|
||||
cy.location('pathname').should(
|
||||
'eq',
|
||||
`/trading/${filtered[filtered.length - 1].id}`
|
||||
);
|
||||
cy.get('input[placeholder="Search"]').should(
|
||||
'have.value',
|
||||
filtered[filtered.length - 1].tradableInstrument.instrument.name
|
||||
);
|
||||
}
|
||||
});
|
||||
// constantly failing on ci
|
||||
it.skip('keyboard navigation should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('input[placeholder="Search"]').type('{backspace}');
|
||||
cy.get('input[placeholder="Search"]').clear();
|
||||
cy.focused().realPress('ArrowDown');
|
||||
cy.focused().should('contain.text', 'AAVEDAI Monthly');
|
||||
cy.focused().realPress('ArrowDown');
|
||||
cy.focused().should('contain.text', 'ETHBTC').realPress('Enter');
|
||||
cy.location('pathname').should('eq', '/trading/ethbtc-quaterly');
|
||||
|
||||
cy.get('input[placeholder="Search"]').type('{backspace}');
|
||||
cy.get('input[placeholder="Search"]').clear();
|
||||
cy.getByTestId('market-pane').should('be.visible');
|
||||
cy.get('body').realPress('ArrowDown');
|
||||
cy.get('body').realPress('Tab');
|
||||
cy.getByTestId('market-pane').should('not.be.visible');
|
||||
}
|
||||
});
|
||||
|
||||
it('mobile view', () => {
|
||||
if (markets?.length) {
|
||||
cy.viewport('iphone-xr');
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('[role="dialog"]').should('not.exist');
|
||||
cy.getByTestId('arrow-button').click();
|
||||
cy.get('[role="dialog"]').should('be.visible');
|
||||
cy.get('input[placeholder="Search"]').then((search) => {
|
||||
cy.wrap(search).clear();
|
||||
});
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.should('have.length', 9);
|
||||
cy.get('div[role="dialog"]').should('have.class', 'w-screen');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.get('input[placeholder="Search"]').should(
|
||||
'have.value',
|
||||
markets[0].tradableInstrument.instrument.name
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,331 +0,0 @@
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
generateSimpleMarkets,
|
||||
generateMarketsCandles,
|
||||
generateMarketsData,
|
||||
generateMarket,
|
||||
generateMarketData,
|
||||
} from '../support/mocks/generate-markets';
|
||||
import { generateMarketTags } from '../support/mocks/generate-market-tags';
|
||||
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
|
||||
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
|
||||
import { generatePartyBalance } from '../support/mocks/generate-party-balance';
|
||||
import { generatePartyMarketData } from '../support/mocks/generate-party-market-data';
|
||||
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
|
||||
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
|
||||
import type { MarketsQuery, Market } from '@vegaprotocol/market-list';
|
||||
import { generateChainId } from '../support/mocks/generate-chain-id';
|
||||
import { generateStatistics } from '../support/mocks/generate-statistics';
|
||||
|
||||
describe('Market trade', { tags: '@smoke' }, () => {
|
||||
let markets: Market[];
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Statistics', generateStatistics());
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketTags', generateMarketTags());
|
||||
aliasQuery(req, 'MarketPositions', generateMarketPositions());
|
||||
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
|
||||
aliasQuery(req, 'PartyBalance', generatePartyBalance());
|
||||
aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
|
||||
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
|
||||
aliasQuery(req, 'MarketDepth', generateMarketDepth());
|
||||
aliasQuery(req, 'Market', generateMarket());
|
||||
aliasQuery(req, 'MarketData', generateMarketData());
|
||||
});
|
||||
cy.visit('/markets');
|
||||
cy.wait('@Markets').then((response) => {
|
||||
const data: MarketsQuery | undefined = response?.response?.body?.data;
|
||||
if (data?.marketsConnection?.edges.length) {
|
||||
markets = data?.marketsConnection?.edges.map((edge) => edge.node);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should not display steps if wallet is disconnected', () => {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
cy.getByTestId('trading-connect-wallet')
|
||||
.find('h3')
|
||||
.should('have.text', 'Please connect your Vega wallet to make a trade');
|
||||
cy.getByTestId('trading-connect-wallet')
|
||||
.find('button')
|
||||
.should('have.text', 'Connect Vega wallet');
|
||||
cy.getByTestId('trading-connect-wallet')
|
||||
.find('a')
|
||||
.should('have.text', 'https://vega.xyz/wallet');
|
||||
});
|
||||
|
||||
it('side selector should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').should(
|
||||
'have.text',
|
||||
'Long'
|
||||
);
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').should(
|
||||
'have.text',
|
||||
'Short'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('side selector mobile view should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.viewport('iphone-xr');
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
connectVegaWallet();
|
||||
cy.getByTestId('next-button').scrollIntoView().click();
|
||||
|
||||
cy.get('button[aria-label="Open long position"]').should(
|
||||
'have.class',
|
||||
'selected'
|
||||
);
|
||||
cy.get('button[aria-label="Open short position"]').should(
|
||||
'not.have.class',
|
||||
'selected'
|
||||
);
|
||||
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('button[aria-label="Open long position"]').should(
|
||||
'not.have.class',
|
||||
'selected'
|
||||
);
|
||||
cy.get('button[aria-label="Open short position"]').should(
|
||||
'have.class',
|
||||
'selected'
|
||||
);
|
||||
cy.getByTestId('next-button').scrollIntoView().click();
|
||||
cy.get('#step-1-control').should(
|
||||
'contain.html',
|
||||
'aria-label="Selected value Short"'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('size slider should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[1].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('button')
|
||||
.should('have.text', '1');
|
||||
cy.get('#step-2-panel').find('[role="slider"]').type('{rightarrow}');
|
||||
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('button')
|
||||
.should('have.text', '2');
|
||||
}
|
||||
});
|
||||
|
||||
it('percentage selection should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[1].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('button')
|
||||
.should('have.text', '1');
|
||||
|
||||
cy.getByTestId('max-label').should('have.text', '21');
|
||||
|
||||
cy.getByTestId('percentage-selector')
|
||||
.find('button')
|
||||
.contains('Max')
|
||||
.click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('button')
|
||||
.should('have.text', '21');
|
||||
}
|
||||
});
|
||||
|
||||
it('size input should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[1].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('button')
|
||||
.should('have.text', '1');
|
||||
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('input')
|
||||
.type('{backspace}2');
|
||||
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('button')
|
||||
.should('have.text', '2');
|
||||
cy.get('button').contains('Max').click();
|
||||
}
|
||||
});
|
||||
|
||||
it('slippage value should be displayed', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[1].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('button').contains('Max').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dl')
|
||||
.eq(2)
|
||||
.find('dd')
|
||||
.should('have.text', '0.02%');
|
||||
}
|
||||
});
|
||||
|
||||
it('allow slippage value to be adjusted', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[1].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('button').contains('Max').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dl')
|
||||
.eq(2)
|
||||
.find('dd')
|
||||
.should('have.text', '0.02%');
|
||||
cy.get('#step-2-panel').find('dl').eq(2).find('button').click();
|
||||
cy.get('#input-order-slippage')
|
||||
.focus()
|
||||
.type('{backspace}{backspace}{backspace}1');
|
||||
|
||||
cy.getByTestId('slippage-dialog').find('button').click();
|
||||
|
||||
cy.get('#step-2-panel')
|
||||
.find('dl')
|
||||
.eq(2)
|
||||
.find('dd')
|
||||
.should('have.text', '1%');
|
||||
}
|
||||
});
|
||||
|
||||
it('notional position size should be present', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[1].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('button')
|
||||
.should('have.text', '1');
|
||||
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(0)
|
||||
.find('input')
|
||||
.type('{backspace}2');
|
||||
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dt')
|
||||
.eq(2)
|
||||
.should('have.text', 'Est. Position Size (tDAI)');
|
||||
cy.get('#step-2-panel').find('dd').eq(2).should('have.text', '197.86012');
|
||||
}
|
||||
});
|
||||
|
||||
it('total fees should be displayed', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[1].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-1-control [aria-label^="Selected value"]').click();
|
||||
cy.get('button[aria-label="Open short position"]').click();
|
||||
cy.get('#step-2-control').click();
|
||||
cy.get('#step-2-panel')
|
||||
.find('dt')
|
||||
.eq(3)
|
||||
.should('have.text', 'Est. Fees (tDAI)');
|
||||
cy.get('#step-2-panel')
|
||||
.find('dd')
|
||||
.eq(3)
|
||||
.should('have.text', '3.00 (3.03%)');
|
||||
}
|
||||
});
|
||||
|
||||
it('order review should display proper calculations', () => {
|
||||
if (markets?.length) {
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-3-control').click();
|
||||
|
||||
cy.getByTestId('review-trade')
|
||||
.get('#contracts_tooltip_trigger')
|
||||
.trigger('click')
|
||||
.realTouch();
|
||||
|
||||
cy.get('[data-radix-popper-content-wrapper]').contains(
|
||||
'The number of contracts determines'
|
||||
);
|
||||
cy.get('#step-3-panel').find('dd').eq(1).should('have.text', '1');
|
||||
|
||||
cy.get('#step-3-panel').find('dd').eq(2).should('have.text', '98.93006');
|
||||
|
||||
cy.get('#step-3-panel')
|
||||
.find('dd')
|
||||
.eq(3)
|
||||
.should('have.text', '3.00 (3.03%)');
|
||||
|
||||
cy.get('#step-3-panel').find('dd').eq(4).should('have.text', ' - ');
|
||||
|
||||
cy.getByTestId('place-order').should('be.enabled').click();
|
||||
}
|
||||
});
|
||||
|
||||
it('info tooltip on mobile view should work well', () => {
|
||||
if (markets?.length) {
|
||||
cy.viewport('iphone-xr');
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
connectVegaWallet();
|
||||
cy.get('#step-3-control').click();
|
||||
|
||||
// Start from the bottom tooltip to ensure the tooltip above
|
||||
// can be interacted with
|
||||
cy.getByTestId('review-trade').get('div.cursor-help').eq(1).realTouch();
|
||||
cy.get('[data-radix-popper-content-wrapper]').contains(
|
||||
'The notional size represents the position size'
|
||||
);
|
||||
|
||||
cy.getByTestId('review-trade')
|
||||
.get('#contracts_tooltip_trigger')
|
||||
.realTouch();
|
||||
cy.get('[data-radix-popper-content-wrapper]').contains(
|
||||
'The number of contracts determines'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,198 +0,0 @@
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
generatePositions,
|
||||
emptyPositions,
|
||||
generateMargins,
|
||||
} from '../support/mocks/generate-positions';
|
||||
import { generateAccounts } from '../support/mocks/generate-accounts';
|
||||
import { generateAssets } from '../support/mocks/generate-assets';
|
||||
import { generateOrders } from '../support/mocks/generate-orders';
|
||||
import { generateFills } from '../support/mocks/generate-fills';
|
||||
import {
|
||||
generateFillsMarkets,
|
||||
generateMarketsData,
|
||||
generatePositionsMarkets,
|
||||
} from '../support/mocks/generate-markets';
|
||||
import { generateChainId } from '../support/mocks/generate-chain-id';
|
||||
import { generateStatistics } from '../support/mocks/generate-statistics';
|
||||
|
||||
describe('Portfolio page - wallet', { tags: '@smoke' }, () => {
|
||||
it('button for wallet connect should work', () => {
|
||||
cy.visit('/');
|
||||
cy.get('[href="/portfolio"]').eq(0).click();
|
||||
cy.getByTestId('trading-connect-wallet').should('be.visible');
|
||||
connectVegaWallet();
|
||||
cy.getByTestId('trading-connect-wallet').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Portfolio page tabs', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Statistics', generateStatistics());
|
||||
aliasQuery(req, 'Positions', generatePositions());
|
||||
aliasQuery(req, 'Margins', generateMargins());
|
||||
aliasQuery(req, 'Markets', generatePositionsMarkets());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'Accounts', generateAccounts());
|
||||
aliasQuery(req, 'Assets', generateAssets());
|
||||
});
|
||||
});
|
||||
|
||||
it('certain tabs should exist', () => {
|
||||
cy.visit('/portfolio');
|
||||
connectVegaWallet();
|
||||
|
||||
cy.getByTestId('assets').click();
|
||||
cy.location('pathname').should('eq', '/portfolio/assets');
|
||||
|
||||
cy.getByTestId('positions').click();
|
||||
cy.location('pathname').should('eq', '/portfolio/positions');
|
||||
|
||||
cy.getByTestId('orders').click();
|
||||
cy.location('pathname').should('eq', '/portfolio/orders');
|
||||
|
||||
cy.getByTestId('fills').click();
|
||||
cy.location('pathname').should('eq', '/portfolio/fills');
|
||||
|
||||
cy.getByTestId('deposits').click();
|
||||
cy.location('pathname').should('eq', '/portfolio/deposits');
|
||||
});
|
||||
|
||||
describe('Assets view', () => {
|
||||
before(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Statistics', generateStatistics());
|
||||
aliasQuery(req, 'Positions', generatePositions());
|
||||
aliasQuery(req, 'Margins', generateMargins());
|
||||
aliasQuery(req, 'Markets', generatePositionsMarkets());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'Accounts', generateAccounts());
|
||||
aliasQuery(req, 'Assets', generateAssets());
|
||||
});
|
||||
cy.visit('/portfolio/assets');
|
||||
connectVegaWallet();
|
||||
});
|
||||
|
||||
it('data should be properly rendered', () => {
|
||||
cy.get('.ag-center-cols-container .ag-row').should('have.length', 3);
|
||||
cy.get(
|
||||
'.ag-center-cols-container [row-id="ACCOUNT_TYPE_GENERAL-asset-id-null"]'
|
||||
)
|
||||
.find('button')
|
||||
.click();
|
||||
cy.getByTestId('dialog-title').should(
|
||||
'have.text',
|
||||
'Asset details - tEURO'
|
||||
);
|
||||
cy.getByTestId('dialog-close').click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Positions view', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Statistics', generateStatistics());
|
||||
aliasQuery(req, 'Positions', generatePositions());
|
||||
aliasQuery(req, 'Accounts', generateAccounts());
|
||||
aliasQuery(req, 'Margins', generateMargins());
|
||||
aliasQuery(req, 'Markets', generatePositionsMarkets());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'Assets', generateAssets());
|
||||
});
|
||||
cy.visit('/portfolio/positions');
|
||||
connectVegaWallet();
|
||||
});
|
||||
|
||||
it('data should be properly rendered', () => {
|
||||
cy.get('.ag-center-cols-container .ag-row').should('have.length', 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Orders view', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Statistics', generateStatistics());
|
||||
aliasQuery(req, 'Orders', generateOrders());
|
||||
aliasQuery(req, 'Markets', generateFillsMarkets());
|
||||
});
|
||||
cy.visit('/portfolio/orders');
|
||||
connectVegaWallet();
|
||||
});
|
||||
|
||||
it('data should be properly rendered', () => {
|
||||
cy.get('.ag-center-cols-container .ag-row').should('have.length', 5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Fills view', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Statistics', generateStatistics());
|
||||
aliasQuery(req, 'Fills', generateFills());
|
||||
aliasQuery(req, 'Markets', generateFillsMarkets());
|
||||
});
|
||||
cy.visit('/portfolio/fills');
|
||||
connectVegaWallet();
|
||||
});
|
||||
|
||||
it('data should be properly rendered', () => {
|
||||
cy.get('.ag-center-cols-container .ag-row').should('have.length', 4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Empty views', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Statistics', generateStatistics());
|
||||
aliasQuery(req, 'Positions', emptyPositions());
|
||||
aliasQuery(req, 'Accounts', { party: null });
|
||||
aliasQuery(req, 'Orders', { party: null });
|
||||
aliasQuery(req, 'Fills', { party: null });
|
||||
aliasQuery(req, 'Markets', {
|
||||
marketsConnection: { edges: [], __typename: 'MarketConnection' },
|
||||
});
|
||||
aliasQuery(req, 'Assets', {
|
||||
assetsConnection: { edges: null, __typename: 'AssetsConnection' },
|
||||
});
|
||||
aliasQuery(req, 'Margins', generateMargins());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
});
|
||||
cy.visit('/portfolio');
|
||||
connectVegaWallet();
|
||||
});
|
||||
|
||||
it('"No data to display" should be always displayed', () => {
|
||||
cy.getByTestId('assets').click();
|
||||
cy.get('div.flex.items-center.justify-center').should(
|
||||
'contain.text',
|
||||
'No data to display'
|
||||
);
|
||||
|
||||
cy.getByTestId('positions').click();
|
||||
cy.get('div.flex.items-center.justify-center').should(
|
||||
'contain.text',
|
||||
'No data to display'
|
||||
);
|
||||
|
||||
cy.getByTestId('orders').click();
|
||||
cy.get('div.flex.items-center.justify-center').should(
|
||||
'contain.text',
|
||||
'No data to display'
|
||||
);
|
||||
|
||||
cy.getByTestId('fills').click();
|
||||
cy.get('div.flex.items-center.justify-center').should(
|
||||
'contain.text',
|
||||
'No data to display'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
@@ -1,36 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
import '@vegaprotocol/cypress';
|
||||
import 'cypress-real-events/support';
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
import registerCypressGrep from 'cypress-grep';
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
registerCypressGrep();
|
||||
|
||||
before(() => {
|
||||
// Mock chainId fetch which happens on every page for wallet connection
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', {
|
||||
statistics: {
|
||||
__typename: 'Statistics',
|
||||
chainId:
|
||||
Cypress.env('VEGA_ENV').toLowerCase() ||
|
||||
'vega-fairground-202210041151',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,156 +0,0 @@
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list';
|
||||
|
||||
export const protoCandles = [
|
||||
{ open: '9556163', close: '9587028', __typename: 'Candle' },
|
||||
{
|
||||
open: '9587028',
|
||||
close: '9769899',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9769899', close: '9586292', __typename: 'Candle' },
|
||||
{
|
||||
open: '9586292',
|
||||
close: '9261774',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9261773', close: '9236369', __typename: 'Candle' },
|
||||
{
|
||||
open: '9236369',
|
||||
close: '9226070',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9226077', close: '9233252', __typename: 'Candle' },
|
||||
{
|
||||
open: '9249854',
|
||||
close: '9333038',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9333038', close: '9410371', __typename: 'Candle' },
|
||||
{
|
||||
open: '9410371',
|
||||
close: '9626249',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9626247', close: '9493253', __typename: 'Candle' },
|
||||
{
|
||||
open: '9493253',
|
||||
close: '9309054',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9309054', close: '9378428', __typename: 'Candle' },
|
||||
{
|
||||
open: '9378428',
|
||||
close: '9352996',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9352996', close: '9451142', __typename: 'Candle' },
|
||||
{
|
||||
open: '9451142',
|
||||
close: '9691070',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9691071', close: '9622031', __typename: 'Candle' },
|
||||
{
|
||||
open: '9622034',
|
||||
close: '9519285',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9528904', close: '9671275', __typename: 'Candle' },
|
||||
{
|
||||
open: '9671275',
|
||||
close: '9988454',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9982457', close: '10085537', __typename: 'Candle' },
|
||||
{
|
||||
open: '10085537',
|
||||
close: '9967390',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{ open: '9967390', close: '9974844', __typename: 'Candle' },
|
||||
{
|
||||
open: '9974844',
|
||||
close: '9940706',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
];
|
||||
|
||||
export const protoMarket: Market = {
|
||||
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
marketTimestamps: {
|
||||
__typename: 'MarketTimestamps',
|
||||
close: '',
|
||||
open: '',
|
||||
},
|
||||
fees: {
|
||||
__typename: 'Fees',
|
||||
factors: {
|
||||
__typename: 'FeeFactors',
|
||||
makerFee: '',
|
||||
infrastructureFee: '',
|
||||
liquidityFee: '',
|
||||
},
|
||||
},
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
id: '',
|
||||
code: 'AAVEDAI.MF21',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:2839D9B2329C9E70',
|
||||
'base:AAVE',
|
||||
'quote:DAI',
|
||||
'class:fx/crypto',
|
||||
'monthly',
|
||||
'sector:defi',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'DAI',
|
||||
settlementAsset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
};
|
||||
|
||||
export const singleMarket: SingleMarketFieldsFragment = {
|
||||
...protoMarket,
|
||||
tradableInstrument: {
|
||||
...protoMarket.tradableInstrument,
|
||||
instrument: {
|
||||
...protoMarket.tradableInstrument.instrument,
|
||||
product: {
|
||||
...protoMarket.tradableInstrument.instrument.product,
|
||||
settlementAsset: {
|
||||
...protoMarket.tradableInstrument.instrument.product.settlementAsset,
|
||||
id: 'dai-id',
|
||||
name: 'DAI Name',
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
id: 'oid',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
depth: {
|
||||
__typename: 'MarketDepth',
|
||||
lastTrade: { price: '9893006', __typename: 'Trade' },
|
||||
},
|
||||
};
|
||||
@@ -1,95 +0,0 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { AccountsQuery } from '@vegaprotocol/accounts';
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateAccounts = (
|
||||
override?: PartialDeep<AccountsQuery>
|
||||
): AccountsQuery => {
|
||||
const defaultAccounts: AccountsQuery = {
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
accountsConnection: {
|
||||
__typename: 'AccountsConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
__typename: 'AccountBalance',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '100000000',
|
||||
market: null,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
__typename: 'AccountBalance',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '100000000',
|
||||
market: {
|
||||
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
|
||||
__typename: 'Market',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id-2',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
__typename: 'AccountBalance',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
balance: '1000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
__typename: 'AccountBalance',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
balance: '1000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id-2',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
__typename: 'AccountBalance',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '100000000',
|
||||
market: null,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-0',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
return merge(defaultAccounts, override);
|
||||
};
|
||||
@@ -1,120 +0,0 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { AssetsQuery } from '@vegaprotocol/assets';
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateAssets = (override?: PartialDeep<AssetsQuery>) => {
|
||||
const defaultAssets: AssetsQuery = {
|
||||
assetsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
name: 'Euro',
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4',
|
||||
lifetimeLimit: '1',
|
||||
withdrawThreshold: '2',
|
||||
},
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
infrastructureFeeAccount: {
|
||||
balance: '1',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
globalRewardPoolAccount: {
|
||||
balance: '2',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
takerFeeRewardAccount: {
|
||||
balance: '3',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
makerFeeRewardAccount: {
|
||||
balance: '4',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
lpFeeRewardAccount: {
|
||||
balance: '5',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
marketProposerRewardAccount: {
|
||||
balance: '6',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
name: 'DAI',
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4',
|
||||
lifetimeLimit: '1',
|
||||
withdrawThreshold: '2',
|
||||
},
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
infrastructureFeeAccount: {
|
||||
balance: '1',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
globalRewardPoolAccount: {
|
||||
balance: '2',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
takerFeeRewardAccount: {
|
||||
balance: '3',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
makerFeeRewardAccount: {
|
||||
balance: '4',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
lpFeeRewardAccount: {
|
||||
balance: '5',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
marketProposerRewardAccount: {
|
||||
balance: '6',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-0',
|
||||
symbol: 'AST0',
|
||||
decimals: 5,
|
||||
name: 'Asto',
|
||||
source: {
|
||||
__typename: 'BuiltinAsset',
|
||||
maxFaucetAmountMint: '3',
|
||||
},
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
infrastructureFeeAccount: {
|
||||
balance: '0',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
globalRewardPoolAccount: null,
|
||||
takerFeeRewardAccount: null,
|
||||
makerFeeRewardAccount: null,
|
||||
lpFeeRewardAccount: null,
|
||||
marketProposerRewardAccount: null,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
return merge(defaultAssets, override);
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
import type { ChainIdQuery } from '@vegaprotocol/react-helpers';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateChainId = (
|
||||
override?: PartialDeep<ChainIdQuery>
|
||||
): ChainIdQuery => {
|
||||
const defaultResult = {
|
||||
statistics: {
|
||||
__typename: 'Statistics',
|
||||
chainId: Cypress.env('VEGA_ENV').toLowerCase() || 'test-chain-id',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
export const generateEstimateOrder = () => {
|
||||
return {
|
||||
estimateOrder: {
|
||||
fee: {
|
||||
__typename: 'TradeFee',
|
||||
makerFee: '100000',
|
||||
liquidityFee: '100000',
|
||||
infrastructureFee: '100000',
|
||||
},
|
||||
marginLevels: {
|
||||
initialLevel: '2844054.80937741220203',
|
||||
__typename: 'MarginLevels',
|
||||
},
|
||||
__typename: 'OrderEstimate',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,111 +0,0 @@
|
||||
import type { FillsQuery, FillFieldsFragment } from '@vegaprotocol/fills';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateFills = (
|
||||
override?: PartialDeep<FillsQuery>
|
||||
): FillsQuery => {
|
||||
const fills: FillFieldsFragment[] = [
|
||||
generateFill({
|
||||
buyer: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
},
|
||||
}),
|
||||
generateFill({
|
||||
id: '1',
|
||||
seller: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
},
|
||||
aggressor: Schema.Side.SIDE_SELL,
|
||||
buyerFee: {
|
||||
infrastructureFee: '5000',
|
||||
},
|
||||
market: {
|
||||
id: 'market-1',
|
||||
},
|
||||
}),
|
||||
generateFill({
|
||||
id: '2',
|
||||
seller: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
},
|
||||
aggressor: Schema.Side.SIDE_BUY,
|
||||
}),
|
||||
generateFill({
|
||||
id: '3',
|
||||
aggressor: Schema.Side.SIDE_SELL,
|
||||
market: {
|
||||
id: 'market-2',
|
||||
},
|
||||
buyer: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
const defaultResult: FillsQuery = {
|
||||
party: {
|
||||
id: 'buyer-id',
|
||||
tradesConnection: {
|
||||
__typename: 'TradeConnection',
|
||||
edges: fills.map((f) => {
|
||||
return {
|
||||
__typename: 'TradeEdge',
|
||||
node: f,
|
||||
cursor: '3',
|
||||
};
|
||||
}),
|
||||
pageInfo: {
|
||||
__typename: 'PageInfo',
|
||||
startCursor: '1',
|
||||
endCursor: '2',
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
},
|
||||
},
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
|
||||
export const generateFill = (override?: PartialDeep<FillFieldsFragment>) => {
|
||||
const defaultFill: FillFieldsFragment = {
|
||||
__typename: 'Trade',
|
||||
id: '0',
|
||||
createdAt: new Date().toISOString(),
|
||||
price: '10000000',
|
||||
size: '50000',
|
||||
buyOrder: 'buy-order',
|
||||
sellOrder: 'sell-order',
|
||||
aggressor: Schema.Side.SIDE_BUY,
|
||||
buyer: {
|
||||
__typename: 'Party',
|
||||
id: 'buyer-id',
|
||||
},
|
||||
seller: {
|
||||
__typename: 'Party',
|
||||
id: 'seller-id',
|
||||
},
|
||||
buyerFee: {
|
||||
__typename: 'TradeFee',
|
||||
makerFee: '100',
|
||||
infrastructureFee: '100',
|
||||
liquidityFee: '100',
|
||||
},
|
||||
sellerFee: {
|
||||
__typename: 'TradeFee',
|
||||
makerFee: '200',
|
||||
infrastructureFee: '200',
|
||||
liquidityFee: '200',
|
||||
},
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'market-0',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultFill, override);
|
||||
};
|
||||
@@ -1,210 +0,0 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
|
||||
import type { MarketDepthQuery } from '../../../../../libs/market-depth/src/lib/__generated___/MarketDepth';
|
||||
|
||||
export const generateMarketDepth = (
|
||||
override?: PartialDeep<MarketDepthQuery>
|
||||
): MarketDepthQuery => {
|
||||
const defaultResult: MarketDepthQuery = {
|
||||
market: {
|
||||
id: 'a46bd7e5277087723b7ab835844dec3cef8b4445738101269624bf5537d5d423',
|
||||
depth: {
|
||||
sell: [
|
||||
{
|
||||
price: '9893007',
|
||||
volume: '3',
|
||||
numberOfOrders: '3',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893010',
|
||||
volume: '4',
|
||||
numberOfOrders: '4',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893012',
|
||||
volume: '1',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893015',
|
||||
volume: '1',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893017',
|
||||
volume: '2',
|
||||
numberOfOrders: '2',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893021',
|
||||
volume: '4',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893025',
|
||||
volume: '5',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893125',
|
||||
volume: '4',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893135',
|
||||
volume: '2',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893165',
|
||||
volume: '5',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893175',
|
||||
volume: '3',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893185',
|
||||
volume: '3',
|
||||
numberOfOrders: '3',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9894185',
|
||||
volume: '1',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9894585',
|
||||
volume: '1',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9895585',
|
||||
volume: '4',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9896585',
|
||||
volume: '2',
|
||||
numberOfOrders: '2',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
],
|
||||
buy: [
|
||||
{
|
||||
price: '9893005',
|
||||
volume: '4',
|
||||
numberOfOrders: '3',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893003',
|
||||
volume: '2',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9893001',
|
||||
volume: '1',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9892006',
|
||||
volume: '3',
|
||||
numberOfOrders: '2',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9891006',
|
||||
volume: '2',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9891001',
|
||||
volume: '1',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890101',
|
||||
volume: '2',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890091',
|
||||
volume: '5',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890081',
|
||||
volume: '4',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890050',
|
||||
volume: '2',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890040',
|
||||
volume: '6',
|
||||
numberOfOrders: '3',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890030',
|
||||
volume: '6',
|
||||
numberOfOrders: '2',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890021',
|
||||
volume: '3',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890011',
|
||||
volume: '1',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
{
|
||||
price: '9890001',
|
||||
volume: '11',
|
||||
numberOfOrders: '1',
|
||||
__typename: 'PriceLevel',
|
||||
},
|
||||
],
|
||||
sequenceNumber: '1661773865550746910',
|
||||
__typename: 'MarketDepth',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
export const generateMarketMarkPrice = () => {
|
||||
return {
|
||||
market: {
|
||||
decimalPlaces: 5,
|
||||
data: { markPrice: '692748', __typename: 'MarketData' },
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,136 +0,0 @@
|
||||
import { protoMarket } from './commons';
|
||||
|
||||
export const generateMarketNames = () => {
|
||||
return {
|
||||
markets: [
|
||||
{ ...protoMarket },
|
||||
{
|
||||
id: '1d7ddf67dac4924db03f5bf58571a7bcb1908d70c66580467717aabc5345b68a',
|
||||
state: 'STATE_SUSPENDED',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'AAPL.MF21',
|
||||
name: 'Apple Monthly (30 Jun 2022)',
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:4899E01009F1A721',
|
||||
'quote:USD',
|
||||
'ticker:AAPL',
|
||||
'class:equities/single-stock-futures',
|
||||
'sector:tech',
|
||||
'listing_venue:NASDAQ',
|
||||
'country:US',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
product: { quoteName: 'USD', __typename: 'Future' },
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
{
|
||||
id: '87ae87cd3244fc1fab4b0e2dad2437879864192bb969f3109b69293421644c8b',
|
||||
state: 'STATE_SUSPENDED',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'TSLA.QM21',
|
||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:5A86B190C384997F',
|
||||
'quote:EURO',
|
||||
'ticker:TSLA',
|
||||
'class:equities/single-stock-futures',
|
||||
'sector:tech',
|
||||
'listing_venue:NASDAQ',
|
||||
'country:US',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
product: { quoteName: 'EURO', __typename: 'Future' },
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
{
|
||||
id: '69205712a854f1bbfb69fa3d11b60e01a1e249bafb5ece88115e7451e8ef07b3',
|
||||
state: 'STATE_SUSPENDED',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'BTCUSD.MF21',
|
||||
name: 'BTCUSD Monthly (30 Jun 2022)',
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:076BB86A5AA41E3E',
|
||||
'base:BTC',
|
||||
'quote:USD',
|
||||
'class:fx/crypto',
|
||||
'monthly',
|
||||
'sector:crypto',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
product: { quoteName: 'USD', __typename: 'Future' },
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
{
|
||||
id: 'ethbtc-quaterly',
|
||||
state: 'STATE_ACTIVE',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'ETHBTC.QM21',
|
||||
name: 'ETHBTC Quarterly (30 Jun 2022)',
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:1F0BB6EB5703B099',
|
||||
'base:ETH',
|
||||
'quote:BTC',
|
||||
'class:fx/crypto',
|
||||
'quarterly',
|
||||
'sector:crypto',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
product: { quoteName: 'BTC', __typename: 'Future' },
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
{
|
||||
id: '3c62b2714c4332d1a689a5352bff090e6aabccfd6bd87ce018936b38372530c9',
|
||||
state: 'STATE_ACTIVE',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'UNIDAI.MF21',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:3C58ED2A4A6C5D7E',
|
||||
'base:UNI',
|
||||
'quote:DAI',
|
||||
'class:fx/crypto',
|
||||
'monthly',
|
||||
'sector:defi',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
product: { quoteName: 'DAI', __typename: 'Future' },
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,72 +0,0 @@
|
||||
import type { MarketPositionsQuery } from '@vegaprotocol/deal-ticket';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
|
||||
export const generateMarketPositions = (): MarketPositionsQuery => {
|
||||
return {
|
||||
party: {
|
||||
id: '2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
|
||||
accountsConnection: {
|
||||
__typename: 'AccountsConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
__typename: 'AccountBalance',
|
||||
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
decimals: 5,
|
||||
},
|
||||
balance: '400000000000000000000',
|
||||
market: {
|
||||
id: '2751c508f9759761f912890f37fb3f97a00300bf7685c02a56a86e05facfe221',
|
||||
__typename: 'Market',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
type: Schema.AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
asset: {
|
||||
decimals: 5,
|
||||
},
|
||||
balance: '265329',
|
||||
market: {
|
||||
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
|
||||
__typename: 'Market',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
positionsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
openVolume: '3',
|
||||
market: {
|
||||
id: '2751c508f9759761f912890f37fb3f97a00300bf7685c02a56a86e05facfe221',
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Position',
|
||||
},
|
||||
__typename: 'PositionEdge',
|
||||
},
|
||||
{
|
||||
node: {
|
||||
openVolume: '12',
|
||||
market: {
|
||||
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Position',
|
||||
},
|
||||
__typename: 'PositionEdge',
|
||||
},
|
||||
],
|
||||
__typename: 'PositionConnection',
|
||||
},
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
export const generateMarketTags = () => {
|
||||
return {
|
||||
market: {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:2839D9B2329C9E70',
|
||||
'base:AAVE',
|
||||
'quote:DAI',
|
||||
'class:fx/crypto',
|
||||
'monthly',
|
||||
'sector:defi',
|
||||
'settlement:2022-08-01',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,143 +0,0 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { OrdersQuery, OrderFieldsFragment } from '@vegaprotocol/orders';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
|
||||
export const generateOrders = (
|
||||
override?: PartialDeep<OrdersQuery>
|
||||
): OrdersQuery => {
|
||||
const orders: OrderFieldsFragment[] = [
|
||||
{
|
||||
__typename: 'Order',
|
||||
id: '066468C06549101DAF7BC51099E1412A0067DC08C246B7D8013C9D0CBF1E8EE7',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'market-0',
|
||||
},
|
||||
size: '10',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status: Schema.OrderStatus.STATUS_FILLED,
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
remaining: '0',
|
||||
price: '20000000',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
createdAt: new Date(2020, 1, 30).toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Order',
|
||||
id: '48DB6767E4E4E0F649C5A13ABFADE39F8451C27DA828DAF14B7A1E8E5EBDAD99',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'market-1',
|
||||
},
|
||||
size: '1',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status: Schema.OrderStatus.STATUS_FILLED,
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
remaining: '0',
|
||||
price: '100',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
createdAt: new Date(2020, 1, 29).toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Order',
|
||||
id: '4e93702990712c41f6995fcbbd94f60bb372ad12d64dfa7d96d205c49f790336',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'market-2',
|
||||
},
|
||||
size: '1',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status: Schema.OrderStatus.STATUS_FILLED,
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
remaining: '0',
|
||||
price: '20000',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
createdAt: new Date(2020, 1, 28).toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Order',
|
||||
id: '94737d2bafafa4bc3b80a56ef084ae52a983b91aa067c31e243c61a0f962a836',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'market-3',
|
||||
},
|
||||
size: '1',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status: Schema.OrderStatus.STATUS_ACTIVE,
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
remaining: '0',
|
||||
price: '100000',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
createdAt: new Date(2020, 1, 27).toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Order',
|
||||
id: '94aead3ca92dc932efcb503631b03a410e2a5d4606cae6083e2406dc38e52f78',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'market-3',
|
||||
},
|
||||
size: '10',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status: Schema.OrderStatus.STATUS_PARTIALLY_FILLED,
|
||||
side: Schema.Side.SIDE_SELL,
|
||||
remaining: '3',
|
||||
price: '100000',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
createdAt: new Date(2020, 1, 27).toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
rejectionReason: null,
|
||||
},
|
||||
];
|
||||
|
||||
const defaultResult: OrdersQuery = {
|
||||
party: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
ordersConnection: {
|
||||
__typename: 'OrderConnection',
|
||||
edges: orders.map((f) => {
|
||||
return {
|
||||
__typename: 'OrderEdge',
|
||||
node: f,
|
||||
cursor: f.id,
|
||||
};
|
||||
}),
|
||||
pageInfo: {
|
||||
__typename: 'PageInfo',
|
||||
startCursor:
|
||||
'066468C06549101DAF7BC51099E1412A0067DC08C246B7D8013C9D0CBF1E8EE7',
|
||||
endCursor:
|
||||
'94737d2bafafa4bc3b80a56ef084ae52a983b91aa067c31e243c61a0f962a836',
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
},
|
||||
},
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
@@ -1,81 +0,0 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartyBalanceQuery } from '@vegaprotocol/deal-ticket';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
export const generatePartyBalance = (
|
||||
override?: PartialDeep<PartyBalanceQuery>
|
||||
): PartyBalanceQuery => {
|
||||
const defaultResult: PartyBalanceQuery = {
|
||||
party: {
|
||||
accountsConnection: {
|
||||
__typename: 'AccountsConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
balance: '88474051',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
id: 'dai-id',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
balance: '100000000',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
|
||||
symbol: 'tEURO',
|
||||
name: 'tEURO TEST',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
balance: '3412867',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
id: 'dai-id',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
balance: '70007',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
id: 'dai-id',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
import type { PartyMarketDataQuery } from '@vegaprotocol/deal-ticket';
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
export const generatePartyMarketData = (): PartyMarketDataQuery => {
|
||||
return {
|
||||
party: {
|
||||
id: '2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
|
||||
accountsConnection: {
|
||||
__typename: 'AccountsConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '1200000',
|
||||
asset: { id: 'fBTC', decimals: 5, __typename: 'Asset' },
|
||||
market: null,
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
__typename: 'AccountBalance',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '0.000000001',
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
decimals: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
marginsConnection: { edges: null, __typename: 'MarginConnection' },
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,145 +0,0 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
PositionsQuery,
|
||||
PositionFieldsFragment,
|
||||
MarginsQuery,
|
||||
} from '@vegaprotocol/positions';
|
||||
|
||||
export const generatePositions = (
|
||||
override?: PartialDeep<PositionsQuery>
|
||||
): PositionsQuery => {
|
||||
const nodes: PositionFieldsFragment[] = [
|
||||
{
|
||||
__typename: 'Position',
|
||||
realisedPNL: '0',
|
||||
openVolume: '6',
|
||||
unrealisedPNL: '895000',
|
||||
averageEntryPrice: '1129935',
|
||||
updatedAt: '2022-07-28T15:09:34.441143Z',
|
||||
market: {
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
__typename: 'Market',
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'Position',
|
||||
realisedPNL: '100',
|
||||
openVolume: '20',
|
||||
unrealisedPNL: '895000',
|
||||
averageEntryPrice: '8509338',
|
||||
updatedAt: '2022-07-28T15:09:34.441143Z',
|
||||
market: {
|
||||
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
|
||||
__typename: 'Market',
|
||||
},
|
||||
},
|
||||
{
|
||||
realisedPNL: '0',
|
||||
openVolume: '1',
|
||||
unrealisedPNL: '-22519',
|
||||
averageEntryPrice: '84400088',
|
||||
updatedAt: '2022-07-28T14:53:54.725477Z',
|
||||
market: {
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Position',
|
||||
},
|
||||
];
|
||||
|
||||
const defaultResult: PositionsQuery = {
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
positionsConnection: {
|
||||
__typename: 'PositionConnection',
|
||||
edges: nodes.map((node) => {
|
||||
return {
|
||||
__typename: 'PositionEdge',
|
||||
node,
|
||||
};
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
|
||||
export const emptyPositions = (): PositionsQuery => {
|
||||
return {
|
||||
party: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
positionsConnection: { edges: null, __typename: 'PositionConnection' },
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const generateMargins = (): MarginsQuery => {
|
||||
return {
|
||||
party: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
marginsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'tDAI-id',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'tDAI-id',
|
||||
},
|
||||
},
|
||||
__typename: 'MarginEdge',
|
||||
},
|
||||
{
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'tEURO-id',
|
||||
},
|
||||
},
|
||||
__typename: 'MarginEdge',
|
||||
},
|
||||
],
|
||||
__typename: 'MarginConnection',
|
||||
},
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
import type { StatisticsQuery } from '@vegaprotocol/environment';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateStatistics = (
|
||||
override?: PartialDeep<StatisticsQuery>
|
||||
): StatisticsQuery => {
|
||||
const defaultResult = {
|
||||
statistics: {
|
||||
__typename: 'Statistics',
|
||||
chainId: Cypress.env('VEGA_ENV').toLowerCase() || 'test-chain-id',
|
||||
blockHeight: '11',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
export const connectVegaWallet = () => {
|
||||
const form = 'rest-connector-form';
|
||||
const walletName = Cypress.env('TRADING_TEST_VEGA_WALLET_NAME');
|
||||
const walletPassphrase = Cypress.env('TRADING_TEST_VEGA_WALLET_PASSPHRASE');
|
||||
cy.getByTestId('connect-vega-wallet').click();
|
||||
cy.getByTestId('connectors-list')
|
||||
.find('[data-testid="connector-gui"]')
|
||||
.click();
|
||||
cy.getByTestId(form).find('#wallet').click().type(walletName);
|
||||
cy.getByTestId(form).find('#passphrase').click().type(walletPassphrase);
|
||||
cy.getByTestId('rest-connector-form').find('button[type=submit]').click();
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"jsx": "react-jsx",
|
||||
"sourceMap": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"allowJs": true,
|
||||
"types": ["cypress", "node", "cypress-real-events", "cypress-grep"]
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.js", "./declaration.d.ts"]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nrwl/react/babel",
|
||||
{
|
||||
"runtime": "automatic"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
# This file is used by:
|
||||
# 1. autoprefixer to adjust CSS to support the below specified browsers
|
||||
# 2. babel preset-env to adjust included polyfills
|
||||
#
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
#
|
||||
# If you need to support different browsers in production, you may tweak the list below.
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major version
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||
@@ -1,27 +0,0 @@
|
||||
# React Environment Variables
|
||||
# https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#expanding-environment-variables-in-env
|
||||
|
||||
# Netlify Environment Variables
|
||||
# https://www.netlify.com/docs/continuous-deployment/#environment-variables
|
||||
NX_VERSION=$npm_package_version
|
||||
NX_REPOSITORY_URL=$REPOSITORY_URL
|
||||
NX_BRANCH=$BRANCH
|
||||
NX_PULL_REQUEST=$PULL_REQUEST
|
||||
NX_HEAD=$HEAD
|
||||
NX_COMMIT_REF=$COMMIT_REF
|
||||
NX_CONTEXT=$CONTEXT
|
||||
NX_REVIEW_ID=$REVIEW_ID
|
||||
NX_INCOMING_HOOK_TITLE=$INCOMING_HOOK_TITLE
|
||||
NX_INCOMING_HOOK_URL=$INCOMING_HOOK_URL
|
||||
NX_INCOMING_HOOK_BODY=$INCOMING_HOOK_BODY
|
||||
NX_URL=$URL
|
||||
NX_DEPLOY_URL=$DEPLOY_URL
|
||||
NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
|
||||
NX_VEGA_CONFIG_URL="https://static.vega.xyz/assets/stagnet3-network.json"
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_VEGA_URL="https://api.stagnet3.vega.xyz/graphql"
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_NETWORKS={"MAINNET":"https://alpha.console.vega.xyz"}
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
@@ -1,3 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_URL=http://localhost:3028/query
|
||||
NX_VEGA_ENV=LOCAL
|
||||
@@ -1,8 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
|
||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\"}
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||
@@ -1,8 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
|
||||
NX_VEGA_URL=https://api.vega.xyz/query
|
||||
NX_VEGA_ENV=MAINNET
|
||||
NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
||||
@@ -1,7 +0,0 @@
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
|
||||
NX_VEGA_URL=https://api.sandbox.vega.xyz/graphql
|
||||
NX_VEGA_ENV=SANDBOX
|
||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
|
||||
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
@@ -1,7 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
|
||||
@@ -1,8 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
NX_VEGA_URL=https://api.n12.testnet.vega.xyz/graphql
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "__generated__", "__generated___"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'console-lite',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest',
|
||||
'^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nrwl/next/babel'] }],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/apps/console-lite',
|
||||
setupFilesAfterEnv: ['./setup-tests.ts'],
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
@@ -1,10 +0,0 @@
|
||||
const { join } = require('path');
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {
|
||||
config: join(__dirname, 'tailwind.config.js'),
|
||||
},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
@@ -1,90 +0,0 @@
|
||||
{
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "apps/console-lite/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "./tools/executors/webpack:build",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
"compiler": "babel",
|
||||
"outputPath": "dist/apps/console-lite",
|
||||
"index": "apps/console-lite/src/index.html",
|
||||
"baseHref": "/",
|
||||
"main": "apps/console-lite/src/main.tsx",
|
||||
"polyfills": "apps/console-lite/src/polyfills.ts",
|
||||
"tsConfig": "apps/console-lite/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/console-lite/src/favicon.ico",
|
||||
"apps/console-lite/src/assets"
|
||||
],
|
||||
"styles": ["apps/console-lite/src/styles.scss"],
|
||||
"scripts": [],
|
||||
"webpackConfig": "@nrwl/react/plugins/webpack"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/console-lite/src/environments/environment.ts",
|
||||
"with": "apps/console-lite/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "./tools/executors/webpack:serve",
|
||||
"options": {
|
||||
"buildTarget": "console-lite:build:development",
|
||||
"hmr": true,
|
||||
"port": 4001
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "console-lite:build:production",
|
||||
"hmr": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/console-lite/**/*.{ts,tsx,js,jsx}"]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"outputs": ["coverage/apps/console-lite"],
|
||||
"options": {
|
||||
"jestConfig": "apps/console-lite/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
},
|
||||
"build-netlify": {
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"cp apps/console-lite/netlify.toml netlify.toml",
|
||||
"nx build console-lite"
|
||||
]
|
||||
}
|
||||
},
|
||||
"build-spec": {
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"outputs": [],
|
||||
"options": {
|
||||
"command": "yarn tsc --project ./apps/console-lite/tsconfig.spec.json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
|
||||
import {
|
||||
VegaConnectDialog,
|
||||
VegaManageDialog,
|
||||
VegaWalletProvider,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { Connectors } from './lib/vega-connectors';
|
||||
import '../styles.scss';
|
||||
import { AppLoader } from './components/app-loader';
|
||||
import Header from './components/header';
|
||||
import { Main } from './components/main';
|
||||
import LocalContext from './context/local-context';
|
||||
import useLocalValues from './hooks/use-local-values';
|
||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||
|
||||
function App() {
|
||||
const [theme, toggleTheme] = useThemeSwitcher();
|
||||
const localValues = useLocalValues(theme, toggleTheme);
|
||||
const {
|
||||
vegaWalletDialog,
|
||||
menu: { setMenuOpen },
|
||||
} = localValues;
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
setMenuOpen(false);
|
||||
}, [location, setMenuOpen]);
|
||||
|
||||
const cacheConfig: InMemoryCacheConfig = {
|
||||
typePolicies: {
|
||||
Market: {
|
||||
merge: true,
|
||||
},
|
||||
Party: {
|
||||
merge: true,
|
||||
},
|
||||
Query: {},
|
||||
Account: {
|
||||
keyFields: false,
|
||||
fields: {
|
||||
balanceFormatted: {},
|
||||
},
|
||||
},
|
||||
Node: {
|
||||
keyFields: false,
|
||||
},
|
||||
Instrument: {
|
||||
keyFields: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<EnvironmentProvider>
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<NetworkLoader cache={cacheConfig}>
|
||||
<VegaWalletProvider>
|
||||
<LocalContext.Provider value={localValues}>
|
||||
<AppLoader>
|
||||
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
|
||||
<Header />
|
||||
<Main />
|
||||
<VegaConnectDialog connectors={Connectors} />
|
||||
<VegaManageDialog
|
||||
dialogOpen={vegaWalletDialog.manage}
|
||||
setDialogOpen={vegaWalletDialog.setManage}
|
||||
/>
|
||||
</div>
|
||||
</AppLoader>
|
||||
</LocalContext.Provider>
|
||||
</VegaWalletProvider>
|
||||
</NetworkLoader>
|
||||
</ThemeContext.Provider>
|
||||
</EnvironmentProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,19 +0,0 @@
|
||||
import { useEagerConnect } from '@vegaprotocol/wallet';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Connectors } from '../../lib/vega-connectors';
|
||||
|
||||
interface AppLoaderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component to handle any app initialization, startup querys and other things
|
||||
* that must happen for it can be used
|
||||
*/
|
||||
export function AppLoader({ children }: AppLoaderProps) {
|
||||
// Get keys from vega wallet immediately
|
||||
useEagerConnect(Connectors);
|
||||
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <>{children}</>;
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
import React, {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import classNames from 'classnames';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||
import { ThemeContext, useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
GridOptions,
|
||||
GetRowIdParams,
|
||||
TabToNextCellParams,
|
||||
CellKeyDownEvent,
|
||||
FullWidthCellKeyDownEvent,
|
||||
IGetRowsParams,
|
||||
IDatasource,
|
||||
} from 'ag-grid-community';
|
||||
import { NO_DATA_MESSAGE } from '../../constants';
|
||||
import * as constants from '../simple-market-list/constants';
|
||||
|
||||
export interface GetRowsParams<T>
|
||||
extends Omit<IGetRowsParams, 'successCallback'> {
|
||||
successCallback(rowsThisBlock: T[], lastRow?: number): void;
|
||||
}
|
||||
|
||||
export interface Datasource<T> extends IDatasource {
|
||||
getRows(params: GetRowsParams<T>): void;
|
||||
}
|
||||
interface Props<T> extends GridOptions {
|
||||
rowData?: T[];
|
||||
datasource?: Datasource<T>;
|
||||
handleRowClicked?: (event: { data: T }) => void;
|
||||
components?: Record<string, unknown>;
|
||||
classNamesParam?: string | string[];
|
||||
}
|
||||
|
||||
const ConsoleLiteGrid = <T extends { id?: string }>(
|
||||
{ handleRowClicked, getRowId, classNamesParam, ...props }: Props<T>,
|
||||
ref?: React.Ref<AgGridReact>
|
||||
) => {
|
||||
const { isMobile, screenSize } = useScreenDimensions();
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const theme = useContext(ThemeContext);
|
||||
const handleOnGridReady = useCallback(() => {
|
||||
(
|
||||
(ref as React.RefObject<AgGridReact>) || gridRef
|
||||
).current?.api?.sizeColumnsToFit();
|
||||
}, [gridRef, ref]);
|
||||
const onTabToNextCell = useCallback((params: TabToNextCellParams) => {
|
||||
const {
|
||||
api,
|
||||
previousCellPosition: { rowIndex },
|
||||
} = params;
|
||||
const rowCount = api.getDisplayedRowCount();
|
||||
if (rowCount <= rowIndex + 1) {
|
||||
return null;
|
||||
}
|
||||
return { ...params.previousCellPosition, rowIndex: rowIndex + 1 };
|
||||
}, []);
|
||||
const getRowIdLocal = useCallback(({ data }: GetRowIdParams) => data.id, []);
|
||||
const onCellKeyDown = useCallback(
|
||||
(
|
||||
params: (CellKeyDownEvent | FullWidthCellKeyDownEvent) & {
|
||||
event: KeyboardEvent;
|
||||
}
|
||||
) => {
|
||||
const { event: { key = '' } = {}, data } = params;
|
||||
if (key === 'Enter') {
|
||||
handleRowClicked?.({ data });
|
||||
}
|
||||
},
|
||||
[handleRowClicked]
|
||||
);
|
||||
const shouldSuppressHorizontalScroll = useMemo(() => {
|
||||
return !isMobile && constants.LARGE_SCREENS.includes(screenSize);
|
||||
}, [isMobile, screenSize]);
|
||||
|
||||
return (
|
||||
<AgGrid
|
||||
className={classNames(classNamesParam)}
|
||||
rowHeight={60}
|
||||
customThemeParams={
|
||||
theme === 'dark'
|
||||
? constants.agGridDarkVariables
|
||||
: constants.agGridLightVariables
|
||||
}
|
||||
onGridReady={handleOnGridReady}
|
||||
onRowClicked={handleRowClicked}
|
||||
rowClass={isMobile ? 'mobile' : ''}
|
||||
rowClassRules={constants.ROW_CLASS_RULES}
|
||||
ref={ref || gridRef}
|
||||
overlayNoRowsTemplate={NO_DATA_MESSAGE}
|
||||
suppressContextMenu
|
||||
getRowId={getRowId || getRowIdLocal}
|
||||
suppressMovableColumns
|
||||
suppressRowTransform
|
||||
onCellKeyDown={onCellKeyDown}
|
||||
tabToNextCell={onTabToNextCell}
|
||||
suppressHorizontalScroll={shouldSuppressHorizontalScroll}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const ConsoleLiteGridForwarder = forwardRef(ConsoleLiteGrid) as <T>(
|
||||
p: Props<T> & { ref?: React.Ref<AgGridReact> }
|
||||
) => React.ReactElement;
|
||||
|
||||
export default ConsoleLiteGridForwarder;
|
||||
@@ -1 +0,0 @@
|
||||
export { default as ConsoleLiteGrid } from './console-lite-grid';
|
||||
@@ -1,11 +0,0 @@
|
||||
query MarketTags($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
query PartyBalanceQuery($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
accountsConnection {
|
||||
edges {
|
||||
node {
|
||||
type
|
||||
balance
|
||||
asset {
|
||||
id
|
||||
symbol
|
||||
name
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: MarketTags
|
||||
// ====================================================
|
||||
|
||||
export interface MarketTags_market_tradableInstrument_instrument_metadata {
|
||||
__typename: "InstrumentMetadata";
|
||||
/**
|
||||
* An arbitrary list of tags to associated to associate to the Instrument (string list)
|
||||
*/
|
||||
tags: string[] | null;
|
||||
}
|
||||
|
||||
export interface MarketTags_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Metadata for this instrument
|
||||
*/
|
||||
metadata: MarketTags_market_tradableInstrument_instrument_metadata;
|
||||
}
|
||||
|
||||
export interface MarketTags_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: MarketTags_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface MarketTags_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: MarketTags_market_tradableInstrument;
|
||||
}
|
||||
|
||||
export interface MarketTags {
|
||||
/**
|
||||
* An instrument that is trading on the Vega network
|
||||
*/
|
||||
market: MarketTags_market | null;
|
||||
}
|
||||
|
||||
export interface MarketTagsVariables {
|
||||
marketId: string;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type MarketTagsQueryVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type MarketTagsQuery = { __typename?: 'Query', market?: { __typename?: 'Market', tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null } } } } | null };
|
||||
|
||||
|
||||
export const MarketTagsDocument = gql`
|
||||
query MarketTags($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useMarketTagsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useMarketTagsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useMarketTagsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useMarketTagsQuery({
|
||||
* variables: {
|
||||
* marketId: // value for 'marketId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useMarketTagsQuery(baseOptions: Apollo.QueryHookOptions<MarketTagsQuery, MarketTagsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<MarketTagsQuery, MarketTagsQueryVariables>(MarketTagsDocument, options);
|
||||
}
|
||||
export function useMarketTagsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarketTagsQuery, MarketTagsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<MarketTagsQuery, MarketTagsQueryVariables>(MarketTagsDocument, options);
|
||||
}
|
||||
export type MarketTagsQueryHookResult = ReturnType<typeof useMarketTagsQuery>;
|
||||
export type MarketTagsLazyQueryHookResult = ReturnType<typeof useMarketTagsLazyQuery>;
|
||||
export type MarketTagsQueryResult = Apollo.QueryResult<MarketTagsQuery, MarketTagsQueryVariables>;
|
||||
@@ -1,61 +0,0 @@
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type PartyBalanceQueryQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type PartyBalanceQueryQuery = { __typename?: 'Query', party?: { __typename?: 'Party', accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number } } } | null> | null } | null } | null };
|
||||
|
||||
|
||||
export const PartyBalanceQueryDocument = gql`
|
||||
query PartyBalanceQuery($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
accountsConnection {
|
||||
edges {
|
||||
node {
|
||||
type
|
||||
balance
|
||||
asset {
|
||||
id
|
||||
symbol
|
||||
name
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __usePartyBalanceQueryQuery__
|
||||
*
|
||||
* To run a query within a React component, call `usePartyBalanceQueryQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `usePartyBalanceQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = usePartyBalanceQueryQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function usePartyBalanceQueryQuery(baseOptions: Apollo.QueryHookOptions<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>(PartyBalanceQueryDocument, options);
|
||||
}
|
||||
export function usePartyBalanceQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>(PartyBalanceQueryDocument, options);
|
||||
}
|
||||
export type PartyBalanceQueryQueryHookResult = ReturnType<typeof usePartyBalanceQueryQuery>;
|
||||
export type PartyBalanceQueryLazyQueryHookResult = ReturnType<typeof usePartyBalanceQueryLazyQuery>;
|
||||
export type PartyBalanceQueryQueryResult = Apollo.QueryResult<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>;
|
||||
@@ -1,36 +0,0 @@
|
||||
import React from 'react';
|
||||
import Video from '../header/video';
|
||||
import Comet from '../header/comet';
|
||||
import Star from '../icons/star';
|
||||
|
||||
const Baubles = () => {
|
||||
return (
|
||||
<aside className="relative right-0 top-0 h-[700px] hidden md:block md:w-1/2 overflow-hidden">
|
||||
<div className="absolute top-[100px] w-[393px] left-[19%] h-[517px]">
|
||||
<div className="absolute top-[82px] right-[34px] w-[100px] h-[100px] clip-path-rounded">
|
||||
<Video />
|
||||
</div>
|
||||
<div className="absolute bottom-[100px] left-[59px] w-[200px] h-[200px] clip-path-rounded">
|
||||
<Video />
|
||||
</div>
|
||||
<div className="absolute w-[118px] h-[85px] right-0 bottom-[178px]">
|
||||
<Comet />
|
||||
</div>
|
||||
<div className="absolute w-[118px] h-[82px] left-0 bottom-[120px]">
|
||||
<Comet />
|
||||
</div>
|
||||
<div className="absolute w-[20px] h-[20px] top-0 left-[49px]">
|
||||
<Star />
|
||||
</div>
|
||||
<div className="absolute w-[20px] h-[20px] top-[89px] left-[184px]">
|
||||
<Star />
|
||||
</div>
|
||||
<div className="absolute w-[10px] h-[10px] bottom-0 right-[137px]">
|
||||
<Star />
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default Baubles;
|
||||
@@ -1,65 +0,0 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import type { AccountFragment } from '@vegaprotocol/deal-ticket';
|
||||
import { DealTicketBalance } from './deal-ticket-balance';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { MarketDealTicketAsset } from '@vegaprotocol/market-list';
|
||||
|
||||
const tDAI: MarketDealTicketAsset = {
|
||||
__typename: 'Asset',
|
||||
id: '1',
|
||||
symbol: 'tDAI',
|
||||
name: 'TDAI',
|
||||
decimals: 2,
|
||||
};
|
||||
|
||||
const accounts: AccountFragment[] = [
|
||||
{
|
||||
__typename: 'AccountBalance',
|
||||
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '1000000',
|
||||
asset: tDAI,
|
||||
},
|
||||
];
|
||||
|
||||
describe('DealTicketBalance', function () {
|
||||
it('should render the balance', () => {
|
||||
const { getByText, getByRole } = render(
|
||||
<DealTicketBalance
|
||||
settlementAsset={tDAI}
|
||||
accounts={accounts}
|
||||
isWalletConnected
|
||||
/>
|
||||
);
|
||||
|
||||
expect(getByRole('complementary')).toHaveAccessibleName('tDAI Balance');
|
||||
expect(getByText('10,000.00')).toBeInTheDocument();
|
||||
expect(getByText('tDAI')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should prompt to connect wallet', () => {
|
||||
const { getByText } = render(
|
||||
<DealTicketBalance
|
||||
settlementAsset={tDAI}
|
||||
accounts={accounts}
|
||||
isWalletConnected={false}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(
|
||||
getByText('Please connect your Vega wallet to see your balance')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display zero balance', () => {
|
||||
const { getByText } = render(
|
||||
<DealTicketBalance
|
||||
settlementAsset={tDAI}
|
||||
accounts={[]}
|
||||
isWalletConnected={true}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(getByText('No tDAI left to trade')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,61 +0,0 @@
|
||||
import classNames from 'classnames';
|
||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { AccountFragment } from '@vegaprotocol/deal-ticket';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { useSettlementAccount } from '@vegaprotocol/deal-ticket';
|
||||
|
||||
interface DealTicketBalanceProps {
|
||||
settlementAsset: MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
accounts: AccountFragment[];
|
||||
isWalletConnected: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const DealTicketBalance = ({
|
||||
settlementAsset,
|
||||
accounts,
|
||||
isWalletConnected,
|
||||
className = '',
|
||||
}: DealTicketBalanceProps) => {
|
||||
const settlementAssetId = settlementAsset?.id;
|
||||
const settlementAssetSymbol = settlementAsset?.symbol;
|
||||
const settlementAccount = useSettlementAccount(
|
||||
settlementAssetId,
|
||||
accounts,
|
||||
Schema.AccountType.ACCOUNT_TYPE_GENERAL
|
||||
);
|
||||
const formattedNumber =
|
||||
settlementAccount?.balance &&
|
||||
settlementAccount.asset.decimals &&
|
||||
addDecimalsFormatNumber(
|
||||
settlementAccount.balance,
|
||||
settlementAccount.asset.decimals
|
||||
);
|
||||
|
||||
const balance = (
|
||||
<p className="text-blue text-lg font-semibold">
|
||||
{settlementAccount
|
||||
? t(`${formattedNumber}`)
|
||||
: `No ${settlementAssetSymbol} left to trade`}
|
||||
</p>
|
||||
);
|
||||
|
||||
const connectWallet = (
|
||||
<p>{t('Please connect your Vega wallet to see your balance')}</p>
|
||||
);
|
||||
|
||||
const ariaLabel = t(`${settlementAssetSymbol} Balance`);
|
||||
|
||||
return (
|
||||
<aside
|
||||
aria-label={ariaLabel}
|
||||
className={classNames('text-right', className)}
|
||||
>
|
||||
<div className="inline-block">
|
||||
<span className="text-blue">{settlementAssetSymbol}</span>
|
||||
{isWalletConnected ? balance : connectWallet}
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import compact from 'lodash/compact';
|
||||
import {
|
||||
DealTicketManager,
|
||||
usePartyBalanceQuery,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { DealTicketSteps } from './deal-ticket-steps';
|
||||
import { DealTicketBalance } from './deal-ticket-balance';
|
||||
import Baubles from './baubles-decor';
|
||||
import ConnectWallet from '../wallet-connector';
|
||||
import { useMemo } from 'react';
|
||||
import type {
|
||||
MarketDataUpdateFieldsFragment,
|
||||
MarketDealTicket,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { marketDealTicketProvider } from '@vegaprotocol/market-list';
|
||||
|
||||
const tempEmptyText = (
|
||||
<p>{t('Please select a market from the markets page')}</p>
|
||||
);
|
||||
|
||||
export const DealTicketContainer = () => {
|
||||
const { marketId } = useParams<{ marketId: string }>();
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
const { data: partyData } = usePartyBalanceQuery({
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId || '',
|
||||
}),
|
||||
[marketId]
|
||||
);
|
||||
const { data, loading } = useDataProvider<
|
||||
MarketDealTicket,
|
||||
MarketDataUpdateFieldsFragment
|
||||
>({
|
||||
dataProvider: marketDealTicketProvider,
|
||||
variables,
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
const accounts = compact(partyData?.party?.accountsConnection?.edges).map(
|
||||
(e) => e.node
|
||||
);
|
||||
|
||||
const loader = <Loader />;
|
||||
if (marketId && data) {
|
||||
const balance = (
|
||||
<DealTicketBalance
|
||||
className="mb-4"
|
||||
settlementAsset={
|
||||
data.tradableInstrument.instrument.product?.settlementAsset
|
||||
}
|
||||
accounts={accounts || []}
|
||||
isWalletConnected={!!pubKey}
|
||||
/>
|
||||
);
|
||||
|
||||
const container = (
|
||||
<DealTicketManager market={data}>
|
||||
{loading ? loader : balance}
|
||||
<DealTicketSteps market={data} />
|
||||
</DealTicketManager>
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="flex p-4 md:p-6">
|
||||
<section className="w-full md:w-1/2 md:min-w-[500px]">
|
||||
{pubKey ? container : <ConnectWallet />}
|
||||
</section>
|
||||
<Baubles />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
return marketId ? (
|
||||
<Splash>
|
||||
<p>{t('Could not load market')}</p>
|
||||
</Splash>
|
||||
) : (
|
||||
tempEmptyText
|
||||
);
|
||||
};
|
||||
@@ -1,149 +0,0 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
SliderRoot,
|
||||
SliderThumb,
|
||||
SliderTrack,
|
||||
SliderRange,
|
||||
FormGroup,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { InputSetter } from '../input-setter';
|
||||
|
||||
interface DealTicketSizeInputProps {
|
||||
step: number;
|
||||
min: number;
|
||||
max: number;
|
||||
value: number;
|
||||
onValueChange: (value: number) => void;
|
||||
positionDecimalPlaces: number;
|
||||
}
|
||||
|
||||
const getSizeLabel = (value: number): string => {
|
||||
const MIN_LABEL = 'Min';
|
||||
const MAX_LABEL = 'Max';
|
||||
if (value === 0) {
|
||||
return MIN_LABEL;
|
||||
} else if (value === 100) {
|
||||
return MAX_LABEL;
|
||||
}
|
||||
|
||||
return `${value}%`;
|
||||
};
|
||||
|
||||
export const DealTicketSizeInput = ({
|
||||
value,
|
||||
step,
|
||||
min,
|
||||
max,
|
||||
onValueChange,
|
||||
positionDecimalPlaces,
|
||||
}: DealTicketSizeInputProps) => {
|
||||
const sizeRatios = [0, 25, 50, 75, 100];
|
||||
const [inputValue, setInputValue] = useState(value);
|
||||
|
||||
const onInputValueChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
let value = parseFloat(event.target.value);
|
||||
const isLessThanMin = value < min;
|
||||
const isMoreThanMax = value > max;
|
||||
if (isLessThanMin) {
|
||||
value = min;
|
||||
} else if (isMoreThanMax) {
|
||||
value = max;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
onValueChange(value);
|
||||
}
|
||||
|
||||
setInputValue(value);
|
||||
},
|
||||
[min, max, onValueChange, setInputValue]
|
||||
);
|
||||
|
||||
const onButtonValueChange = (size: number) => {
|
||||
const newVal = new BigNumber(size)
|
||||
.decimalPlaces(positionDecimalPlaces)
|
||||
.toNumber();
|
||||
onValueChange(newVal);
|
||||
setInputValue(newVal);
|
||||
};
|
||||
|
||||
const onSliderValueChange = useCallback(
|
||||
(value: number[]) => {
|
||||
const val = value[0];
|
||||
setInputValue(val);
|
||||
onValueChange(val);
|
||||
},
|
||||
[onValueChange]
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between text-black dark:text-white mb-2">
|
||||
<span data-testid="min-label">{min}</span>
|
||||
<span data-testid="max-label">{max}</span>
|
||||
</div>
|
||||
<SliderRoot
|
||||
className="mb-2"
|
||||
value={[value]}
|
||||
onValueChange={onSliderValueChange}
|
||||
step={step}
|
||||
min={min}
|
||||
max={max}
|
||||
>
|
||||
<SliderTrack className="bg-lightGrey dark:bg-offBlack">
|
||||
<SliderRange className="!bg-black dark:!bg-white" />
|
||||
</SliderTrack>
|
||||
<SliderThumb />
|
||||
</SliderRoot>
|
||||
|
||||
<div
|
||||
data-testid="percentage-selector"
|
||||
className="flex w-full justify-between text-black dark:text-white mb-6"
|
||||
>
|
||||
{sizeRatios.map((size, index) => {
|
||||
const proportionalSize = size ? (size / 100) * max : min;
|
||||
return (
|
||||
<button
|
||||
className="no-underline hover:underline text-blue"
|
||||
onClick={() => onButtonValueChange(proportionalSize)}
|
||||
type="button"
|
||||
key={index}
|
||||
>
|
||||
{getSizeLabel(size)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<dl className="text-black dark:text-white">
|
||||
<div className="flex items-center justify-between">
|
||||
<dt>{t('Contracts')}</dt>
|
||||
<dd className="flex justify-end w-full">
|
||||
<FormGroup
|
||||
hideLabel={true}
|
||||
label="Enter Size"
|
||||
labelFor="trade-size-input"
|
||||
className="mb-1"
|
||||
>
|
||||
<InputSetter
|
||||
id="input-order-size-market"
|
||||
type="number"
|
||||
step={step}
|
||||
min={min}
|
||||
max={max}
|
||||
className="w-full"
|
||||
value={inputValue}
|
||||
onChange={onInputValueChange}
|
||||
>
|
||||
{inputValue}
|
||||
</InputSetter>
|
||||
</FormGroup>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
import { DealTicketEstimates } from '@vegaprotocol/deal-ticket';
|
||||
import { DealTicketSizeInput } from './deal-ticket-size-input';
|
||||
|
||||
interface DealTicketSizeProps {
|
||||
step: number;
|
||||
min: number;
|
||||
max: number;
|
||||
size: number;
|
||||
onSizeChange: (value: number) => void;
|
||||
name: string;
|
||||
quoteName: string;
|
||||
price: string;
|
||||
estCloseOut: string;
|
||||
estMargin: string;
|
||||
fees: string;
|
||||
positionDecimalPlaces: number;
|
||||
notionalSize: string;
|
||||
}
|
||||
|
||||
export const DealTicketSize = ({
|
||||
step,
|
||||
min,
|
||||
max,
|
||||
price,
|
||||
quoteName,
|
||||
size,
|
||||
onSizeChange,
|
||||
estCloseOut,
|
||||
positionDecimalPlaces,
|
||||
fees,
|
||||
notionalSize,
|
||||
}: DealTicketSizeProps) => {
|
||||
return max === 0 ? (
|
||||
<p>Not enough balance to trade</p>
|
||||
) : (
|
||||
<div>
|
||||
<DealTicketSizeInput
|
||||
step={step}
|
||||
min={min}
|
||||
max={max}
|
||||
value={size}
|
||||
onValueChange={onSizeChange}
|
||||
positionDecimalPlaces={positionDecimalPlaces}
|
||||
/>
|
||||
<DealTicketEstimates
|
||||
quoteName={quoteName}
|
||||
fees={fees}
|
||||
estCloseOut={estCloseOut}
|
||||
price={price}
|
||||
notionalSize={notionalSize}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,112 +0,0 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
Dialog,
|
||||
Icon,
|
||||
Intent,
|
||||
Tooltip,
|
||||
TrafficLight,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { InputSetter } from '../../components/input-setter';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import {
|
||||
DataTitle,
|
||||
ValueTooltipRow,
|
||||
EST_SLIPPAGE,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
|
||||
interface DealTicketSlippageProps {
|
||||
step?: number;
|
||||
min?: number;
|
||||
max?: number;
|
||||
value: number;
|
||||
onValueChange(value: number): void;
|
||||
}
|
||||
|
||||
export const DealTicketSlippage = ({
|
||||
value,
|
||||
step = 0.01,
|
||||
min = 0,
|
||||
max = 50,
|
||||
onValueChange,
|
||||
}: DealTicketSlippageProps) => {
|
||||
const [isDialogVisible, setIsDialogVisible] = useState(false);
|
||||
|
||||
const onChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = event.target.value;
|
||||
const numericValue = parseFloat(value);
|
||||
onValueChange(numericValue);
|
||||
},
|
||||
[onValueChange]
|
||||
);
|
||||
|
||||
const toggleDialog = useCallback(() => {
|
||||
setIsDialogVisible(!isDialogVisible);
|
||||
}, [isDialogVisible]);
|
||||
|
||||
const formLabel = (
|
||||
<label className="flex items-center mb-1">
|
||||
<span className="mr-1">{t('Adjust slippage tolerance')}</span>
|
||||
<Tooltip align="center" description={EST_SLIPPAGE}>
|
||||
<div className="cursor-help" tabIndex={-1}>
|
||||
<Icon
|
||||
name={IconNames.ISSUE}
|
||||
className="block rotate-180"
|
||||
ariaLabel={EST_SLIPPAGE}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</label>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog
|
||||
open={isDialogVisible}
|
||||
onChange={toggleDialog}
|
||||
intent={Intent.None}
|
||||
title={t('Transaction Settings')}
|
||||
>
|
||||
<div data-testid="slippage-dialog">
|
||||
{formLabel}
|
||||
<InputSetter
|
||||
id="input-order-slippage"
|
||||
isInputVisible
|
||||
hasError={!value}
|
||||
type="number"
|
||||
step={step}
|
||||
min={min}
|
||||
max={max}
|
||||
className="w-full"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
>
|
||||
{value}%
|
||||
</InputSetter>
|
||||
</div>
|
||||
</Dialog>
|
||||
<dl className="text-black dark:text-white">
|
||||
<div className="flex justify-between mb-2">
|
||||
<DataTitle>{t('Est. Price Impact / Slippage')}</DataTitle>
|
||||
<div className="flex">
|
||||
<div className="mr-1">
|
||||
<ValueTooltipRow description={EST_SLIPPAGE}>
|
||||
<TrafficLight value={value} q1={1} q2={5}>
|
||||
{value}%
|
||||
</TrafficLight>
|
||||
</ValueTooltipRow>
|
||||
</div>
|
||||
<button type="button" onClick={toggleDialog}>
|
||||
<Icon
|
||||
name={IconNames.COG}
|
||||
className="block rotate-180"
|
||||
ariaLabel={t('Override slippage value')}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dl>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,355 +0,0 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import compact from 'lodash/compact';
|
||||
import { Stepper } from '../stepper';
|
||||
import {
|
||||
getDefaultOrder,
|
||||
useOrderCloseOut,
|
||||
useOrderMargin,
|
||||
usePartyBalanceQuery,
|
||||
useMaximumPositionSize,
|
||||
useCalculateSlippage,
|
||||
validateAmount,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import { InputError } from '@vegaprotocol/ui-toolkit';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { MarketSelector } from '@vegaprotocol/deal-ticket';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
t,
|
||||
toDecimal,
|
||||
removeDecimal,
|
||||
addDecimalsFormatNumber,
|
||||
addDecimal,
|
||||
formatNumber,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
useOrderSubmit,
|
||||
getOrderDialogTitle,
|
||||
getOrderDialogIntent,
|
||||
getOrderDialogIcon,
|
||||
OrderFeedback,
|
||||
} from '@vegaprotocol/orders';
|
||||
import { DealTicketSize } from './deal-ticket-size';
|
||||
import MarketNameRenderer from '../simple-market-list/simple-market-renderer';
|
||||
import SideSelector, { SIDE_NAMES } from './side-selector';
|
||||
import ReviewTrade from './review-trade';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { DealTicketSlippage } from './deal-ticket-slippage';
|
||||
import { useOrderValidation } from './use-order-validation';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
interface DealTicketMarketProps {
|
||||
market: MarketDealTicket;
|
||||
}
|
||||
|
||||
export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
|
||||
const navigate = useNavigate();
|
||||
const setMarket = useCallback(
|
||||
(marketId: string) => {
|
||||
navigate(`/trading/${marketId}`);
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
watch,
|
||||
setValue,
|
||||
formState: { errors },
|
||||
} = useForm<OrderSubmissionBody['orderSubmission']>({
|
||||
mode: 'onChange',
|
||||
defaultValues: getDefaultOrder(market),
|
||||
});
|
||||
|
||||
const emptyString = ' - ';
|
||||
const step = toDecimal(market.positionDecimalPlaces);
|
||||
const order = watch();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { message: invalidText, isDisabled } = useOrderValidation({
|
||||
market,
|
||||
order,
|
||||
fieldErrors: errors,
|
||||
});
|
||||
const { submit, transaction, finalizedOrder, Dialog } = useOrderSubmit();
|
||||
|
||||
const { data: partyBalance } = usePartyBalanceQuery({
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
const accounts = compact(partyBalance?.party?.accountsConnection?.edges).map(
|
||||
(e) => e.node
|
||||
);
|
||||
const maxTrade = useMaximumPositionSize({
|
||||
partyId: pubKey || '',
|
||||
accounts: accounts,
|
||||
marketId: market.id,
|
||||
settlementAssetId:
|
||||
market.tradableInstrument.instrument.product.settlementAsset.id,
|
||||
price: market?.depth?.lastTrade?.price,
|
||||
order,
|
||||
});
|
||||
|
||||
const estCloseOut = useOrderCloseOut({
|
||||
order,
|
||||
market,
|
||||
partyData: partyBalance,
|
||||
});
|
||||
const slippage = useCalculateSlippage({ marketId: market.id, order });
|
||||
const [slippageValue, setSlippageValue] = useState(
|
||||
slippage ? parseFloat(slippage) : 0
|
||||
);
|
||||
const transactionStatus =
|
||||
transaction.status === VegaTxStatus.Requested ||
|
||||
transaction.status === VegaTxStatus.Pending
|
||||
? 'pending'
|
||||
: 'default';
|
||||
|
||||
useEffect(() => {
|
||||
setSlippageValue(slippage ? parseFloat(slippage) : 0);
|
||||
}, [slippage]);
|
||||
|
||||
const price = useMemo(() => {
|
||||
if (slippage && market?.depth?.lastTrade?.price) {
|
||||
const isLong = order.side === Schema.Side.SIDE_BUY;
|
||||
const multiplier = new BigNumber(1)[isLong ? 'plus' : 'minus'](
|
||||
parseFloat(slippage) / 100
|
||||
);
|
||||
return new BigNumber(market?.depth?.lastTrade?.price)
|
||||
.multipliedBy(multiplier)
|
||||
.toString();
|
||||
}
|
||||
return undefined;
|
||||
}, [market?.depth?.lastTrade?.price, order.side, slippage]);
|
||||
|
||||
const estMargin = useOrderMargin({
|
||||
order,
|
||||
market,
|
||||
partyId: pubKey || '',
|
||||
derivedPrice: price,
|
||||
});
|
||||
|
||||
const formattedPrice =
|
||||
price && addDecimalsFormatNumber(price, market.decimalPlaces);
|
||||
|
||||
const notionalSize = useMemo(() => {
|
||||
if (price) {
|
||||
const size = new BigNumber(price).multipliedBy(order.size).toNumber();
|
||||
|
||||
return addDecimalsFormatNumber(size, market.decimalPlaces);
|
||||
}
|
||||
return null;
|
||||
}, [market.decimalPlaces, order.size, price]);
|
||||
|
||||
const assetDecimals =
|
||||
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
||||
|
||||
const fees = useMemo(() => {
|
||||
if (estMargin?.totalFees && notionalSize) {
|
||||
const percentage = new BigNumber(estMargin?.totalFees)
|
||||
.dividedBy(notionalSize)
|
||||
.multipliedBy(100)
|
||||
.decimalPlaces(2)
|
||||
.toString();
|
||||
|
||||
return `${addDecimalsFormatNumber(
|
||||
estMargin.totalFees,
|
||||
assetDecimals
|
||||
)} (${formatNumber(addDecimal(percentage, assetDecimals), 2)}%)`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [assetDecimals, estMargin?.totalFees, notionalSize]);
|
||||
|
||||
const max = useMemo(() => {
|
||||
return new BigNumber(maxTrade)
|
||||
.decimalPlaces(market.positionDecimalPlaces)
|
||||
.toNumber();
|
||||
}, [market.positionDecimalPlaces, maxTrade]);
|
||||
|
||||
useEffect(() => {
|
||||
setSlippageValue(slippage ? parseFloat(slippage) : 0);
|
||||
}, [slippage]);
|
||||
|
||||
const onSizeChange = useCallback(
|
||||
(value: number) => {
|
||||
const newVal = new BigNumber(value)
|
||||
.decimalPlaces(market.positionDecimalPlaces)
|
||||
.toString();
|
||||
const isValid = validateAmount(step, 'Size')(newVal);
|
||||
if (isValid !== 'step') {
|
||||
setValue('size', newVal);
|
||||
}
|
||||
},
|
||||
[market.positionDecimalPlaces, setValue, step]
|
||||
);
|
||||
|
||||
const onSlippageChange = useCallback(
|
||||
(value: number) => {
|
||||
if (market?.depth?.lastTrade?.price) {
|
||||
if (value) {
|
||||
const isLong = order.side === Schema.Side.SIDE_BUY;
|
||||
const multiplier = new BigNumber(1)[isLong ? 'plus' : 'minus'](
|
||||
value / 100
|
||||
);
|
||||
const bestAskPrice = new BigNumber(market?.depth?.lastTrade?.price)
|
||||
.multipliedBy(multiplier)
|
||||
.decimalPlaces(market.decimalPlaces)
|
||||
.toString();
|
||||
|
||||
setValue('price', bestAskPrice);
|
||||
|
||||
if (order.type === Schema.OrderType.TYPE_MARKET) {
|
||||
setValue('type', Schema.OrderType.TYPE_LIMIT);
|
||||
}
|
||||
} else {
|
||||
setValue('type', Schema.OrderType.TYPE_MARKET);
|
||||
setValue('price', market?.depth?.lastTrade?.price);
|
||||
}
|
||||
}
|
||||
setSlippageValue(value);
|
||||
},
|
||||
[
|
||||
market.decimalPlaces,
|
||||
market?.depth?.lastTrade?.price,
|
||||
order.side,
|
||||
order.type,
|
||||
setSlippageValue,
|
||||
setValue,
|
||||
]
|
||||
);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
(order: OrderSubmissionBody['orderSubmission']) => {
|
||||
if (transactionStatus !== 'pending') {
|
||||
submit({
|
||||
...order,
|
||||
price:
|
||||
order.price && removeDecimal(order.price, market.decimalPlaces),
|
||||
size: removeDecimal(order.size, market.positionDecimalPlaces),
|
||||
});
|
||||
}
|
||||
},
|
||||
[
|
||||
transactionStatus,
|
||||
submit,
|
||||
market.decimalPlaces,
|
||||
market.positionDecimalPlaces,
|
||||
]
|
||||
);
|
||||
|
||||
const steps = [
|
||||
{
|
||||
label: t('Select Market'),
|
||||
component: (
|
||||
<MarketSelector
|
||||
market={market}
|
||||
setMarket={setMarket}
|
||||
ItemRenderer={MarketNameRenderer}
|
||||
/>
|
||||
),
|
||||
value: market.tradableInstrument.instrument.name,
|
||||
},
|
||||
{
|
||||
label: t('Select Direction'),
|
||||
component: (
|
||||
<Controller
|
||||
name="side"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<SideSelector value={field.value} onSelect={field.onChange} />
|
||||
)}
|
||||
/>
|
||||
),
|
||||
value: SIDE_NAMES[order.side] || '',
|
||||
},
|
||||
{
|
||||
label: t('Choose Position Size'),
|
||||
component:
|
||||
max !== null ? (
|
||||
<>
|
||||
<DealTicketSize
|
||||
step={step}
|
||||
min={step}
|
||||
max={max}
|
||||
onSizeChange={onSizeChange}
|
||||
size={new BigNumber(order.size).toNumber()}
|
||||
name="size"
|
||||
price={formattedPrice || emptyString}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
quoteName={
|
||||
market.tradableInstrument.instrument.product.settlementAsset
|
||||
.symbol
|
||||
}
|
||||
notionalSize={notionalSize || emptyString}
|
||||
estCloseOut={estCloseOut || emptyString}
|
||||
fees={fees || emptyString}
|
||||
estMargin={estMargin?.margin || emptyString}
|
||||
/>
|
||||
<DealTicketSlippage
|
||||
value={slippageValue}
|
||||
onValueChange={onSlippageChange}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
t('Loading...')
|
||||
),
|
||||
value: order.size,
|
||||
},
|
||||
{
|
||||
label: t('Review Trade'),
|
||||
component: (
|
||||
<div className="mb-8">
|
||||
{invalidText && (
|
||||
<div className="mb-2">
|
||||
<InputError data-testid="dealticket-error-message">
|
||||
{invalidText}
|
||||
</InputError>
|
||||
</div>
|
||||
)}
|
||||
<ReviewTrade
|
||||
market={market}
|
||||
isDisabled={isDisabled}
|
||||
transactionStatus={transactionStatus}
|
||||
order={order}
|
||||
estCloseOut={estCloseOut || emptyString}
|
||||
estMargin={estMargin?.margin || emptyString}
|
||||
price={formattedPrice || emptyString}
|
||||
quoteName={
|
||||
market.tradableInstrument.instrument.product.settlementAsset
|
||||
.symbol
|
||||
}
|
||||
notionalSize={notionalSize || emptyString}
|
||||
fees={fees || emptyString}
|
||||
slippage={slippageValue}
|
||||
/>
|
||||
<Dialog
|
||||
title={getOrderDialogTitle(finalizedOrder?.status)}
|
||||
intent={getOrderDialogIntent(finalizedOrder?.status)}
|
||||
icon={getOrderDialogIcon(finalizedOrder?.status)}
|
||||
content={{
|
||||
Complete: (
|
||||
<OrderFeedback
|
||||
transaction={transaction}
|
||||
order={finalizedOrder}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
disabled: true,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="px-2 py-4">
|
||||
<Stepper steps={steps} />
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './deal-ticket-container';
|
||||
export * from './deal-ticket-size';
|
||||
@@ -1,126 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
Button,
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import classNames from 'classnames';
|
||||
import { DealTicketEstimates } from '@vegaprotocol/deal-ticket';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { SIDE_NAMES } from './side-selector';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { MarketExpires } from '@vegaprotocol/market-info';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import type {
|
||||
MarketTags,
|
||||
MarketTagsVariables,
|
||||
} from './__generated__/MarketTags';
|
||||
|
||||
export const MARKET_TAGS_QUERY = gql`
|
||||
query MarketTags($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
market: MarketDealTicket;
|
||||
isDisabled: boolean;
|
||||
transactionStatus?: string;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
estCloseOut: string;
|
||||
estMargin: string;
|
||||
quoteName: string;
|
||||
price: string;
|
||||
fees: string;
|
||||
notionalSize: string;
|
||||
slippage: number;
|
||||
}
|
||||
|
||||
export default ({
|
||||
isDisabled,
|
||||
market,
|
||||
order,
|
||||
transactionStatus,
|
||||
estCloseOut,
|
||||
quoteName,
|
||||
fees,
|
||||
price,
|
||||
notionalSize,
|
||||
slippage,
|
||||
}: Props) => {
|
||||
const { data: tagsData } = useQuery<MarketTags, MarketTagsVariables>(
|
||||
MARKET_TAGS_QUERY,
|
||||
{
|
||||
variables: { marketId: market.id },
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mb-8 text-black dark:text-white" data-testid="review-trade">
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow noBorder>
|
||||
<div className="flex flex-none gap-x-2 items-center">
|
||||
<div
|
||||
className={classNames(
|
||||
{
|
||||
'buyButton dark:buyButtonDark':
|
||||
order.side === Schema.Side.SIDE_BUY,
|
||||
'sellButton dark:sellButtonDark':
|
||||
order.side === Schema.Side.SIDE_SELL,
|
||||
},
|
||||
'px-2 py-1 inline text-ui-small'
|
||||
)}
|
||||
>
|
||||
{SIDE_NAMES[order.side]}
|
||||
</div>
|
||||
<div>{market.tradableInstrument.instrument.product.quoteName}</div>
|
||||
<div>
|
||||
{tagsData?.market?.tradableInstrument.instrument.metadata
|
||||
.tags && (
|
||||
<MarketExpires
|
||||
tags={
|
||||
tagsData?.market.tradableInstrument.instrument.metadata.tags
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-blue">
|
||||
{`@ ${price} `}
|
||||
<span className="text-ui-small inline">(EST)</span>
|
||||
</div>
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
|
||||
<DealTicketEstimates
|
||||
size={order.size}
|
||||
quoteName={quoteName}
|
||||
fees={fees}
|
||||
estCloseOut={estCloseOut}
|
||||
notionalSize={notionalSize}
|
||||
slippage={slippage.toString()}
|
||||
/>
|
||||
|
||||
<div className="mt-12 max-w-sm">
|
||||
<Button
|
||||
fill={true}
|
||||
type="submit"
|
||||
disabled={transactionStatus === 'pending' || isDisabled}
|
||||
data-testid="place-order"
|
||||
rightIcon="arrow-top-right"
|
||||
>
|
||||
{transactionStatus === 'pending' ? t('Pending...') : t('Submit')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { FormGroup } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
|
||||
interface SideSelectorProps {
|
||||
value: Schema.Side;
|
||||
onSelect: (side: Schema.Side) => void;
|
||||
}
|
||||
|
||||
export const SIDE_NAMES: Record<Schema.Side, string> = {
|
||||
[Schema.Side.SIDE_BUY]: t('Long'),
|
||||
[Schema.Side.SIDE_SELL]: t('Short'),
|
||||
};
|
||||
|
||||
export default ({ value, onSelect }: SideSelectorProps) => {
|
||||
return (
|
||||
<FormGroup
|
||||
label={t('Direction')}
|
||||
labelFor="order-side-toggle"
|
||||
hideLabel={true}
|
||||
>
|
||||
<fieldset
|
||||
className="w-full grid md:grid-cols-2 gap-4"
|
||||
id="order-side-toggle"
|
||||
>
|
||||
<button
|
||||
aria-label={t('Open long position')}
|
||||
type="button"
|
||||
className={classNames(
|
||||
'px-8 py-2',
|
||||
'buyButton hover:buyButton dark:buyButtonDark dark:hover:buyButtonDark',
|
||||
{ selected: value === Schema.Side.SIDE_BUY }
|
||||
)}
|
||||
onClick={() => onSelect(Schema.Side.SIDE_BUY)}
|
||||
>
|
||||
{t('Long')}
|
||||
</button>
|
||||
<button
|
||||
aria-label={t('Open short position')}
|
||||
type="button"
|
||||
className={classNames(
|
||||
'px-8 py-2',
|
||||
'sellButton hover:sellButton dark:sellButtonDark dark:hover:sellButtonDark',
|
||||
{ selected: value === Schema.Side.SIDE_SELL }
|
||||
)}
|
||||
onClick={() => onSelect(Schema.Side.SIDE_SELL)}
|
||||
>
|
||||
{t('Short')}
|
||||
</button>
|
||||
<div className="md:col-span-2 text-black dark:text-white text-ui-small">
|
||||
{t(
|
||||
'Trading derivatives allows you to make a profit or loss regardless of whether the market you are trading goes up or down. If you open a "long" position, you will make a profit if the price of your chosen market goes up, and you will make a profit for "short" positions when the price goes down.'
|
||||
)}
|
||||
</div>
|
||||
</fieldset>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
@@ -1,396 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
MarketStateMapping,
|
||||
Schema as Types,
|
||||
Schema,
|
||||
} from '@vegaprotocol/types';
|
||||
import type { ValidationProps } from './use-order-validation';
|
||||
import { marketTranslations, useOrderValidation } from './use-order-validation';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import * as DealTicket from '@vegaprotocol/deal-ticket';
|
||||
|
||||
jest.mock('@vegaprotocol/wallet');
|
||||
jest.mock('@vegaprotocol/deal-ticket', () => {
|
||||
return {
|
||||
...jest.requireActual('@vegaprotocol/deal-ticket'),
|
||||
useOrderMarginValidation: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
type SettlementAsset =
|
||||
MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
const asset: SettlementAsset = {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
symbol: 'asset-symbol',
|
||||
name: 'asset-name',
|
||||
decimals: 2,
|
||||
};
|
||||
|
||||
const market: MarketDealTicket = {
|
||||
id: 'market-id',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 1,
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
id: 'instrument-id',
|
||||
name: 'instrument-name',
|
||||
code: 'instriment-code',
|
||||
metadata: {
|
||||
tags: [],
|
||||
},
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'quote-name',
|
||||
settlementAsset: asset,
|
||||
dataSourceSpecForTradingTermination: {
|
||||
id: 'dataSource-id',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
depth: {
|
||||
__typename: 'MarketDepth',
|
||||
lastTrade: {
|
||||
__typename: 'Trade',
|
||||
price: '100',
|
||||
},
|
||||
},
|
||||
fees: {
|
||||
__typename: 'Fees',
|
||||
factors: {
|
||||
__typename: 'FeeFactors',
|
||||
makerFee: '1',
|
||||
infrastructureFee: '2',
|
||||
liquidityFee: '3',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
__typename: 'MarketData',
|
||||
bestBidPrice: '1605489971',
|
||||
bestOfferPrice: '1606823730',
|
||||
markPrice: '1606823730',
|
||||
trigger: Types.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||
staticMidPrice: '1606156850',
|
||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
indicativeVolume: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '1605489971',
|
||||
bestStaticOfferPrice: '1606823730',
|
||||
targetStake: '8561302732',
|
||||
suppliedStake: '727654170336',
|
||||
auctionStart: null,
|
||||
auctionEnd: null,
|
||||
market: { __typename: 'Market', id: 'market-id' },
|
||||
},
|
||||
marketTimestamps: {},
|
||||
};
|
||||
|
||||
const defaultWalletContext = {
|
||||
pubKey: '111111__111111',
|
||||
pubKeys: [],
|
||||
sendTx: jest.fn().mockReturnValue(Promise.resolve(null)),
|
||||
connect: jest.fn(),
|
||||
disconnect: jest.fn(),
|
||||
selectPubKey: jest.fn(),
|
||||
connector: null,
|
||||
};
|
||||
|
||||
const order = {
|
||||
type: Schema.OrderType.TYPE_MARKET,
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
marketId: 'market-id',
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
size: '0.1',
|
||||
};
|
||||
|
||||
const defaultOrder = {
|
||||
market: { ...market },
|
||||
step: 0.1,
|
||||
order: {
|
||||
...order,
|
||||
},
|
||||
};
|
||||
|
||||
const ERROR = {
|
||||
KEY_MISSING: 'No public key selected',
|
||||
KEY_TAINTED: 'Selected public key has been tainted',
|
||||
MARKET_SUSPENDED: 'Market is currently suspended',
|
||||
MARKET_INACTIVE: 'Market is no longer active',
|
||||
MARKET_WAITING: 'Market is not active yet',
|
||||
MARKET_CONTINUOUS_LIMIT:
|
||||
'Only limit orders are permitted when market is in auction',
|
||||
MARKET_CONTINUOUS_TIF:
|
||||
'Until the auction ends, you can only place GFA, GTT, or GTC limit orders',
|
||||
FIELD_SIZE_REQ: 'You need to provide a size',
|
||||
FIELD_SIZE_MIN: `Size cannot be lower than "${defaultOrder.step}"`,
|
||||
FIELD_PRICE_REQ: 'You need to provide a price',
|
||||
FIELD_PRICE_MIN: 'The price cannot be negative',
|
||||
FIELD_PRICE_STEP_NULL: 'Order sizes must be in whole numbers for this market',
|
||||
FIELD_PRICE_STEP_DECIMAL: `The size field accepts up to ${market.positionDecimalPlaces} decimal places`,
|
||||
};
|
||||
|
||||
function setup(
|
||||
props?: Partial<ValidationProps>,
|
||||
context?: Partial<VegaWalletContextShape>
|
||||
) {
|
||||
const mockUseVegaWallet = useVegaWallet as jest.Mock;
|
||||
mockUseVegaWallet.mockReturnValue({ ...defaultWalletContext, context });
|
||||
return renderHook(() => useOrderValidation({ ...defaultOrder, ...props }), {
|
||||
wrapper: MockedProvider,
|
||||
});
|
||||
}
|
||||
|
||||
describe('useOrderValidation', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('Returns empty string when given valid data', () => {
|
||||
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
|
||||
balance: '0',
|
||||
margin: '100',
|
||||
balanceError: false,
|
||||
});
|
||||
|
||||
const { result } = setup();
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: false,
|
||||
message: ``,
|
||||
section: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('Returns an error message when no keypair found', () => {
|
||||
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
|
||||
balance: '0',
|
||||
margin: '100',
|
||||
balanceError: false,
|
||||
});
|
||||
const { result } = setup(defaultOrder, { pubKey: null });
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: false,
|
||||
message: ``,
|
||||
section: '',
|
||||
});
|
||||
});
|
||||
|
||||
it.each`
|
||||
state
|
||||
${Schema.MarketState.STATE_SETTLED}
|
||||
${Schema.MarketState.STATE_REJECTED}
|
||||
${Schema.MarketState.STATE_TRADING_TERMINATED}
|
||||
${Schema.MarketState.STATE_CLOSED}
|
||||
${Schema.MarketState.STATE_CANCELLED}
|
||||
`(
|
||||
'Returns an error message for market state when not accepting orders',
|
||||
({ state }) => {
|
||||
const { result } = setup({ market: { ...defaultOrder.market, state } });
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: true,
|
||||
message: `This market is ${marketTranslations(
|
||||
state
|
||||
)} and not accepting orders`,
|
||||
section: 'sec-summary',
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it.each`
|
||||
state
|
||||
${Schema.MarketState.STATE_PENDING}
|
||||
${Schema.MarketState.STATE_PROPOSED}
|
||||
`(
|
||||
'Returns an error message for market state suspended or pending',
|
||||
({ state }) => {
|
||||
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
|
||||
balance: '0',
|
||||
margin: '100',
|
||||
balanceError: false,
|
||||
// asset,
|
||||
});
|
||||
const { result } = setup({
|
||||
market: {
|
||||
...defaultOrder.market,
|
||||
state,
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
|
||||
},
|
||||
order: {
|
||||
...order,
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: false,
|
||||
message: `This market is ${MarketStateMapping[
|
||||
state as Schema.MarketState
|
||||
].toLowerCase()} and only accepting liquidity commitment orders`,
|
||||
section: 'sec-summary',
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it.each`
|
||||
tradingMode | errorMessage
|
||||
${Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION} | ${ERROR.MARKET_CONTINUOUS_LIMIT}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION} | ${ERROR.MARKET_CONTINUOUS_LIMIT}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION} | ${ERROR.MARKET_CONTINUOUS_LIMIT}
|
||||
`(
|
||||
`Returns an error message when trying to submit a non-limit order for a "$tradingMode" market`,
|
||||
({ tradingMode, errorMessage }) => {
|
||||
const { result } = setup({
|
||||
market: { ...defaultOrder.market, tradingMode },
|
||||
order: {
|
||||
...order,
|
||||
type: Schema.OrderType.TYPE_MARKET,
|
||||
},
|
||||
});
|
||||
expect(result.current.isDisabled).toBeTruthy();
|
||||
expect(result.current.message).toBe(errorMessage);
|
||||
}
|
||||
);
|
||||
|
||||
it.each`
|
||||
tradingMode | orderTimeInForce | errorMessage
|
||||
${Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_FOK} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_FOK} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_FOK} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_IOC} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_IOC} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_IOC} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_GFN} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_GFN} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
${Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION} | ${Schema.OrderTimeInForce.TIME_IN_FORCE_GFN} | ${ERROR.MARKET_CONTINUOUS_TIF}
|
||||
`(
|
||||
`Returns an error message when submitting a limit order with a "$orderTimeInForce" value to a "$tradingMode" market`,
|
||||
({ tradingMode, orderTimeInForce, errorMessage }) => {
|
||||
const { result } = setup({
|
||||
market: { ...defaultOrder.market, tradingMode },
|
||||
order: {
|
||||
...order,
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
timeInForce: orderTimeInForce,
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: true,
|
||||
message: errorMessage,
|
||||
section: 'sec-force',
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it.each`
|
||||
fieldName | errorType | section | errorMessage
|
||||
${`size`} | ${`required`} | ${'sec-size'} | ${ERROR.FIELD_SIZE_REQ}
|
||||
${`size`} | ${`min`} | ${'sec-size'} | ${ERROR.FIELD_SIZE_MIN}
|
||||
${`price`} | ${`required`} | ${'sec-price'} | ${ERROR.FIELD_PRICE_REQ}
|
||||
${`price`} | ${`min`} | ${'sec-price'} | ${ERROR.FIELD_PRICE_MIN}
|
||||
`(
|
||||
`Returns an error message when the order $fieldName "$errorType" validation fails`,
|
||||
({ fieldName, errorType, section, errorMessage }) => {
|
||||
const { result } = setup({
|
||||
fieldErrors: { [fieldName]: { type: errorType } },
|
||||
order: {
|
||||
...order,
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: true,
|
||||
message: errorMessage,
|
||||
section,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it('Returns an error message when the order size incorrectly has decimal values', () => {
|
||||
const { result } = setup({
|
||||
market: { ...market, positionDecimalPlaces: 0 },
|
||||
fieldErrors: {
|
||||
size: { type: `validate`, message: DealTicket.ERROR_SIZE_DECIMAL },
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: true,
|
||||
message: ERROR.FIELD_PRICE_STEP_NULL,
|
||||
section: 'sec-size',
|
||||
});
|
||||
});
|
||||
|
||||
it('Returns an error message when the order size has more decimals than allowed', () => {
|
||||
const { result } = setup({
|
||||
fieldErrors: {
|
||||
size: { type: `validate`, message: DealTicket.ERROR_SIZE_DECIMAL },
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: true,
|
||||
message: ERROR.FIELD_PRICE_STEP_DECIMAL,
|
||||
section: 'sec-size',
|
||||
});
|
||||
});
|
||||
|
||||
it('Returns an error message when the estimated margin is higher than collateral', async () => {
|
||||
const invalidatedMockValue = {
|
||||
balance: '100',
|
||||
margin: '200',
|
||||
balanceError: true,
|
||||
};
|
||||
|
||||
jest
|
||||
.spyOn(DealTicket, 'useOrderMarginValidation')
|
||||
.mockReturnValue(invalidatedMockValue);
|
||||
|
||||
const { result } = setup({});
|
||||
|
||||
expect(result.current.isDisabled).toBe(false);
|
||||
|
||||
const testElement = (
|
||||
<DealTicket.MarginWarning
|
||||
margin={invalidatedMockValue.margin}
|
||||
balance={invalidatedMockValue.balance}
|
||||
asset={asset}
|
||||
/>
|
||||
);
|
||||
expect((result.current.message as React.ReactElement)?.props).toEqual(
|
||||
testElement.props
|
||||
);
|
||||
expect((result.current.message as React.ReactElement)?.type).toEqual(
|
||||
testElement.type
|
||||
);
|
||||
});
|
||||
|
||||
it.each`
|
||||
state
|
||||
${Schema.MarketState.STATE_PENDING}
|
||||
${Schema.MarketState.STATE_PROPOSED}
|
||||
`(
|
||||
'Returns error when market state is pending and size is wrong',
|
||||
({ state }) => {
|
||||
const { result } = setup({
|
||||
fieldErrors: {
|
||||
size: { type: `validate`, message: DealTicket.ERROR_SIZE_DECIMAL },
|
||||
},
|
||||
market: {
|
||||
...market,
|
||||
state,
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: true,
|
||||
message: ERROR.FIELD_PRICE_STEP_DECIMAL,
|
||||
section: 'sec-size',
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -1,384 +0,0 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import type { FieldErrors } from 'react-hook-form';
|
||||
import { useMemo } from 'react';
|
||||
import { t, toDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { MarketStateMapping, Schema } from '@vegaprotocol/types';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
MarketDataGrid,
|
||||
compileGridData,
|
||||
MarginWarning,
|
||||
isMarketInAuction,
|
||||
ERROR_SIZE_DECIMAL,
|
||||
useOrderMarginValidation,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
export const DEAL_TICKET_SECTION = {
|
||||
TYPE: 'sec-type',
|
||||
SIZE: 'sec-size',
|
||||
PRICE: 'sec-price',
|
||||
FORCE: 'sec-force',
|
||||
EXPIRY: 'sec-expiry',
|
||||
SUMMARY: 'sec-summary',
|
||||
};
|
||||
|
||||
export const ERROR_EXPIRATION_IN_THE_PAST = 'ERROR_EXPIRATION_IN_THE_PAST';
|
||||
|
||||
export type ValidationProps = {
|
||||
step?: number;
|
||||
market: MarketDealTicket;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
fieldErrors?: FieldErrors<OrderSubmissionBody['orderSubmission']>;
|
||||
};
|
||||
|
||||
export const marketTranslations = (marketState: Schema.MarketState) => {
|
||||
switch (marketState) {
|
||||
case Schema.MarketState.STATE_TRADING_TERMINATED:
|
||||
return t('terminated');
|
||||
default:
|
||||
return t(MarketStateMapping[marketState]).toLowerCase();
|
||||
}
|
||||
};
|
||||
|
||||
export type DealTicketSection =
|
||||
| ''
|
||||
| typeof DEAL_TICKET_SECTION[keyof typeof DEAL_TICKET_SECTION];
|
||||
|
||||
export const useOrderValidation = ({
|
||||
market,
|
||||
fieldErrors,
|
||||
order,
|
||||
}: ValidationProps): {
|
||||
message: ReactNode | string;
|
||||
isDisabled: boolean;
|
||||
section: DealTicketSection;
|
||||
} => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const minSize = toDecimal(market.positionDecimalPlaces);
|
||||
const isInvalidOrderMargin = useOrderMarginValidation({ market, order });
|
||||
|
||||
const fieldErrorChecking = useMemo<{
|
||||
message: ReactNode | string;
|
||||
isDisabled: boolean;
|
||||
section: DealTicketSection;
|
||||
} | null>(() => {
|
||||
if (fieldErrors?.size?.type || fieldErrors?.price?.type) {
|
||||
if (fieldErrors?.size?.type === 'required') {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t('You need to provide a size'),
|
||||
section: DEAL_TICKET_SECTION.SIZE,
|
||||
};
|
||||
}
|
||||
|
||||
if (fieldErrors?.size?.type === 'min') {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t(`Size cannot be lower than "${minSize}"`),
|
||||
section: DEAL_TICKET_SECTION.SIZE,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
fieldErrors?.price?.type === 'required' &&
|
||||
order.type !== Schema.OrderType.TYPE_MARKET
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t('You need to provide a price'),
|
||||
section: DEAL_TICKET_SECTION.PRICE,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
fieldErrors?.price?.type === 'min' &&
|
||||
order.type !== Schema.OrderType.TYPE_MARKET
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t(`The price cannot be negative`),
|
||||
section: DEAL_TICKET_SECTION.PRICE,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
fieldErrors?.size?.type === 'validate' &&
|
||||
fieldErrors?.size?.message === ERROR_SIZE_DECIMAL
|
||||
) {
|
||||
if (market.positionDecimalPlaces === 0) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t('Order sizes must be in whole numbers for this market'),
|
||||
section: DEAL_TICKET_SECTION.SIZE,
|
||||
};
|
||||
}
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t(
|
||||
`The size field accepts up to ${market.positionDecimalPlaces} decimal places`
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.SIZE,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
fieldErrors?.expiresAt?.type === 'validate' &&
|
||||
fieldErrors?.expiresAt.message === ERROR_EXPIRATION_IN_THE_PAST
|
||||
) {
|
||||
return {
|
||||
isDisabled: false,
|
||||
message: t(
|
||||
'The expiry date that you have entered appears to be in the past'
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.EXPIRY,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}, [
|
||||
fieldErrors?.size?.type,
|
||||
fieldErrors?.size?.message,
|
||||
fieldErrors?.price?.type,
|
||||
fieldErrors?.expiresAt?.type,
|
||||
fieldErrors?.expiresAt?.message,
|
||||
order.type,
|
||||
minSize,
|
||||
market.positionDecimalPlaces,
|
||||
]);
|
||||
|
||||
const { message, isDisabled, section } = useMemo<{
|
||||
message: ReactNode | string;
|
||||
isDisabled: boolean;
|
||||
section: DealTicketSection;
|
||||
}>(() => {
|
||||
if (!pubKey) {
|
||||
return {
|
||||
message: t('No public key selected'),
|
||||
isDisabled: true,
|
||||
section: DEAL_TICKET_SECTION.SUMMARY,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
Schema.MarketState.STATE_SETTLED,
|
||||
Schema.MarketState.STATE_REJECTED,
|
||||
Schema.MarketState.STATE_TRADING_TERMINATED,
|
||||
Schema.MarketState.STATE_CANCELLED,
|
||||
Schema.MarketState.STATE_CLOSED,
|
||||
].includes(market.state)
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t(
|
||||
`This market is ${marketTranslations(
|
||||
market.state
|
||||
)} and not accepting orders`
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.SUMMARY,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
Schema.MarketState.STATE_PROPOSED,
|
||||
Schema.MarketState.STATE_PENDING,
|
||||
].includes(market.state)
|
||||
) {
|
||||
if (fieldErrorChecking) {
|
||||
return fieldErrorChecking;
|
||||
}
|
||||
return {
|
||||
isDisabled: false,
|
||||
message: t(
|
||||
`This market is ${marketTranslations(
|
||||
market.state
|
||||
)} and only accepting liquidity commitment orders`
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.SUMMARY,
|
||||
};
|
||||
}
|
||||
|
||||
if (isMarketInAuction(market)) {
|
||||
if (order.type === Schema.OrderType.TYPE_MARKET) {
|
||||
if (
|
||||
market.tradingMode ===
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
market.data?.trigger ===
|
||||
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: (
|
||||
<span>
|
||||
{t('This market is in auction until it reaches')}{' '}
|
||||
<Tooltip
|
||||
description={
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
}
|
||||
>
|
||||
<span>{t('sufficient liquidity')}</span>
|
||||
</Tooltip>
|
||||
{'. '}
|
||||
{t('Only limit orders are permitted when market is in auction')}
|
||||
</span>
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.TYPE,
|
||||
};
|
||||
}
|
||||
if (
|
||||
market.tradingMode ===
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
market.data?.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: (
|
||||
<span>
|
||||
{t('This market is in auction due to')}{' '}
|
||||
<Tooltip
|
||||
description={
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
}
|
||||
>
|
||||
<span>{t('high price volatility')}</span>
|
||||
</Tooltip>
|
||||
{'. '}
|
||||
{t('Only limit orders are permitted when market is in auction')}
|
||||
</span>
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.TYPE,
|
||||
};
|
||||
}
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t(
|
||||
'Only limit orders are permitted when market is in auction'
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.SUMMARY,
|
||||
};
|
||||
}
|
||||
if (
|
||||
order.type === Schema.OrderType.TYPE_LIMIT &&
|
||||
[
|
||||
Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
Schema.OrderTimeInForce.TIME_IN_FORCE_GFN,
|
||||
].includes(order.timeInForce)
|
||||
) {
|
||||
if (
|
||||
market.tradingMode ===
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
market.data?.trigger ===
|
||||
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: (
|
||||
<span>
|
||||
{t('This market is in auction until it reaches')}{' '}
|
||||
<Tooltip
|
||||
description={
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
}
|
||||
>
|
||||
<span>{t('sufficient liquidity')}</span>
|
||||
</Tooltip>
|
||||
{'. '}
|
||||
{t(
|
||||
`Until the auction ends, you can only place GFA, GTT, or GTC limit orders`
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.FORCE,
|
||||
};
|
||||
}
|
||||
if (
|
||||
market.tradingMode ===
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
market.data?.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: (
|
||||
<span>
|
||||
{t('This market is in auction due to')}{' '}
|
||||
<Tooltip
|
||||
description={
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
}
|
||||
>
|
||||
<span>{t('high price volatility')}</span>
|
||||
</Tooltip>
|
||||
{'. '}
|
||||
{t(
|
||||
`Until the auction ends, you can only place GFA, GTT, or GTC limit orders`
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.FORCE,
|
||||
};
|
||||
}
|
||||
return {
|
||||
isDisabled: true,
|
||||
message: t(
|
||||
`Until the auction ends, you can only place GFA, GTT, or GTC limit orders`
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.FORCE,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldErrorChecking) {
|
||||
return fieldErrorChecking;
|
||||
}
|
||||
|
||||
if (isInvalidOrderMargin.balanceError) {
|
||||
return {
|
||||
isDisabled: false,
|
||||
message: (
|
||||
<MarginWarning
|
||||
margin={isInvalidOrderMargin.margin}
|
||||
balance={isInvalidOrderMargin.balance}
|
||||
asset={market.tradableInstrument.instrument.product.settlementAsset}
|
||||
/>
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.PRICE,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
||||
].includes(market.tradingMode)
|
||||
) {
|
||||
return {
|
||||
isDisabled: false,
|
||||
message: t(
|
||||
'Any orders placed now will not trade until the auction ends'
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.SUMMARY,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isDisabled: false,
|
||||
message: '',
|
||||
section: '',
|
||||
};
|
||||
}, [
|
||||
pubKey,
|
||||
market,
|
||||
fieldErrorChecking,
|
||||
isInvalidOrderMargin,
|
||||
order.type,
|
||||
order.timeInForce,
|
||||
]);
|
||||
|
||||
return { message, isDisabled, section };
|
||||
};
|
||||
@@ -1,18 +0,0 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { DepositDialog, useDepositDialog } from '@vegaprotocol/deposits';
|
||||
|
||||
/**
|
||||
* Fetches data required for the Deposit page
|
||||
*/
|
||||
export const DepositContainer = () => {
|
||||
const openDepositDialog = useDepositDialog((state) => state.open);
|
||||
return (
|
||||
<div>
|
||||
<DepositDialog />
|
||||
<Button size="sm" onClick={() => openDepositDialog()}>
|
||||
{t('Make deposit')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './deposits';
|
||||
@@ -1,21 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import type { ReactElement } from 'react';
|
||||
|
||||
interface Props {
|
||||
children: ReactElement | ReactElement[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const DrawerContent = ({ children, className = '' }: Props) => {
|
||||
const classes = classNames(
|
||||
'w-full sm:w-full grow-1 overflow-hidden',
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
<main aria-label="Page Content" className={classes}>
|
||||
{children}
|
||||
</main>
|
||||
);
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { ButtonLink, Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import type { IconName } from '@vegaprotocol/ui-toolkit';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const enum DRAWER_TOGGLE_VARIANTS {
|
||||
OPEN = 'open',
|
||||
CLOSE = 'close',
|
||||
}
|
||||
|
||||
interface Props {
|
||||
onToggle: React.MouseEventHandler<HTMLButtonElement>;
|
||||
variant: DRAWER_TOGGLE_VARIANTS.OPEN | DRAWER_TOGGLE_VARIANTS.CLOSE;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const DrawerToggle = ({
|
||||
onToggle,
|
||||
variant = DRAWER_TOGGLE_VARIANTS.CLOSE,
|
||||
className = '',
|
||||
}: Props) => {
|
||||
const [iconName, setIconName] = useState(IconNames.MENU);
|
||||
const classes = classNames('md:hidden', className);
|
||||
|
||||
useEffect(() => {
|
||||
if (variant === DRAWER_TOGGLE_VARIANTS.OPEN) {
|
||||
setIconName(IconNames.MENU);
|
||||
} else {
|
||||
setIconName(IconNames.CROSS);
|
||||
}
|
||||
}, [variant]);
|
||||
|
||||
const ariaLabel = `${
|
||||
variant === DRAWER_TOGGLE_VARIANTS.OPEN ? 'Open' : 'Close'
|
||||
} Sidebar Navigation Menu`;
|
||||
|
||||
return (
|
||||
<span className={classes}>
|
||||
<ButtonLink aria-label={ariaLabel} onClick={onToggle}>
|
||||
<Icon name={iconName as IconName} />
|
||||
</ButtonLink>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import type { ReactElement } from 'react';
|
||||
|
||||
interface Props {
|
||||
children: ReactElement | ReactElement[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const DrawerWrapper = ({ children, className = '' }: Props) => {
|
||||
const classes = classNames('flex dark:bg-lite-black md:flex-row', className);
|
||||
return <div className={classes}>{children}</div>;
|
||||
};
|
||||
@@ -1,63 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import type { ReactElement } from 'react';
|
||||
|
||||
interface Props {
|
||||
children?: ReactElement | ReactElement[];
|
||||
isMenuOpen?: boolean;
|
||||
onToggle(): void;
|
||||
rtl?: boolean;
|
||||
outerClasses?: string;
|
||||
innerClasses?: string;
|
||||
}
|
||||
|
||||
export const NavigationDrawer = ({
|
||||
isMenuOpen = false,
|
||||
onToggle,
|
||||
children,
|
||||
rtl,
|
||||
outerClasses = '',
|
||||
innerClasses = '',
|
||||
}: Props) => {
|
||||
const width = 'w-full md:w-auto md:min-w-[15%] shrink-0';
|
||||
const position = 'absolute inset-0 h-full z-10 md:static';
|
||||
const background = 'bg-black/50 dark:bg-white/50';
|
||||
const flex = 'flex justify-end overflow-hidden';
|
||||
const joinedClasses = [flex, width, position, background].join(' ');
|
||||
|
||||
const outerStyles = classNames(joinedClasses, {
|
||||
visible: isMenuOpen,
|
||||
'invisible md:visible': !isMenuOpen,
|
||||
'flex-row-reverse': !rtl,
|
||||
[outerClasses]: outerClasses,
|
||||
});
|
||||
|
||||
const translateClose = rtl ? 'translate-x-full' : '-translate-x-full';
|
||||
|
||||
const innerStyles = classNames(
|
||||
'w-3/4 md:w-full bg-white dark:bg-lite-black',
|
||||
{
|
||||
'translate-x-0 transition-transform md:transform-none': isMenuOpen,
|
||||
[`${translateClose} md:transform-none`]: !isMenuOpen,
|
||||
[innerClasses]: innerClasses,
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<aside aria-label="Sidebar Navigation Menu" className={outerStyles}>
|
||||
<div
|
||||
role="presentation"
|
||||
aria-label="Content Overlay - Click To Close Sidebar Navigation"
|
||||
className="md:hidden grow h-full"
|
||||
onClick={onToggle}
|
||||
/>
|
||||
<div
|
||||
role="group"
|
||||
aria-label="Sidebar Navigation Grouped Content"
|
||||
className={innerStyles}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
export * from './drawer';
|
||||
export * from './drawer-toggle';
|
||||
export * from './drawer-content';
|
||||
export * from './drawer-wrapper';
|
||||
@@ -1,48 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
const Comet = () => {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 118 82"
|
||||
fill="currentColor"
|
||||
className="max-w-[7.5rem] mx-auto"
|
||||
>
|
||||
<g className="fill-black dark:fill-white">
|
||||
<path d="M44.3791 67.5864H41.5859V70.3796H44.3791V67.5864Z"></path>
|
||||
<path d="M47.173 64.7932V62H44.3799V64.7932V67.5863H47.173V64.7932Z"></path>
|
||||
<path d="M41.5863 70.3794H36V73.1726H41.5863V70.3794Z"></path>
|
||||
<path d="M44.3791 73.1719H41.5859V75.965H44.3791V73.1719Z"></path>
|
||||
<path d="M47.173 75.9658H44.3799V81.5521H47.173V75.9658Z"></path>
|
||||
<path d="M49.966 73.1719H47.1729V75.965H49.966V73.1719Z"></path>
|
||||
<path d="M55.5521 70.3794H49.9658V73.1726H55.5521V70.3794Z"></path>
|
||||
<path d="M49.966 67.5864H47.1729V70.3796H49.966V67.5864Z"></path>
|
||||
<path d="M57.1876 60.564H54V63.7515H57.1876V60.564Z"></path>
|
||||
<path d="M60.3751 57.3765H57.1875V60.564H60.3751V57.3765Z"></path>
|
||||
<path d="M63.5626 54.1885H60.375V57.3761H63.5626V54.1885Z"></path>
|
||||
<path d="M66.7501 51.001H63.5625V54.1886H66.7501V51.001Z"></path>
|
||||
<path d="M69.9376 47.8135H66.75V51.0011H69.9376V47.8135Z"></path>
|
||||
<path d="M73.1251 44.626H69.9375V47.8136H73.1251V44.626Z"></path>
|
||||
<path d="M76.3126 41.4385H73.125V44.6261H76.3126V41.4385Z"></path>
|
||||
<path d="M79.5001 38.251H76.3125V41.4386H79.5001V38.251Z"></path>
|
||||
<path d="M82.6886 35.0635H79.501V38.2511H82.6886V35.0635Z"></path>
|
||||
<path d="M85.8761 31.876H82.6885V35.0636H85.8761V31.876Z"></path>
|
||||
<path d="M89.0636 28.688H85.876V31.8756H89.0636V28.688Z"></path>
|
||||
<path d="M92.2511 25.5005H89.0635V28.6881H92.2511V25.5005Z"></path>
|
||||
<path d="M95.4386 22.313H92.251V25.5006H95.4386V22.313Z"></path>
|
||||
<path d="M98.6261 19.1255H95.4385V22.3131H98.6261V19.1255Z"></path>
|
||||
<path d="M101.814 15.938H98.626V19.1256H101.814V15.938Z"></path>
|
||||
<path d="M105.001 12.7505H101.813V15.9381H105.001V12.7505Z"></path>
|
||||
<path d="M108.189 9.5625H105.001V12.7501H108.189V9.5625Z"></path>
|
||||
<path d="M111.376 6.375H108.188V9.56258H111.376V6.375Z"></path>
|
||||
<path d="M114.565 3.1875H111.377V6.37508H114.565V3.1875Z"></path>
|
||||
<path d="M117.752 0H114.564V3.18758H117.752V0Z"></path>
|
||||
<path d="M2.79316 20.793H0V23.5861H2.79316V20.793Z"></path>
|
||||
<path d="M5.58612 18H2.79297V20.7932H5.58612V18Z"></path>
|
||||
<path d="M5.58612 23.5859H2.79297V26.3791H5.58612V23.5859Z"></path>
|
||||
<path d="M8.37909 20.793H5.58594V23.5861H8.37909V20.793Z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default Comet;
|
||||
@@ -1,34 +0,0 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||
import Logo from './logo';
|
||||
import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
|
||||
import LocalContext from '../../context/local-context';
|
||||
|
||||
const Header = () => {
|
||||
const { updateVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
|
||||
updateVegaWalletDialog: store.updateVegaWalletDialog,
|
||||
}));
|
||||
const {
|
||||
vegaWalletDialog: { setManage },
|
||||
theme,
|
||||
toggleTheme,
|
||||
} = useContext(LocalContext);
|
||||
return (
|
||||
<div
|
||||
className="dark flex items-stretch pr-6 py-6 bg-black text-neutral-400"
|
||||
data-testid="header"
|
||||
>
|
||||
<Logo />
|
||||
<div className="flex items-center gap-2 ml-auto relative z-10">
|
||||
<VegaWalletConnectButton
|
||||
setConnectDialog={updateVegaWalletDialog}
|
||||
setManageDialog={setManage}
|
||||
/>
|
||||
<ThemeSwitcher theme={theme} onToggle={toggleTheme} className="-my-4" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user