Compare commits
774
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
885dc0b52b | ||
|
|
58df46687b | ||
|
|
96a07b6379 | ||
|
|
619b73212f | ||
|
|
3e2449fdea | ||
|
|
0351d3f478 | ||
|
|
5ab455159c | ||
|
|
5742759780 | ||
|
|
94c34a1d76 | ||
|
|
2c1a3d106c | ||
|
|
d41e9456bc | ||
|
|
532ad3a4b9 | ||
|
|
3a8b40d7a5 | ||
|
|
be38813a33 | ||
|
|
bf70dc33ec | ||
|
|
0bad7e3317 | ||
|
|
d6084e75a0 | ||
|
|
b2d52f6f5c | ||
|
|
75e7cea32a | ||
|
|
b4e98e285e | ||
|
|
3ae2fe3e1c | ||
|
|
8eed5f1eb4 | ||
|
|
84bb32bdd7 | ||
|
|
f62e29c67f | ||
|
|
94e7ad489f | ||
|
|
657942d995 | ||
|
|
a529b9b031 | ||
|
|
87579c0c5f | ||
|
|
4bb50c0dab | ||
|
|
96b46d1533 | ||
|
|
19732d90e0 | ||
|
|
853d0654d7 | ||
|
|
b24b630f5f | ||
|
|
7777420f1f | ||
|
|
0f311611ba | ||
|
|
f5406941e7 | ||
|
|
02bd031bee | ||
|
|
bd97651dd3 | ||
|
|
516b3e5b93 | ||
|
|
42a98b6a35 | ||
|
|
2002731c52 | ||
|
|
18a3786c98 | ||
|
|
a49139f127 | ||
|
|
e216b23472 | ||
|
|
e52ae97233 | ||
|
|
1780f6fa7f | ||
|
|
8b91592b93 | ||
|
|
508274268d | ||
|
|
2a40d9ec4d | ||
|
|
efb746f373 | ||
|
|
6d2f367987 | ||
|
|
6b7bbc9c94 | ||
|
|
9153677a33 | ||
|
|
cff1818940 | ||
|
|
d05dd6e4cb | ||
|
|
4ef789e00a | ||
|
|
0bd13a5f7b | ||
|
|
67d38ff03e | ||
|
|
6aea10c27b | ||
|
|
27a9d5f247 | ||
|
|
261f32aa5b | ||
|
|
053775bef6 | ||
|
|
0660eda334 | ||
|
|
f22a3bc2d2 | ||
|
|
fde77ebccb | ||
|
|
e309669736 | ||
|
|
b1621d1191 | ||
|
|
39907f07db | ||
|
|
3dab5f3d9b | ||
|
|
3cf9ae7582 | ||
|
|
557894e2ef | ||
|
|
baf9875c69 | ||
|
|
51199b02ce | ||
|
|
bb826c88f0 | ||
|
|
0da20b750f | ||
|
|
e16c447564 | ||
|
|
a2170d27d6 | ||
|
|
00d840b7b3 | ||
|
|
2a4a05630f | ||
|
|
97f1f40f2c | ||
|
|
a8e6963521 | ||
|
|
a2bffa1dfd | ||
|
|
9253e8067a | ||
|
|
58972f0a11 | ||
|
|
a3c55fd7c3 | ||
|
|
c63cba1071 | ||
|
|
bc9d87fe30 | ||
|
|
6a21862378 | ||
|
|
0fb4348e9c | ||
|
|
b751bcf17d | ||
|
|
d32f27fcb1 | ||
|
|
d05cd6a2ed | ||
|
|
c003e5fa30 | ||
|
|
f62d3289ab | ||
|
|
a3d3d18c5c | ||
|
|
77ca101781 | ||
|
|
d238c37d0c | ||
|
|
79feb485f6 | ||
|
|
6aa5c3b6e3 | ||
|
|
82abc13fda | ||
|
|
933f07cddf | ||
|
|
c8067669c2 | ||
|
|
78f5a9c520 | ||
|
|
462066959d | ||
|
|
f12f5ab961 | ||
|
|
98b2460d8b | ||
|
|
67c182f3de | ||
|
|
68e0009ab0 | ||
|
|
ad74b12908 | ||
|
|
7fff33e493 | ||
|
|
e7cb2c8276 | ||
|
|
4adaeea40a | ||
|
|
d47d894147 | ||
|
|
515932d401 | ||
|
|
723ff2805d | ||
|
|
424cced4be | ||
|
|
b2c7ee82c5 | ||
|
|
4cc63be4f9 | ||
|
|
9fbb7a13e6 | ||
|
|
1874095222 | ||
|
|
e459e92127 | ||
|
|
4dd65b4923 | ||
|
|
5d792d2458 | ||
|
|
59b2f75b13 | ||
|
|
95775679ca | ||
|
|
4cffee29f8 | ||
|
|
bd70b0c233 | ||
|
|
145792f216 | ||
|
|
10add7c236 | ||
|
|
362a2031c7 | ||
|
|
5aaeb87059 | ||
|
|
d240dddab5 | ||
|
|
0af1d0ba82 | ||
|
|
665ab6693a | ||
|
|
902ee2696c | ||
|
|
3beeb0140c | ||
|
|
4b208e90bf | ||
|
|
ec837854cf | ||
|
|
8b94a75ba4 | ||
|
|
08c57b6759 | ||
|
|
bb2184498f | ||
|
|
8b07ce3024 | ||
|
|
8a110584dd | ||
|
|
b82615a3d8 | ||
|
|
f178b85846 | ||
|
|
0796f2b31f | ||
|
|
67be224138 | ||
|
|
51c426ef4b | ||
|
|
fa28d31ef3 | ||
|
|
201a586b05 | ||
|
|
7d96d9bcd1 | ||
|
|
345be81142 | ||
|
|
2221e9faca | ||
|
|
7c0139e107 | ||
|
|
a157ff1e05 | ||
|
|
2e9fa0c52e | ||
|
|
c0790c1e93 | ||
|
|
13c1044f8e | ||
|
|
cf9f313e4c | ||
|
|
f56d34fe6e | ||
|
|
1379366caa | ||
|
|
8958c12fe3 | ||
|
|
fef13874db | ||
|
|
40f02ecf89 | ||
|
|
41cd6b1455 | ||
|
|
3cd393dac0 | ||
|
|
a52e60d6a2 | ||
|
|
bc13f1b359 | ||
|
|
eb81f4ae44 | ||
|
|
51ab02a2e2 | ||
|
|
ffada1b93d | ||
|
|
9dda3f712b | ||
|
|
df20dbeee0 | ||
|
|
cdfd8a2d00 | ||
|
|
1e5c523bc4 | ||
|
|
37cd69ba6e | ||
|
|
2c11045dd9 | ||
|
|
9aef41a119 | ||
|
|
80ab8821d0 | ||
|
|
8a3657a9b9 | ||
|
|
7100b0e9fc | ||
|
|
614a83b7d6 | ||
|
|
3dc77b0eff | ||
|
|
a59f7dfd29 | ||
|
|
61471228aa | ||
|
|
127e784ceb | ||
|
|
70d748fb15 | ||
|
|
e06f4818fc | ||
|
|
8182da3b31 | ||
|
|
c8c56307bb | ||
|
|
a8cd7f157f | ||
|
|
4f18caa486 | ||
|
|
5c7c626bbc | ||
|
|
e4c4c20631 | ||
|
|
0697302d07 | ||
|
|
2d926c0ce0 | ||
|
|
f57d6a7c7b | ||
|
|
15f905046f | ||
|
|
4f7918f64e | ||
|
|
52ab0562b0 | ||
|
|
4e2b0d1b1d | ||
|
|
0b0bcad9b3 | ||
|
|
bcf17bb34e | ||
|
|
a2b9b0da05 | ||
|
|
7588d0cd11 | ||
|
|
5ee1748495 | ||
|
|
73a118978f | ||
|
|
eac26c1966 | ||
|
|
d615587564 | ||
|
|
ba4ce1ce88 | ||
|
|
3bbacc1aa0 | ||
|
|
de5371435d | ||
|
|
12cb5e10b6 | ||
|
|
ee2909cc84 | ||
|
|
068d6abf1b | ||
|
|
e5d4d2b0b8 | ||
|
|
d4e801cfc6 | ||
|
|
964deb2f23 | ||
|
|
6669125dd3 | ||
|
|
129b6c4e89 | ||
|
|
ca418cabfe | ||
|
|
192af844c4 | ||
|
|
6a841f226a | ||
|
|
76426baa2a | ||
|
|
6fdac2419c | ||
|
|
87807d2088 | ||
|
|
a5f2533a66 | ||
|
|
1e9251c9c0 | ||
|
|
2a27e124d7 | ||
|
|
4ee85720ab | ||
|
|
a19da4c408 | ||
|
|
65ad4fffda | ||
|
|
11317cdb2e | ||
|
|
c98870f27d | ||
|
|
c0c56e4c48 | ||
|
|
d9dc43b359 | ||
|
|
06a6fe6d67 | ||
|
|
a9ca215276 | ||
|
|
61a9eb2f5c | ||
|
|
bb47747501 | ||
|
|
5827b87f89 | ||
|
|
19b95832c4 | ||
|
|
48e4ab53a1 | ||
|
|
cefcff040f | ||
|
|
c3ef639daf | ||
|
|
b6052bc3e5 | ||
|
|
6e8894936e | ||
|
|
66f55855ae | ||
|
|
5725b824ad | ||
|
|
9344a2abc0 | ||
|
|
fae66ca4ce | ||
|
|
4b7338ed94 | ||
|
|
2983c6c6ba | ||
|
|
31524ac7a7 | ||
|
|
70f42c1c7e | ||
|
|
2304ce9763 | ||
|
|
79a16b8562 | ||
|
|
ea3e5a7651 | ||
|
|
b062339682 | ||
|
|
824bcf89bd | ||
|
|
f315917094 | ||
|
|
5661b74082 | ||
|
|
8e898cfd78 | ||
|
|
f377e07996 | ||
|
|
090d340364 | ||
|
|
6d32fa7362 | ||
|
|
1a7682c3c9 | ||
|
|
3294c0cabe | ||
|
|
c10084d441 | ||
|
|
96658134ee | ||
|
|
a070504d2e | ||
|
|
f891caf08b | ||
|
|
69bdc637e5 | ||
|
|
78add88014 | ||
|
|
02c425f304 | ||
|
|
06769f25cf | ||
|
|
b3014bb98a | ||
|
|
132f2e4b2b | ||
|
|
374890dc08 | ||
|
|
22703d937e | ||
|
|
7f95ba577e | ||
|
|
2f7e53e282 | ||
|
|
568dcd5305 | ||
|
|
9605b0e7fa | ||
|
|
0776332ba7 | ||
|
|
f780013846 | ||
|
|
73f37c2477 | ||
|
|
607ad06971 | ||
|
|
7aee2a3a7b | ||
|
|
1fdf519780 | ||
|
|
9233778e85 | ||
|
|
7a91f48bcb | ||
|
|
b43ea0f60b | ||
|
|
6e31fb03ae | ||
|
|
d76fa13c5d | ||
|
|
89aeed6305 | ||
|
|
6e677084a3 | ||
|
|
8069aa5ee7 | ||
|
|
b0169a0d39 | ||
|
|
06cfd79415 | ||
|
|
443220283c | ||
|
|
a642bf8ce4 | ||
|
|
20233db706 | ||
|
|
d4f50eb70c | ||
|
|
e5d3f90d45 | ||
|
|
673c896e2f | ||
|
|
deea63fa5e | ||
|
|
d31333538b | ||
|
|
4af9979a21 | ||
|
|
6421cf87c6 | ||
|
|
0ebfab64ff | ||
|
|
142f08343b | ||
|
|
61aa45a9ed | ||
|
|
4c95db5fb3 | ||
|
|
3072b7824f | ||
|
|
0580e90171 | ||
|
|
c440abc77d | ||
|
|
fbafc726a4 | ||
|
|
dd1890d8c6 | ||
|
|
c8e624eaba | ||
|
|
cc6629ad27 | ||
|
|
9838efa00e | ||
|
|
dac7142a98 | ||
|
|
1397aafd25 | ||
|
|
b192603e57 | ||
|
|
8c2c8d987c | ||
|
|
52c96794f7 | ||
|
|
58ce016d4d | ||
|
|
ac16eb06f5 | ||
|
|
3319871617 | ||
|
|
37e850304a | ||
|
|
655131c744 | ||
|
|
f1cb1b9408 | ||
|
|
891ac527a2 | ||
|
|
546087fb9f | ||
|
|
f7a82d33ba | ||
|
|
d85f413e41 | ||
|
|
c7d0025b4f | ||
|
|
6c9272cd53 | ||
|
|
82fb29d541 | ||
|
|
43cd170c77 | ||
|
|
1d39f81dfc | ||
|
|
f5868b6f1b | ||
|
|
20e1522088 | ||
|
|
ae02b153f8 | ||
|
|
fee5f862a7 | ||
|
|
c25362b084 | ||
|
|
7c105d2c6b | ||
|
|
2dfcb02d1e | ||
|
|
a98ab775c3 | ||
|
|
097bf7c08c | ||
|
|
236e35a92b | ||
|
|
abf84b9d45 | ||
|
|
6d2a2ea0a0 | ||
|
|
6ac79e9f6d | ||
|
|
835ee64243 | ||
|
|
e7c3b5054c | ||
|
|
9dc9588a14 | ||
|
|
a0844d41bf | ||
|
|
3d1aa74128 | ||
|
|
2376bfe58f | ||
|
|
72ccf96523 | ||
|
|
f416fa4a25 | ||
|
|
a24e3646cc | ||
|
|
55b092b216 | ||
|
|
ef4cf6a87e | ||
|
|
c9860a3412 | ||
|
|
127bd3faf3 | ||
|
|
1791b3ca6a | ||
|
|
6044b86ff4 | ||
|
|
341d78e761 | ||
|
|
58cc074538 | ||
|
|
852c9bb8f4 | ||
|
|
efe9b7a0e7 | ||
|
|
695a059dde | ||
|
|
5d7e4d273a | ||
|
|
b137e024c6 | ||
|
|
6651ee52b4 | ||
|
|
0d14722c5d | ||
|
|
4968b537b8 | ||
|
|
5f5c45f3b9 | ||
|
|
6b10df015d | ||
|
|
6d7e24732b | ||
|
|
b33cf04e16 | ||
|
|
66ebb26b0f | ||
|
|
51c88d2fce | ||
|
|
2786a984b0 | ||
|
|
39c53a7326 | ||
|
|
3371e8e2cc | ||
|
|
5843a36851 | ||
|
|
68b4909dff | ||
|
|
da8e382454 | ||
|
|
81ebefc329 | ||
|
|
1ed7d6fda2 | ||
|
|
a2e4f34b0d | ||
|
|
3a1bb855aa | ||
|
|
b4ca0a8390 | ||
|
|
349c790ecc | ||
|
|
4c8a15cc01 | ||
|
|
f433a030ff | ||
|
|
63a6e4ecbd | ||
|
|
555f6e2a6d | ||
|
|
c116762865 | ||
|
|
b47bd49e83 | ||
|
|
4b942cfb7d | ||
|
|
c27443fc13 | ||
|
|
6dbde76c84 | ||
|
|
f4abd7cef5 | ||
|
|
3b978118dc | ||
|
|
bb4cc1e51d | ||
|
|
797db6ee93 | ||
|
|
6e7b87d9ef | ||
|
|
6965bdf0ca | ||
|
|
f4d46efff5 | ||
|
|
d510330c6b | ||
|
|
5b5765ef63 | ||
|
|
283f654a4c | ||
|
|
6945514b49 | ||
|
|
f74687d30c | ||
|
|
2a7574bd8e | ||
|
|
872f1d300f | ||
|
|
600ea0eeab | ||
|
|
7c3f7a7ab1 | ||
|
|
539abce8af | ||
|
|
60ca6c2eb6 | ||
|
|
eeff4ffcd4 | ||
|
|
73ae00f12c | ||
|
|
ee73e4d5e2 | ||
|
|
14928d318d | ||
|
|
a19ea1c939 | ||
|
|
c65c296db2 | ||
|
|
6c5cd85d96 | ||
|
|
8efadda98c | ||
|
|
0872a14f44 | ||
|
|
8b249e1917 | ||
|
|
13817e4d57 | ||
|
|
abb771e2f9 | ||
|
|
acf1d50d0f | ||
|
|
9da704c117 | ||
|
|
d262650258 | ||
|
|
30da1663eb | ||
|
|
79cbe62774 | ||
|
|
df11401b69 | ||
|
|
2f0be0bf34 | ||
|
|
5b5802104e | ||
|
|
3a149ddfb2 | ||
|
|
0e519f4d0e | ||
|
|
ff2e2574f6 | ||
|
|
9b52cecf21 | ||
|
|
478cc9e753 | ||
|
|
18f1fbd56d | ||
|
|
ccb22f02c3 | ||
|
|
015d8f51c0 | ||
|
|
e2a72cb395 | ||
|
|
0669696b6f | ||
|
|
56c662e5ba | ||
|
|
7fe269fad6 | ||
|
|
b761023069 | ||
|
|
7453acd632 | ||
|
|
1f507facba | ||
|
|
9d6b34963a | ||
|
|
7ac3a68ac9 | ||
|
|
2640ccb20a | ||
|
|
77c0894501 | ||
|
|
60d7cf3029 | ||
|
|
2b8abde938 | ||
|
|
2005f19d50 | ||
|
|
d78de10855 | ||
|
|
bb402c02f6 | ||
|
|
8a9b1c7874 | ||
|
|
a7e8b0eb01 | ||
|
|
89b3c06107 | ||
|
|
cd5c73d3fd | ||
|
|
b3a5ab022d | ||
|
|
ba438549bc | ||
|
|
496d1f5c68 | ||
|
|
e914e7bb70 | ||
|
|
71a36c2382 | ||
|
|
1c6a307bcd | ||
|
|
ef4a740b91 | ||
|
|
a6303456c5 | ||
|
|
2d4be5fcb3 | ||
|
|
9cbd6baccd | ||
|
|
525773773a | ||
|
|
45d6f43e74 | ||
|
|
41760f2956 | ||
|
|
3d2b171de7 | ||
|
|
39a041332b | ||
|
|
4c0d05844e | ||
|
|
bf8480fed4 | ||
|
|
44434a7d39 | ||
|
|
b818e9b2a1 | ||
|
|
775835c667 | ||
|
|
3e30f053ff | ||
|
|
5db3453ba5 | ||
|
|
0b1987d4ce | ||
|
|
290b7ae856 | ||
|
|
835f2b793f | ||
|
|
e1557f51ce | ||
|
|
c98e53a984 | ||
|
|
95a51fd152 | ||
|
|
d50b988b4a | ||
|
|
76ee58e473 | ||
|
|
a6aec899c8 | ||
|
|
a6672d213f | ||
|
|
62f368da10 | ||
|
|
f3e2fe746d | ||
|
|
8b19572dc9 | ||
|
|
80399d04f7 | ||
|
|
8322fc7edd | ||
|
|
46752816ec | ||
|
|
f99f78780c | ||
|
|
f7037bca80 | ||
|
|
ba39720f05 | ||
|
|
6d35f2b39d | ||
|
|
78afecc2e5 | ||
|
|
3de5b07495 | ||
|
|
e944d3e37c | ||
|
|
5596392835 | ||
|
|
5c57106c04 | ||
|
|
2fc688f477 | ||
|
|
9ea8c839db | ||
|
|
d7e2da7a54 | ||
|
|
b29c268257 | ||
|
|
01ca05a313 | ||
|
|
e3c6dd41c9 | ||
|
|
fbd01dc1bd | ||
|
|
af6719cc9d | ||
|
|
c433a4ee06 | ||
|
|
e3a00ada05 | ||
|
|
aa38e0c001 | ||
|
|
86da521da5 | ||
|
|
c6df34fe95 | ||
|
|
c7d0803164 | ||
|
|
250a654544 | ||
|
|
7f5e8ebb15 | ||
|
|
ccbe34e172 | ||
|
|
27e8ce88bf | ||
|
|
41804d9869 | ||
|
|
293288286b | ||
|
|
a77765b1e9 | ||
|
|
2453d7841a | ||
|
|
a0945be721 | ||
|
|
84e40ccb2b | ||
|
|
a868f6d2f5 | ||
|
|
8b83c51014 | ||
|
|
bf7aacf984 | ||
|
|
5183f2591b | ||
|
|
b3308439bd | ||
|
|
719d210219 | ||
|
|
f810a3a0b1 | ||
|
|
db19ee80ac | ||
|
|
45623f33c5 | ||
|
|
08e204fe31 | ||
|
|
81f7b0595e | ||
|
|
4ed0e3a056 | ||
|
|
47a84b4dac | ||
|
|
c540d4b17f | ||
|
|
f1fa3250a4 | ||
|
|
707c00def2 | ||
|
|
78aff54360 | ||
|
|
6160fd7638 | ||
|
|
c345623a06 | ||
|
|
e9173796f5 | ||
|
|
2a0811863f | ||
|
|
4f610bbd1b | ||
|
|
104b2d145d | ||
|
|
f75787562c | ||
|
|
678c9090c7 | ||
|
|
21bb6a69c6 | ||
|
|
467ed5d53d | ||
|
|
d268088e60 | ||
|
|
1208d3f2a8 | ||
|
|
b5ba4f99d9 | ||
|
|
66f25603d3 | ||
|
|
4afd469404 | ||
|
|
9e5bc9c8d1 | ||
|
|
e41aff88b1 | ||
|
|
9209074332 | ||
|
|
39e5836edb | ||
|
|
85a4981700 | ||
|
|
247927e939 | ||
|
|
6523490d96 | ||
|
|
105a758e8d | ||
|
|
559ef48d6d | ||
|
|
255c3752f2 | ||
|
|
2bbf1e2b81 | ||
|
|
06d3ef8d73 | ||
|
|
de4c7926c2 | ||
|
|
50959b4c50 | ||
|
|
a8c2f4e025 | ||
|
|
2cea73c567 | ||
|
|
b0a54be408 | ||
|
|
d1a036e53c | ||
|
|
9ac199f59a | ||
|
|
332cc302c3 | ||
|
|
4da0e9c368 | ||
|
|
13e1f99767 | ||
|
|
5c18c898b0 | ||
|
|
4fe81cc4aa | ||
|
|
0fb8ee3abb | ||
|
|
3422b99491 | ||
|
|
287e294281 | ||
|
|
dc959025c6 | ||
|
|
63bfcc8f65 | ||
|
|
952e906eac | ||
|
|
e765c247ef | ||
|
|
52dea6d0dc | ||
|
|
97f243e5f7 | ||
|
|
9992d9f053 | ||
|
|
3e26431e8f | ||
|
|
6a9f15f59e | ||
|
|
4684745382 | ||
|
|
927e21b045 | ||
|
|
570472b739 | ||
|
|
28f7bd36e7 | ||
|
|
0f3e5595ba | ||
|
|
d3dbdd2bd5 | ||
|
|
0767139712 | ||
|
|
250492a02c | ||
|
|
29f3374c61 | ||
|
|
ba7b574a07 | ||
|
|
afd8650657 | ||
|
|
78414b4429 | ||
|
|
e0a91b3850 | ||
|
|
80f7a08765 | ||
|
|
3e627ff849 | ||
|
|
d2854b6e90 | ||
|
|
6d130c9cfc | ||
|
|
ab4f4e9084 | ||
|
|
fa1825ca64 | ||
|
|
206c6c7207 | ||
|
|
5b0bd69710 | ||
|
|
546b710093 | ||
|
|
afbf62be84 | ||
|
|
ef26d03d36 | ||
|
|
7471116ebf | ||
|
|
7142fc956c | ||
|
|
611f8d7491 | ||
|
|
f3b72b894e | ||
|
|
140f16f637 | ||
|
|
cae1fc67a4 | ||
|
|
35e25d9a8f | ||
|
|
86e122389c | ||
|
|
6616aceebb | ||
|
|
c937a9df0c | ||
|
|
9fcf286e4b | ||
|
|
e3ed71bec4 | ||
|
|
809f149df9 | ||
|
|
e4eedf5ccd | ||
|
|
20cbcb8302 | ||
|
|
cd3acf8ff9 | ||
|
|
30735388e8 | ||
|
|
478c4f83bb | ||
|
|
431fab8824 | ||
|
|
83b6d3d295 | ||
|
|
98fd79bc35 | ||
|
|
39aa27f332 | ||
|
|
bf4fb29fe6 | ||
|
|
5ed1befc53 | ||
|
|
1b311a8b36 | ||
|
|
70c3bc8128 | ||
|
|
7e49836875 | ||
|
|
d624957e6d | ||
|
|
069b57d4ae | ||
|
|
6894fe1264 | ||
|
|
93e4b5fdb9 | ||
|
|
1566fc3984 | ||
|
|
39962a0246 | ||
|
|
8d31510d5e | ||
|
|
26d5a67604 | ||
|
|
9cc8f5a377 | ||
|
|
2e11cf4dfa | ||
|
|
9e4ba9f275 | ||
|
|
aac0c25d09 | ||
|
|
d20c2a08ae | ||
|
|
4e6ba5fe3d | ||
|
|
276d1d7c7b | ||
|
|
4990c5808d | ||
|
|
cdd91c24f2 | ||
|
|
e3eb13ca72 | ||
|
|
3f0ebbf33d | ||
|
|
026aa3964b | ||
|
|
aa4c5a4a57 | ||
|
|
0874314d2a | ||
|
|
a70a7bcc8e | ||
|
|
4461a6a497 | ||
|
|
1041864ad8 | ||
|
|
015e0188ec | ||
|
|
228236c152 | ||
|
|
cd6e906dc6 | ||
|
|
8a47a92dbd | ||
|
|
af14c27df9 | ||
|
|
38edcd88c0 | ||
|
|
a74cf02030 | ||
|
|
6686755763 | ||
|
|
79cf8163be | ||
|
|
1688e26f4b | ||
|
|
5e101a8eaf | ||
|
|
65071f57d0 | ||
|
|
b87c981a90 | ||
|
|
b509e5b347 | ||
|
|
bb9fce4831 | ||
|
|
918825aca8 | ||
|
|
74bf183fad | ||
|
|
674baa1ee3 | ||
|
|
d18a0c7e15 | ||
|
|
76a6005b77 | ||
|
|
79414614c2 | ||
|
|
fde49e5446 | ||
|
|
45283161aa | ||
|
|
375d447fa8 | ||
|
|
1dd97a2bce | ||
|
|
d4a1a9b193 | ||
|
|
376c5241a8 | ||
|
|
8e6d8517cf | ||
|
|
5f9ec222c1 | ||
|
|
8954c41c0a | ||
|
|
4414ab4f47 | ||
|
|
d1d4bacc68 | ||
|
|
f476688c7f | ||
|
|
8845222700 | ||
|
|
e64c464091 | ||
|
|
b2c2d0d7d6 | ||
|
|
1fb61d313c | ||
|
|
ccf5ff632c | ||
|
|
54d6aaf56f | ||
|
|
736b262947 | ||
|
|
6a07127185 | ||
|
|
45f0ba7c0e | ||
|
|
6f4ea68778 | ||
|
|
90dda20891 | ||
|
|
278eb01c2f | ||
|
|
c3157de146 | ||
|
|
d28db485c5 | ||
|
|
caa0076396 | ||
|
|
451da40ed2 | ||
|
|
47694e7b72 | ||
|
|
e01fb7f9ae | ||
|
|
ffcdfb6a6a | ||
|
|
86f0d013bb | ||
|
|
c12ac45890 | ||
|
|
47ce68455a | ||
|
|
c1675e4b49 | ||
|
|
f8c4d39b93 | ||
|
|
e55cf5ecc6 | ||
|
|
406cf22810 | ||
|
|
8ff46bab5b | ||
|
|
5f177785b6 | ||
|
|
06779f36ca | ||
|
|
29991015b5 | ||
|
|
071a6ff8bb | ||
|
|
5b8df4c414 | ||
|
|
ce6873fe54 | ||
|
|
d0e64364e3 | ||
|
|
737ffb4c35 | ||
|
|
53048ac8ef | ||
|
|
05ca1a09b9 | ||
|
|
94e398dd1c | ||
|
|
7c0a4f61e9 | ||
|
|
056d3215e8 | ||
|
|
a68b2093e4 | ||
|
|
f440f57be2 | ||
|
|
edbdbcf38e | ||
|
|
94a067e34b | ||
|
|
8b6b904cd6 | ||
|
|
27cd8086e1 | ||
|
|
6aa109131e | ||
|
|
74777e54f9 | ||
|
|
61e7450906 | ||
|
|
6a55319e04 | ||
|
|
5692d4e74c | ||
|
|
ffe89d0fe0 | ||
|
|
77e1390686 |
+5
-2
@@ -51,7 +51,8 @@
|
||||
"ul": ["list"],
|
||||
"ol": ["list"]
|
||||
}
|
||||
]
|
||||
],
|
||||
"no-console": ["error", { "allow": ["warn", "error"] }]
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -72,9 +73,11 @@
|
||||
"error",
|
||||
{
|
||||
"prefer": "type-imports",
|
||||
"disallowTypeAnnotations": true
|
||||
"disallowTypeAnnotations": true,
|
||||
"fixStyle": "inline-type-imports"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-useless-constructor": 0,
|
||||
"curly": ["error", "multi-line"]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* text eol=lf
|
||||
*.png binary
|
||||
*.ico binary
|
||||
*.woff2 binary
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Related issues 🔗
|
||||
|
||||
Issue: #[Issue number here]
|
||||
Closes #[Issue number here]
|
||||
|
||||
# Description ℹ️
|
||||
|
||||
|
||||
@@ -82,3 +82,38 @@ jobs:
|
||||
https://${{ env.IPFS_V1 }}.ipfs.dweb.link/
|
||||
https://${{ env.IPFS_V1 }}.ipfs.cf-ipfs.com/
|
||||
ipfs://${{ env.IPFS_V0 }}/
|
||||
|
||||
- name: Ensure 'Released' label exists
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
REPO="${{ github.repository }}"
|
||||
LABEL_EXIST=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$REPO/labels/Released")
|
||||
if [[ "$LABEL_EXIST" == *"Not Found"* ]]; then
|
||||
curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-X POST "https://api.github.com/repos/$REPO/labels" \
|
||||
-d '{"name": "Released", "color": "FFFFFF"}'
|
||||
fi
|
||||
|
||||
- name: Extract issues from release notes
|
||||
id: extract-issues
|
||||
run: |
|
||||
ISSUES=$(echo "${{ github.event.release.body }}" | grep -o -E '#[0-9]+' | tr -d '#' | jq -R . | jq -cs .)
|
||||
echo "Issues to label: $ISSUES"
|
||||
echo "::set-output name=issue_numbers::$ISSUES"
|
||||
|
||||
- name: Add 'Released' label to issues
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
ISSUE_NUMBERS="${{ steps.extract-issues.outputs.issue_numbers }}"
|
||||
REPO="${{ github.repository }}"
|
||||
for ISSUE in $(echo "$ISSUE_NUMBERS" | jq -r '.[]'); do
|
||||
curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-X POST "https://api.github.com/repos/$REPO/issues/$ISSUE/labels" \
|
||||
-d '{"labels": ["Released"]}'
|
||||
done
|
||||
|
||||
@@ -5,15 +5,17 @@ on:
|
||||
branches:
|
||||
- release/*
|
||||
- develop
|
||||
- main
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
jobs:
|
||||
node-modules:
|
||||
# All jobs depend on node_modules, so none should run if the PR is in draft
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-22.04
|
||||
name: 'Cache yarn modules'
|
||||
steps:
|
||||
@@ -21,7 +23,6 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Cache node modules
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
@@ -33,29 +34,21 @@ jobs:
|
||||
${{ runner.os }}-cache-node-modules-
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
|
||||
- name: yarn install
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: yarn install --pure-lockfile
|
||||
|
||||
lint-pr-title:
|
||||
needs: node-modules
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
name: Verify PR title
|
||||
uses: ./.github/workflows/lint-pr.yml
|
||||
secrets: inherit
|
||||
|
||||
lint-test-build:
|
||||
timeout-minutes: 60
|
||||
lint-format:
|
||||
timeout-minutes: 20
|
||||
needs: node-modules
|
||||
runs-on: ubuntu-22.04
|
||||
name: '(CI) lint + unit test + build'
|
||||
name: '(CI) lint + format check'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
@@ -64,7 +57,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
@@ -81,6 +74,76 @@ jobs:
|
||||
with:
|
||||
main-branch-name: develop
|
||||
|
||||
- name: Check formatting
|
||||
run: yarn nx format:check
|
||||
|
||||
- name: Lint affected
|
||||
run: yarn nx affected:lint --max-warnings=0
|
||||
|
||||
- name: Build affected spec
|
||||
run: yarn nx affected --target=build-spec
|
||||
|
||||
test-affected:
|
||||
timeout-minutes: 30
|
||||
needs: build-sources
|
||||
runs-on: ubuntu-22.04
|
||||
name: 'run unit test of affected apps'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v3
|
||||
with:
|
||||
main-branch-name: develop
|
||||
|
||||
- name: Test affected
|
||||
run: yarn nx affected:test
|
||||
|
||||
build-sources:
|
||||
timeout-minutes: 30
|
||||
needs: lint-format
|
||||
runs-on: ubuntu-22.04
|
||||
name: 'Build sources of affected apps'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v3
|
||||
with:
|
||||
main-branch-name: develop
|
||||
|
||||
# See affected apps
|
||||
- name: See affected apps
|
||||
run: |
|
||||
@@ -97,21 +160,8 @@ jobs:
|
||||
echo "preview_explorer: ${{ env.PREVIEW_EXPLORER }}"
|
||||
echo "preview_tools: ${{ env.PREVIEW_TOOLS }}"
|
||||
|
||||
- name: Check formatting
|
||||
run: yarn nx format:check
|
||||
|
||||
- name: Lint affected
|
||||
run: yarn nx affected:lint --max-warnings=0
|
||||
|
||||
- name: Build affected spec
|
||||
run: yarn nx affected --target=build-spec
|
||||
|
||||
- name: Test affected
|
||||
run: yarn nx affected:test
|
||||
|
||||
- name: Build affected
|
||||
run: yarn nx affected:build || (yarn install && yarn nx affected:build)
|
||||
|
||||
outputs:
|
||||
projects: ${{ env.PROJECTS }}
|
||||
projects-e2e: ${{ env.PROJECTS_E2E }}
|
||||
@@ -120,39 +170,62 @@ jobs:
|
||||
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
|
||||
preview_tools: ${{ env.PREVIEW_TOOLS }}
|
||||
|
||||
console-e2e:
|
||||
needs: lint-test-build
|
||||
name: '(CI) console python'
|
||||
uses: ./.github/workflows/console-test-run.yml
|
||||
secrets: inherit
|
||||
if: ${{ contains(fromJSON(needs.lint-test-build.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
|
||||
with:
|
||||
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
check-e2e-needed:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-sources
|
||||
name: '(CI) check if e2e needed'
|
||||
outputs:
|
||||
run-tests: ${{ steps.check-test.outputs.e2e-needed }}
|
||||
steps:
|
||||
- name: Check branch
|
||||
id: check-test
|
||||
run: |
|
||||
if [[ "${{ github.base_ref }}" == "develop" ]]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.base_ref }}" == "main" ]]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/"* ]]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "e2e-needed=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Print result
|
||||
run: |
|
||||
echo "e2e-needed: ${{ steps.check-test.outputs.e2e-needed }}"
|
||||
|
||||
cypress:
|
||||
needs: lint-test-build
|
||||
needs: [build-sources, check-e2e-needed]
|
||||
name: '(CI) cypress'
|
||||
# if: ${{ needs.lint-test-build.outputs.projects-e2e != '[]' }}
|
||||
if: ${{ needs.check-e2e-needed.outputs.run-tests == 'true' }}
|
||||
uses: ./.github/workflows/cypress-run.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
projects: ${{ needs.lint-test-build.outputs.projects-e2e }}
|
||||
projects: ${{ needs.build-sources.outputs.projects-e2e }}
|
||||
tags: '@smoke'
|
||||
|
||||
console-e2e:
|
||||
needs: [build-sources, check-e2e-needed]
|
||||
name: '(CI) trading e2e python'
|
||||
uses: ./.github/workflows/console-test-run.yml
|
||||
secrets: inherit
|
||||
if: needs.check-e2e-needed.outputs.run-tests == 'true' && contains(needs.build-sources.outputs.projects, 'trading')
|
||||
with:
|
||||
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
publish-dist:
|
||||
needs: lint-test-build
|
||||
needs: build-sources
|
||||
name: '(CD) publish dist'
|
||||
if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'vegaprotocol/frontend-monorepo') || github.event_name == 'push' }}
|
||||
uses: ./.github/workflows/publish-dist.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
projects: ${{ needs.lint-test-build.outputs.projects }}
|
||||
projects: ${{ needs.build-sources.outputs.projects }}
|
||||
|
||||
dist-check:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- publish-dist
|
||||
- lint-test-build
|
||||
- build-sources
|
||||
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'vegaprotocol/frontend-monorepo' }}
|
||||
timeout-minutes: 60
|
||||
name: '(CD) comment preview links'
|
||||
@@ -168,27 +241,27 @@ jobs:
|
||||
run: |
|
||||
# https://stackoverflow.com/questions/3183444/check-for-valid-link-url
|
||||
regex='(https?|ftp|file)://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
|
||||
if [[ "${{ needs.lint-test-build.outputs.preview_governance }}" =~ $regex ]]; then
|
||||
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_governance }}"; do
|
||||
echo "waiting for governance preview: ${{ needs.lint-test-build.outputs.preview_governance }}"
|
||||
if [[ "${{ needs.build-sources.outputs.preview_governance }}" =~ $regex ]]; then
|
||||
until curl --insecure --location --fail "${{ needs.build-sources.outputs.preview_governance }}"; do
|
||||
echo "waiting for governance preview: ${{ needs.build-sources.outputs.preview_governance }}"
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
if [[ "${{ needs.lint-test-build.outputs.preview_explorer }}" =~ $regex ]]; then
|
||||
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_explorer }}"; do
|
||||
echo "waiting for explorer preview: ${{ needs.lint-test-build.outputs.preview_explorer }}"
|
||||
if [[ "${{ needs.build-sources.outputs.preview_explorer }}" =~ $regex ]]; then
|
||||
until curl --insecure --location --fail "${{ needs.build-sources.outputs.preview_explorer }}"; do
|
||||
echo "waiting for explorer preview: ${{ needs.build-sources.outputs.preview_explorer }}"
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
if [[ "${{ needs.lint-test-build.outputs.preview_trading }}" =~ $regex ]]; then
|
||||
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_trading }}"; do
|
||||
echo "waiting for trading preview: ${{ needs.lint-test-build.outputs.preview_trading }}"
|
||||
if [[ "${{ needs.build-sources.outputs.preview_trading }}" =~ $regex ]]; then
|
||||
until curl --insecure --location --fail "${{ needs.build-sources.outputs.preview_trading }}"; do
|
||||
echo "waiting for trading preview: ${{ needs.build-sources.outputs.preview_trading }}"
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
if [[ "${{ needs.lint-test-build.outputs.preview_tools }}" =~ $regex ]]; then
|
||||
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_tools }}"; do
|
||||
echo "waiting for tools preview: ${{ needs.lint-test-build.outputs.preview_tools }}"
|
||||
if [[ "${{ needs.build-sources.outputs.preview_tools }}" =~ $regex ]]; then
|
||||
until curl --insecure --location --fail "${{ needs.build-sources.outputs.preview_tools }}"; do
|
||||
echo "waiting for tools preview: ${{ needs.build-sources.outputs.preview_tools }}"
|
||||
sleep 5
|
||||
done
|
||||
fi
|
||||
@@ -200,10 +273,10 @@ jobs:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
Previews
|
||||
* governance: ${{ needs.lint-test-build.outputs.preview_governance }}
|
||||
* explorer: ${{ needs.lint-test-build.outputs.preview_explorer }}
|
||||
* trading: ${{ needs.lint-test-build.outputs.preview_trading }}
|
||||
* tools: ${{ needs.lint-test-build.outputs.preview_tools }}
|
||||
* governance: ${{ needs.build-sources.outputs.preview_governance }}
|
||||
* explorer: ${{ needs.build-sources.outputs.preview_explorer }}
|
||||
* trading: ${{ needs.build-sources.outputs.preview_trading }}
|
||||
* tools: ${{ needs.build-sources.outputs.preview_tools }}
|
||||
|
||||
# Report single result at the end, to avoid mess with required checks in PR
|
||||
cypress-check:
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#managing-caches
|
||||
name: cleanup caches by a branch
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
echo "Fetching list of cache key"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
@@ -6,23 +6,37 @@ on:
|
||||
github-sha:
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
console-test-branch:
|
||||
type: choice
|
||||
description: 'main: v0.73.5, develop: v0.73.5'
|
||||
options:
|
||||
- main
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
run-tests:
|
||||
name: run-tests
|
||||
runs-on: 8-cores
|
||||
timeout-minutes: 20
|
||||
create-docker-image:
|
||||
name: Create docker image for console-test
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
#----------------------------------------------
|
||||
# check-out frontend-monorepo
|
||||
#----------------------------------------------
|
||||
- name: Checkout console test repo
|
||||
- name: Checkout frontend-monorepo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ inputs.github-sha }}
|
||||
ref: ${{ inputs.github-sha || github.sha }}
|
||||
#----------------------------------------------
|
||||
# cache node modules
|
||||
#----------------------------------------------
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
|
||||
- name: Cache node modules
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
@@ -33,15 +47,6 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cache-node-modules-
|
||||
#----------------------------------------------
|
||||
# setup node
|
||||
#----------------------------------------------
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
#----------------------------------------------
|
||||
# install deps if cache missing
|
||||
#----------------------------------------------
|
||||
- name: yarn install
|
||||
@@ -50,39 +55,124 @@ jobs:
|
||||
#----------------------------------------------
|
||||
# build trading
|
||||
#----------------------------------------------
|
||||
- name: Build affected spec
|
||||
- name: Build trading app
|
||||
run: |
|
||||
yarn env-cmd -f ./apps/trading/.env.stagnet1 yarn nx export trading
|
||||
DIST_LOCATION=dist/apps/trading/exported
|
||||
mv $DIST_LOCATION dist-result
|
||||
tree dist-result
|
||||
|
||||
#----------------------------------------------
|
||||
# run trading server
|
||||
# export trading app docker image
|
||||
#----------------------------------------------
|
||||
- name: Run trading server
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and export to local Docker
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/node-outside-docker.Dockerfile
|
||||
load: true
|
||||
build-args: |
|
||||
APP=trading
|
||||
ENV_NAME=stagnet1
|
||||
tags: ci/trading:local
|
||||
outputs: type=docker,dest=/tmp/console-image.tar
|
||||
|
||||
- name: Verify docker image created
|
||||
run: |
|
||||
docker run -d -p 80:4200 -v $PWD/docker/nginx.conf:/etc/nginx/conf.d/default.conf -v $PWD/dist/apps/trading/exported:/usr/share/nginx/html nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
|
||||
sleep 5
|
||||
docker ps
|
||||
#----------------------------------------------
|
||||
# check if container persists between runs
|
||||
#----------------------------------------------
|
||||
- name: Check server
|
||||
echo ${{ steps.docker_build.outputs.digest }}
|
||||
echo ${{ steps.docker_build.outputs.imageid }}
|
||||
|
||||
- name: Upload docker image for console-test usage
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: console-image
|
||||
path: /tmp/console-image.tar
|
||||
|
||||
console-test-branch:
|
||||
name: Choose console-test branch to run on
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
console-branch: ${{ steps.output-step.outputs.branch }}
|
||||
steps:
|
||||
- name: Workflow dispatch input
|
||||
id: dispatch-step
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: echo "branch=${{ inputs.console-test-branch }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Print Workflow dispatch input
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: echo ${{ steps.dispatch-step.outputs.branch }}
|
||||
|
||||
- name: Workflow_call input
|
||||
id: workflow_call-step
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
run: |
|
||||
docker ps
|
||||
if [[ "${{ github.base_ref }}" == "main" ]]; then
|
||||
echo "branch=main" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.base_ref }}" == "develop" && "${{ github.ref_name }}" == "main" ]]; then
|
||||
echo "branch=main" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/mainnet"* ]]; then
|
||||
echo "branch=main" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "branch=develop" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Print Workflow_call input
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
run: echo ${{ steps.workflow_call-step.outputs.branch }}
|
||||
|
||||
- name: Set output
|
||||
id: output-step
|
||||
run: echo "branch=${{ steps.dispatch-step.outputs.branch || steps.workflow_call-step.outputs.branch }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Print final output
|
||||
run: echo ${{ steps.output-step.outputs.branch }}
|
||||
|
||||
run-tests:
|
||||
name: run-tests
|
||||
runs-on: 8-cores
|
||||
needs: [create-docker-image, console-test-branch]
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
#----------------------------------------------
|
||||
# check-out tests repo
|
||||
# load docker image
|
||||
#----------------------------------------------
|
||||
- name: Checkout console test repo
|
||||
- name: Download docker image from previous job
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: console-image
|
||||
path: /tmp
|
||||
|
||||
- name: Load Docker image
|
||||
run: |
|
||||
docker load --input /tmp/console-image.tar
|
||||
docker image ls -a
|
||||
#----------------------------------------------
|
||||
# check-out frontend-monorepo
|
||||
#----------------------------------------------
|
||||
- name: Checkout frontend-monorepo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: vegaprotocol/console-test
|
||||
path: './console-test'
|
||||
ref: ${{ inputs.github-sha || github.sha }}
|
||||
#----------------------------------------------
|
||||
# set-up python
|
||||
# get vega version
|
||||
#----------------------------------------------
|
||||
- name: Set up python
|
||||
id: setup-python
|
||||
- name: Set VEGA_VERSION from .env
|
||||
id: set_vega_version
|
||||
run: echo "VEGA_VERSION=$(grep VEGA_VERSION apps/trading/e2e/.env | cut -d '=' -f2)" >> $GITHUB_ENV
|
||||
#----------------------------------------------
|
||||
# ----- Setup python -----
|
||||
#----------------------------------------------
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10.11'
|
||||
python-version: '3.10'
|
||||
#----------------------------------------------
|
||||
# ----- install & configure poetry -----
|
||||
#----------------------------------------------
|
||||
@@ -91,45 +181,32 @@ jobs:
|
||||
with:
|
||||
virtualenvs-create: true
|
||||
virtualenvs-in-project: true
|
||||
virtualenvs-path: console-test/.venv
|
||||
virtualenvs-path: .venv
|
||||
|
||||
#----------------------------------------------
|
||||
# load cached venv if cache exists
|
||||
#----------------------------------------------
|
||||
- name: Load cached venv
|
||||
id: cached-poetry-dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: console-test/.venv
|
||||
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
|
||||
#----------------------------------------------
|
||||
# install dependencies if cache does not exist
|
||||
# install python dependencies
|
||||
#----------------------------------------------
|
||||
- name: Install dependencies
|
||||
working-directory: ./console-test
|
||||
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||
run: poetry install --no-interaction --no-root
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# install vega binaries
|
||||
#----------------------------------------------
|
||||
- name: Install vega binaries
|
||||
working-directory: ./console-test
|
||||
run: poetry run python -m vega_sim.tools.load_binaries --force
|
||||
run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# install playwright
|
||||
# install playwrightworking-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
- name: install playwright
|
||||
run: poetry run playwright install
|
||||
working-directory: ./console-test
|
||||
run: poetry run playwright install --with-deps chromium
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# run tests
|
||||
#----------------------------------------------
|
||||
- name: Run tests
|
||||
working-directory: ./console-test
|
||||
run: poetry run pytest -v -s --numprocesses auto --dist loadfile --durations=20
|
||||
- name: Check files
|
||||
run: |
|
||||
ls -al .
|
||||
ls -al console-test
|
||||
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v --numprocesses 1 --dist loadfile --durations=45
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# upload traces
|
||||
#----------------------------------------------
|
||||
@@ -138,5 +215,58 @@ jobs:
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-trace
|
||||
path: ./traces/
|
||||
path: apps/trading/e2e/traces/
|
||||
retention-days: 15
|
||||
#----------------------------------------------
|
||||
# ----- upload logs -----
|
||||
#----------------------------------------------
|
||||
- name: Upload worker logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: worker-logs
|
||||
path: ./logs/
|
||||
retention-days: 15
|
||||
#----------------------------------------------
|
||||
# ----- upload market-sim logs -----
|
||||
#----------------------------------------------
|
||||
- name: Prepare and Zip market-sim-logs
|
||||
if: always()
|
||||
run: |
|
||||
parent_dir="/tmp/market-sim-logs"
|
||||
echo "Creating parent directory at $parent_dir"
|
||||
mkdir -p "$parent_dir"
|
||||
|
||||
echo "Waiting for vega-sim-* folders to be created..."
|
||||
sleep 10 # Waits 10 seconds to ensure all folders are created
|
||||
|
||||
echo "Before searching for vega-sim-* folders in /tmp..."
|
||||
folders=$(find /tmp -mindepth 1 -type d -name 'vega-sim-*' -print) || echo "Find command failed with exit code $?"
|
||||
|
||||
echo "After searching for vega-sim-* folders in /tmp..."
|
||||
|
||||
if [ -z "$folders" ]; then
|
||||
echo "No vega-sim-* folders found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Moving vega-sim-* folders to $parent_dir"
|
||||
echo "$folders" | xargs -I {} mv {} "$parent_dir/"
|
||||
|
||||
echo "Checking if $parent_dir is not empty..."
|
||||
if [ "$(ls -A $parent_dir)" ]; then
|
||||
echo "Zipping the parent directory..."
|
||||
zip -r market-sim-logs.zip "$parent_dir" && echo "Zip file created successfully."
|
||||
else
|
||||
echo "$parent_dir is empty. No zip file created."
|
||||
exit 0
|
||||
fi
|
||||
shell: /usr/bin/bash -e {0}
|
||||
|
||||
- name: Upload market-sim-logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: market-sim-logs
|
||||
path: market-sim-logs.zip
|
||||
retention-days: 15
|
||||
|
||||
@@ -18,11 +18,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js 16
|
||||
- name: Use Node.js 20
|
||||
id: Node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.15.1
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Run Cypress tests
|
||||
uses: cypress-io/github-action@v4
|
||||
|
||||
@@ -13,13 +13,35 @@ on:
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
runner-choice:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner: ${{ steps.step.outputs.runner }}
|
||||
steps:
|
||||
- name: Check branch
|
||||
id: step
|
||||
run: |
|
||||
if [[ "${{ github.base_ref }}" == "main" ]]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.base_ref }}" == "develop" && "${{ github.ref_name }}" == "main" ]]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/mainnet"* ]]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "runner=self-hosted-runner" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Print runner
|
||||
run: echo ${{ steps.step.outputs.runner }}
|
||||
|
||||
e2e:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
project: ${{ fromJSON(inputs.projects) }}
|
||||
name: ${{ matrix.project }}
|
||||
runs-on: self-hosted-runner
|
||||
needs: runner-choice
|
||||
runs-on: ${{ needs.runner-choice.outputs.runner }}
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
# Checks if skip cache was requested
|
||||
@@ -35,8 +57,17 @@ jobs:
|
||||
path: './frontend-monorepo'
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: './frontend-monorepo/.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
cache-dependency-path: './frontend-monorepo/yarn.lock'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
@@ -46,6 +77,7 @@ jobs:
|
||||
|
||||
# Install frontend dependencies
|
||||
- name: Install root dependencies
|
||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
@@ -61,13 +93,14 @@ jobs:
|
||||
- name: Run Vegacapsule network and Vega wallet
|
||||
id: setup-vega
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
timeout-minutes: 10
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
######
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --browser chrome --env.grepTags="${{ inputs.tags }}"
|
||||
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --browser chrome --env.grepTags="${{ inputs.tags }}"
|
||||
working-directory: frontend-monorepo
|
||||
env:
|
||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
name: Verify PR title
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
lint_pr:
|
||||
@@ -11,21 +16,16 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
rm package.json
|
||||
npm install --no-save @commitlint/cli @commitlint/config-conventional @commitlint/config-nx-scopes nx
|
||||
|
||||
- name: Check PR title
|
||||
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
|
||||
|
||||
@@ -30,12 +30,18 @@ jobs:
|
||||
echo IS_IPFS_RELEASE=false >> $GITHUB_ENV
|
||||
echo IS_S3_RELEASE=false >> $GITHUB_ENV
|
||||
echo IS_DEV_IMAGE=false >> $GITHUB_ENV
|
||||
echo IS_MAIN_IMAGE=false >> $GITHUB_ENV
|
||||
|
||||
- name: Is dev image
|
||||
if: ${{ contains(github.ref, 'develop') && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
if: ${{ github.ref_name == 'develop' && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
run: |
|
||||
echo IS_DEV_IMAGE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is main image
|
||||
if: ${{ github.ref_name == 'main' && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
run: |
|
||||
echo IS_MAIN_IMAGE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is PR
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
@@ -57,7 +63,7 @@ jobs:
|
||||
echo IS_IPFS_RELEASE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is S3 Release
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' && github.ref_name != 'main'}}
|
||||
run: |
|
||||
echo IS_S3_RELEASE=true >> $GITHUB_ENV
|
||||
|
||||
@@ -81,13 +87,13 @@ jobs:
|
||||
|
||||
- name: Log in to the Container registry (docker hub)
|
||||
uses: docker/login-action@v2
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' || env.IS_MAIN_IMAGE == 'true' }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
@@ -155,10 +161,10 @@ jobs:
|
||||
- name: Sanity check docker image
|
||||
run: |
|
||||
echo "Check ipfs-hash"
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matrix.app }}-ipfs-hash
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'cat /ipfs-hash'
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'cat /ipfs-hash' > ${{ matrix.app }}-ipfs-hash
|
||||
echo "List html directory"
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree /usr/share/nginx/html'
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'apk add --update tree; tree /usr/share/nginx/html'
|
||||
|
||||
- name: Publish dist as docker image (ghcr)
|
||||
uses: docker/build-push-action@v3
|
||||
@@ -179,7 +185,7 @@ jobs:
|
||||
uses: docker/build-push-action@v3
|
||||
continue-on-error: true
|
||||
id: dockerhub-push
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' || env.IS_MAIN_IMAGE == 'true' }}
|
||||
with:
|
||||
context: .
|
||||
file: docker/node-outside-docker.Dockerfile
|
||||
@@ -189,7 +195,7 @@ jobs:
|
||||
ENV_NAME=${{ env.ENV_NAME }}
|
||||
tags: |
|
||||
vegaprotocol/${{ matrix.app }}:${{ github.sha }}
|
||||
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || '' }}
|
||||
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true' && 'main' || '' }}
|
||||
|
||||
- name: Publish dist as docker image (ghcr - retry)
|
||||
uses: docker/build-push-action@v3
|
||||
@@ -216,7 +222,7 @@ jobs:
|
||||
ENV_NAME=${{ env.ENV_NAME }}
|
||||
tags: |
|
||||
vegaprotocol/${{ matrix.app }}:${{ github.sha }}
|
||||
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || '' }}
|
||||
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true' && 'main' || '' }}
|
||||
|
||||
# bucket creation in github.com/vegaprotocol/terraform//frontend
|
||||
- name: Publish dist to s3
|
||||
@@ -329,7 +335,9 @@ jobs:
|
||||
fi
|
||||
|
||||
# create commit
|
||||
commit_msg="Automated hash update from ${{ github.ref }}"
|
||||
git commit -m "$commit_msg"
|
||||
git push -u origin "main"
|
||||
if ! git diff --cached --exit-code; then
|
||||
commit_msg="Automated hash update from ${{ github.ref }}"
|
||||
git commit -m "$commit_msg"
|
||||
git push -u origin "main"
|
||||
fi
|
||||
)
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
|
||||
+9
-1
@@ -48,7 +48,15 @@ cypress.env.json
|
||||
# Next.js
|
||||
.next
|
||||
|
||||
#cypress
|
||||
# cypress
|
||||
/apps/**/cypress/reports/
|
||||
/apps/**/cypress/downloads/
|
||||
/apps/**/fixtures/wallet/node**
|
||||
|
||||
# apps/trading/e2e
|
||||
__pycache__/
|
||||
apps/trading/e2e/logs/
|
||||
apps/trading/e2e/.pytest_cache/
|
||||
apps/trading/e2e/traces/
|
||||
|
||||
.nx/
|
||||
|
||||
@@ -3,6 +3,3 @@
|
||||
|
||||
# Lint commit messages to ensure they follow conventional commit standards
|
||||
yarn commitlint --edit "${1}"
|
||||
|
||||
# Lint all staged files
|
||||
yarn lint-staged
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
# Auto-format all files
|
||||
yarn nx format:write
|
||||
|
||||
# Lint all staged files
|
||||
yarn lint-staged
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
# Lint all staged files - this brings more value as pre-commit
|
||||
# yarn nx format:check
|
||||
|
||||
# Test all projects with changes
|
||||
# yarn nx affected -t test --exclude trading
|
||||
@@ -1,6 +1,7 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
|
||||
/dist
|
||||
/dist-result
|
||||
/coverage
|
||||
__generated__
|
||||
__generated___
|
||||
@@ -8,3 +9,15 @@ __generated___
|
||||
apps/static/src/assets/devnet-tranches.json
|
||||
apps/static/src/assets/mainnet-tranches.json
|
||||
apps/static/src/assets/testnet-tranches.json
|
||||
|
||||
/apps/**/cypress/reports/
|
||||
/apps/**/cypress/downloads/
|
||||
|
||||
/.nx/cache
|
||||
|
||||
# apps/trading/e2e
|
||||
__pycache__/
|
||||
apps/trading/e2e/logs/
|
||||
apps/trading/e2e/.pytest_cache/
|
||||
apps/trading/e2e/traces/
|
||||
.pytest_cache/
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
* @vegaprotocol/frontend
|
||||
apps/ @vegaprotocol/frontend-qa
|
||||
libs/ @vegaprotocol/frontend-qa
|
||||
*.graphql @vegaprotocol/core
|
||||
|
||||
@@ -11,7 +11,7 @@ recalculate-ipfs:
|
||||
echo "ipfs hash inside the image"
|
||||
docker run --rm ${TAG} cat /ipfs-hash
|
||||
echo "recalculating ipfs hash"
|
||||
docker run --rm ${TAG} ipfs add -r /usr/share/nginx/html
|
||||
docker run --rm ${TAG} ipfs add -rQ /usr/share/nginx/html
|
||||
|
||||
.PHONY: eject-ipfs-hash
|
||||
unpack:
|
||||
|
||||
@@ -4,7 +4,7 @@ The front-end monorepo provides a toolkit for building apps that interact with V
|
||||
|
||||
This repository is managed using [Nx](https://nx.dev).
|
||||
|
||||
# 🔎 Applications in this repo
|
||||
## 🔎 Applications in this repo
|
||||
|
||||
### [Block explorer](./apps/explorer)
|
||||
|
||||
@@ -30,7 +30,7 @@ Hosting for static content being shared across apps, for example fonts.
|
||||
|
||||
The utility dApp for validators wishing to add or remove themselves as a signer of the multisig contract.
|
||||
|
||||
# 🧱 Libraries in this repo
|
||||
## 🧱 Libraries in this repo
|
||||
|
||||
### [UI toolkit](./libs/ui-toolkit)
|
||||
|
||||
@@ -53,7 +53,7 @@ A utility library for connecting to the Ethereum network and interacting with Ve
|
||||
|
||||
Generic react helpers that can be used across multiple applications, along with other utilities.
|
||||
|
||||
# 💻 Develop
|
||||
## 💻 Develop
|
||||
|
||||
### Set up
|
||||
|
||||
@@ -103,7 +103,7 @@ In CI linting, formatting and also run. These checks can be seen in the [CI work
|
||||
|
||||
Visit the [Nx Documentation](https://nx.dev/getting-started/intro) to learn more.
|
||||
|
||||
# 🐋 Hosting a console
|
||||
## 🐋 Hosting a console
|
||||
|
||||
To host a console there are two possible build scenarios for running the frontends: nx performed **outside** or **inside** docker build. For specific build instructions follow [build instructions](#build-instructions).
|
||||
|
||||
@@ -113,13 +113,47 @@ In order to run a container on port 3000:
|
||||
docker run -p 3000:80 [TAG]
|
||||
```
|
||||
|
||||
On top of that there are two possible scenarios for running docker image - using nginx server (default) of ipfs daemon.
|
||||
|
||||
to run ipfs on port 3000:
|
||||
|
||||
```bash
|
||||
docker run -p 3000:80 [TAG] /run-ipfs.sh
|
||||
```
|
||||
|
||||
to run nginx on port 3000:
|
||||
|
||||
```bash
|
||||
docker run -p 3000:80 [TAG]
|
||||
```
|
||||
|
||||
## Build instructions
|
||||
|
||||
The [`docker`](./docker) subfolder has some docker configurations for easily setting up your own hosted version of console either for the web, or ready for pinning on IPFS
|
||||
The [`docker`](./docker) subfolder has some docker configurations for easily setting up your own hosted version of Console either for the web, or ready for pinning on IPFS.
|
||||
|
||||
### nx build inside the docker
|
||||
|
||||
Using multistage dockerfile dist is compiled using [node](https://hub.docker.com/_/node) image and later packed to nginx as in [dist build](#dist-build). The multistage builds ensures consistent CPU architecture and build toolchains are used so that the result will be identical.
|
||||
|
||||
```bash
|
||||
docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=20.9.1 --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
|
||||
```
|
||||
|
||||
### Computing ipfs-hash of the build
|
||||
|
||||
At the moment this feature is important only for Console releases.
|
||||
|
||||
Each docker build finishes with hash calculation for ` dist`` directory. Resulting hash is added to file named as `/ipfs-hash`. Once docker image is produced you can run following commad to display ipfs-hash:
|
||||
|
||||
```bash
|
||||
make recalculate-ipfs TAG=vegaprotocol/trading:{YOUR_VERSION}
|
||||
```
|
||||
|
||||
**updating hash:** recompiling dist directory (even if there are no changed to source code) results in different hash computed by ipfs command.
|
||||
|
||||
### nx build outside the docker
|
||||
|
||||
Packaging prepared dist into [`nginx`](https://hub.docker.com/_/nginx)([server configuration](./nginx/nginx.conf)) docker image involves building the application on docker host machine from source.
|
||||
This Docker image packages a pre-built `dist` folder into an [`nginx`](https://hub.docker.com/_/nginx)([server configuration](./nginx/nginx.conf)) docker image. In this case, the application on docker host machine from source.
|
||||
|
||||
As a prerequisite you need to perform build of `dist` directory and move its content for specific application to `dist-result` directory. Use following script to do it with a single command:
|
||||
|
||||
@@ -130,41 +164,21 @@ As a prerequisite you need to perform build of `dist` directory and move its con
|
||||
You can build any of the containers locally with the following command:
|
||||
|
||||
```bash
|
||||
docker build --dockerfile docker/node-outside-docker.Dockerfile . --tag=[TAG]
|
||||
docker build -f docker/node-outside-docker.Dockerfile . --tag=[TAG]
|
||||
```
|
||||
|
||||
### nx build inside the docker
|
||||
|
||||
Using multistage dockerfile dist is compiled using [node](https://hub.docker.com/_/node) image and later packed to nginx as in [dist build](#dist-build) example.
|
||||
|
||||
```bash
|
||||
docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=$(cat .nvmrc) --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
|
||||
```
|
||||
|
||||
### Computing ipfs-hash of the build
|
||||
|
||||
At the moment this feature is important only for `trading` (console) releases.
|
||||
|
||||
Each docker build finishes with hash calculation for dist directory. Resulting hash is added to file named as `/ipfs-hash`. Once docker image is produced you can run following commad to display ipfs-hash:
|
||||
|
||||
```bash
|
||||
make recalculate-ipfs TAG=vegaprotocol/trading:{YOUR_VERSION}
|
||||
```
|
||||
|
||||
**updating hash:** recompiling dist directory (even if there are no changed to source code) results in different hash computed by ipfs command.
|
||||
|
||||
### Verifying ipfs-hash of existing current application version
|
||||
|
||||
An IPFS CID will be attached to every [release](https://github.com/vegaprotocol/frontend-monorepo/releases). If you are intending to pin an application on IPFS, you can check that your build matches by running the following steps:
|
||||
|
||||
1. Show latest release by runnning: `make latest-release`. You need to configure [`gh`](https://cli.github.com/) for this step to work, otherwise please provide release manually from [github](https://github.com/vegaprotocol/frontend-monorepo/releases) or [dockerhub](https://hub.docker.com/r/vegaprotocol/trading)
|
||||
1. Show latest release by running: `make latest-release`. You need to configure [`gh`](https://cli.github.com/) for this step to work, otherwise please provide release manually from [github](https://github.com/vegaprotocol/frontend-monorepo/releases) or [dockerhub](https://hub.docker.com/r/vegaprotocol/trading)
|
||||
2. Set RELEASE environment variable to value that you want to validate: `export RELEASE=$(make latest-release)` or `export RELEASE=vXX.XX.XX`
|
||||
3. Set TAG environment variable to image that you want to validate: `export TAG=vegaprotocol/trading:$RELEASE`
|
||||
4. Download docker image with the desired release `docker pull $TAG`.
|
||||
5. Recalculate hash: `make recalculate-ipfs`
|
||||
6. You should see exactly same hash produced by ipfs command as one placed with the release notes: `make show-latest-release`
|
||||
7. If you want to extract dist from docker image to your local filesystem you can run following command: `make unpack`
|
||||
8. Now `dist` directory contains valid application build. **it is not possible to calculate same ipfs hash on files that are result of copy operation**
|
||||
8. Now `dist` directory contains valid application build
|
||||
|
||||
## Config
|
||||
|
||||
@@ -212,6 +226,6 @@ Note: The script is only needed if capsule was built for first time or fresh. To
|
||||
vega wallet service run -n DV --load-tokens --tokens-passphrase-file passphrase --no-version-check --automatic-consent --home ~/.vegacapsule/testnet/wallet
|
||||
```
|
||||
|
||||
# 📑 License
|
||||
## 📑 License
|
||||
|
||||
[MIT](./LICENSE)
|
||||
|
||||
@@ -16,5 +16,10 @@ NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
|
||||
CYPRESS_VEGA_WALLET_API_TOKEN=
|
||||
CYPRESS_VEGA_URL=http://localhost:3008/graphql
|
||||
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
|
||||
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
|
||||
CYPRESS_FAUCET_URL=http://localhost:1790/api/v1/mint
|
||||
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
|
||||
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
|
||||
CYPRESS_VEGA_WALLET_API_TOKEN=
|
||||
|
||||
@@ -4,6 +4,8 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
|
||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -4,6 +4,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocke
|
||||
NX_VEGA_URL=https://api.vega.community/graphql
|
||||
NX_VEGA_ENV=MAINNET
|
||||
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -4,6 +4,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
|
||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
"rules": {
|
||||
"cypress/unsafe-to-chain-command": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ module.exports = defineConfig({
|
||||
viewportWidth: 1440,
|
||||
viewportHeight: 900,
|
||||
testIsolation: false,
|
||||
experimentalMemoryManagement: true,
|
||||
},
|
||||
env: {
|
||||
environment: 'CUSTOM',
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/linter:eslint",
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/explorer-e2e/**/*.{js,ts}"]
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"proposalSubmission": {
|
||||
"rationale": {
|
||||
"title": "Test new asset proposal",
|
||||
"description": "E2E test for proposals"
|
||||
},
|
||||
"terms": {
|
||||
"newAsset": {
|
||||
"changes": {
|
||||
"name": "USDT Coin",
|
||||
"symbol": "USDT",
|
||||
"decimals": "18",
|
||||
"quantum": "1",
|
||||
"erc20": {
|
||||
"contractAddress": "0xb404c51bbc10dcbe948077f18a4b8e553d160084",
|
||||
"withdrawThreshold": "10",
|
||||
"lifetimeLimit": "10"
|
||||
}
|
||||
}
|
||||
},
|
||||
"closingTimestamp": 1724339572,
|
||||
"enactmentTimestamp": 1724339572,
|
||||
"validationTimestamp": 1692799617
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,168 @@
|
||||
//Tests set to skip until market bug for capsule checkpoint is fixed
|
||||
context.skip('Market page', { tags: '@regression' }, function () {
|
||||
describe('Verify elements on page', function () {
|
||||
const marketHeaders = '[data-testid="markets-header"]';
|
||||
const marketNavigation = 'a[href="/markets"]';
|
||||
import { createSuccessorMarketProposal } from '../support/governance.functions';
|
||||
|
||||
it('Markets page is displayed', function () {
|
||||
context('Market page', { tags: '@regression' }, function () {
|
||||
describe('Verify elements on page', function () {
|
||||
const marketHeaders = 'markets-heading';
|
||||
|
||||
before('Create market', function () {
|
||||
cy.visit('/');
|
||||
cy.get(marketNavigation).click();
|
||||
cy.common_validate_blocks_data_displayed(marketHeaders);
|
||||
cy.createMarket();
|
||||
});
|
||||
|
||||
it('Markets page displayed on mobile', function () {
|
||||
beforeEach('Get market id', function () {
|
||||
cy.navigate_to('markets');
|
||||
cy.get('[col-id="id"]').last().invoke('text').as('createdMarketId');
|
||||
});
|
||||
|
||||
it('Market displayed on market page', function () {
|
||||
cy.navigate_to('markets');
|
||||
cy.getByTestId(marketHeaders).should('be.visible');
|
||||
cy.get(`[row-id="${this.createdMarketId}"]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get_element_by_col_id('code').should('have.text', 'TEST.24h');
|
||||
cy.get_element_by_col_id('name').should('have.text', 'Test market 1');
|
||||
cy.get_element_by_col_id('state').should('have.text', 'Pending');
|
||||
cy.get_element_by_col_id('asset').should('have.text', 'fUSDC');
|
||||
cy.get_element_by_col_id('id').should(
|
||||
'have.text',
|
||||
this.createdMarketId
|
||||
);
|
||||
cy.get_element_by_col_id('actions')
|
||||
.find('a')
|
||||
.should('have.attr', 'href', `/markets/${this.createdMarketId}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('Able to go to market details page', function () {
|
||||
cy.navigate_to('markets');
|
||||
cy.contains('Test market 1').click();
|
||||
cy.getByTestId(marketHeaders).should('have.text', 'Test market 1');
|
||||
cy.validate_element_from_table('Name', 'Test market 1');
|
||||
cy.validate_element_from_table('Trading Mode', 'Opening auction');
|
||||
cy.validate_element_from_table('Market Decimal Places', '5');
|
||||
cy.validate_element_from_table('Position Decimal Places', '5');
|
||||
cy.validate_element_from_table('Settlement Asset Decimal Places', '5');
|
||||
// Instrument
|
||||
cy.validate_element_from_table('Market Name', 'Test market 1');
|
||||
cy.validate_element_from_table('Code', 'TEST.24h');
|
||||
cy.validate_element_from_table('Product Type', 'Future');
|
||||
cy.validate_element_from_table('Quote Name', 'fUSDC');
|
||||
// Settlement Asset
|
||||
cy.validate_element_from_table('Quote Name', 'fUSDC');
|
||||
cy.validate_element_from_table('Symbol', 'fUSDC');
|
||||
cy.validate_element_from_table('Decimals', '5');
|
||||
cy.validate_element_from_table('Quantum', '0.00');
|
||||
cy.validate_element_from_table('Status', 'Enabled');
|
||||
cy.validate_element_from_table('Max faucet amount', '10,000,000.00');
|
||||
cy.validate_element_from_table(
|
||||
'Infrastructure fee account balance',
|
||||
'0.00'
|
||||
);
|
||||
cy.validate_element_from_table(
|
||||
'Global reward pool account balance',
|
||||
'0.00'
|
||||
);
|
||||
// Metadata
|
||||
cy.validate_element_from_table('Sector', 'tech');
|
||||
cy.validate_element_from_table('Source', 'docs.vega.xyz');
|
||||
// Risk model
|
||||
cy.validate_element_from_table('Tau', '0.0001140771161');
|
||||
cy.validate_element_from_table('Risk Aversion Parameter', '0.01');
|
||||
// Risk parameters
|
||||
// cy.validate_element_from_table('R', '0.016')
|
||||
cy.validate_element_from_table('Sigma', '0.5');
|
||||
// Risk factors
|
||||
cy.validate_element_from_table('Short', '0.0143218738374871');
|
||||
cy.validate_element_from_table('Long', '0.0141450471498822');
|
||||
// Price monitoring settings 1
|
||||
cy.validate_element_from_table('Horizon Secs', '43,200');
|
||||
cy.validate_element_from_table('Probability', '1');
|
||||
cy.validate_element_from_table('Auction Extension Secs', '600');
|
||||
// Liquidity Monitoring
|
||||
cy.validate_element_from_table('Triggering Ratio', '0.7');
|
||||
cy.validate_element_from_table('Time Window', '3,600');
|
||||
cy.validate_element_from_table('Scaling Factor', '10');
|
||||
// Liquidity
|
||||
cy.validate_element_from_table('Target Stake', '0.00 fUSDC');
|
||||
cy.validate_element_from_table('Supplied Stake', '0.00 fUSDC');
|
||||
// Liquidity price range
|
||||
cy.validate_element_from_table(
|
||||
'Liquidity Price Range',
|
||||
'95.00% of mid price'
|
||||
);
|
||||
cy.validate_element_from_table('Lowest Price', '0.00 fUSDC');
|
||||
cy.validate_element_from_table('Highest Price', '0.00 fUSDC');
|
||||
cy.getByTestId('oracle-spec-links')
|
||||
.should('have.attr', 'href')
|
||||
.and(
|
||||
'contain',
|
||||
'/oracles/bf242aa5c9f64fcbb77808aa8582e73711519f4b35264eb797a80f1803590a24'
|
||||
);
|
||||
|
||||
// Able to view Json
|
||||
cy.contains('View JSON').click();
|
||||
cy.get('.language-json').should('exist');
|
||||
cy.getByTestId('icon-cross').click();
|
||||
});
|
||||
|
||||
// Skipping due to resize observer loop limit error
|
||||
it.skip('Markets page displayed on mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(marketNavigation).click();
|
||||
cy.common_validate_blocks_data_displayed(marketHeaders);
|
||||
cy.navigate_to('markets', true);
|
||||
cy.getByTestId(marketHeaders).should('be.visible');
|
||||
cy.get(`[row-id="${this.createdMarketId}"]`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get_element_by_col_id('code').should('have.text', 'TEST.24h');
|
||||
cy.get_element_by_col_id('name').should('have.text', 'Test market 1');
|
||||
cy.get_element_by_col_id('state').should('have.text', 'Pending');
|
||||
cy.get_element_by_col_id('asset').should('have.text', 'fUSDC');
|
||||
cy.get_element_by_col_id('id').should(
|
||||
'have.text',
|
||||
this.createdMarketId
|
||||
);
|
||||
cy.get_element_by_col_id('actions')
|
||||
.find('a')
|
||||
.should('have.attr', 'href', `/markets/${this.createdMarketId}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('Able to go to market details page for successor market', function () {
|
||||
const successionLineItem = 'succession-line-item';
|
||||
const successionLineMarketId = 'succession-line-item-market-id';
|
||||
|
||||
createSuccessorMarketProposal(this.createdMarketId);
|
||||
cy.navigate_to('markets');
|
||||
cy.reload();
|
||||
cy.contains('Token test market', { timeout: 8000 }).should('be.visible');
|
||||
cy.get('[row-index="0"]')
|
||||
.invoke('attr', 'row-id')
|
||||
.as('successorMarketId');
|
||||
cy.contains('Token test market').click();
|
||||
cy.getByTestId(marketHeaders).should('have.text', 'Token test market');
|
||||
cy.validate_element_from_table('Triggering Ratio', '0.7');
|
||||
cy.validate_element_from_table('Time Window', '3,600');
|
||||
cy.validate_element_from_table('Scaling Factor', '10');
|
||||
|
||||
cy.getByTestId(successionLineItem)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.contains('Test market 1');
|
||||
cy.getByTestId(successionLineMarketId).should(
|
||||
'have.text',
|
||||
this.createdMarketId
|
||||
);
|
||||
});
|
||||
cy.getByTestId(successionLineItem)
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.contains('Token test market');
|
||||
cy.getByTestId(successionLineMarketId).should(
|
||||
'have.text',
|
||||
this.successorMarketId
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
context('Network parameters page', { tags: '@smoke' }, function () {
|
||||
before('navigate to network parameter page', function () {
|
||||
cy.fixture('net_parameter_format_lookup').as('networkParameterFormat');
|
||||
cy.visit('/network-parameters');
|
||||
});
|
||||
describe('Verify elements on page', function () {
|
||||
beforeEach(() => {
|
||||
cy.visit('/network-parameters');
|
||||
});
|
||||
|
||||
const networkParametersHeader = '[data-testid="network-param-header"]';
|
||||
const tableRows = '[data-testid="key-value-table-row"]';
|
||||
|
||||
@@ -16,6 +13,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
|
||||
.and('be.visible');
|
||||
});
|
||||
|
||||
// 0006-NETW-021
|
||||
it('should list each of the network parameters available', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
const numberOfNetworkParametersInSystem =
|
||||
@@ -198,6 +196,19 @@ context('Network parameters page', { tags: '@smoke' }, function () {
|
||||
});
|
||||
});
|
||||
|
||||
// 0006-NETW-022 0006-NETW-023
|
||||
it('governance assets should be correctly grouped', function () {
|
||||
cy.getByTestId('governance')
|
||||
.should('exist')
|
||||
.parent()
|
||||
.should('have.attr', 'href', '/network-parameters#governance');
|
||||
cy.get('[id="governance-proposal-asset"]')
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.getByTestId('key-value-table-row').should('have.length', 8);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to see network parameters - on mobile', function () {
|
||||
cy.switchToMobile();
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
|
||||
@@ -40,7 +40,7 @@ context.skip('Node switcher', { tags: '@regression' }, function () {
|
||||
const errorTypeTxt = 'Error: invalid url';
|
||||
const nodeErrorTxt = 'fakeUrl is not a valid url.';
|
||||
|
||||
cy.getByTestId('node-url-custom').click();
|
||||
cy.getByTestId('node-url-custom').click({ force: true });
|
||||
|
||||
cy.getByTestId(customNodeBtn).within(() => {
|
||||
cy.get('input').clear().type('fakeUrl');
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import { getNewAssetTxBody } from '../support/governance.functions';
|
||||
|
||||
context('Proposal page', { tags: '@smoke' }, function () {
|
||||
describe('Verify elements on page', function () {
|
||||
const proposalHeading = 'proposals-heading';
|
||||
const dateTimeRegex =
|
||||
/(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
|
||||
|
||||
before('Create market proposal', function () {
|
||||
cy.visit('/');
|
||||
cy.createMarket();
|
||||
});
|
||||
|
||||
it('Able to view proposal', function () {
|
||||
const proposalTitle = 'Add Lorem Ipsum market';
|
||||
|
||||
cy.navigate_to('governanceProposals');
|
||||
cy.getByTestId(proposalHeading).should('be.visible');
|
||||
cy.contains(proposalTitle)
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
||||
cy.get_element_by_col_id('type').should('have.text', 'NewMarket');
|
||||
cy.get_element_by_col_id('state').should('have.text', 'Enacted');
|
||||
cy.getByTestId('vote-progress').should('be.visible');
|
||||
cy.getByTestId('vote-progress-bar-for')
|
||||
.invoke('attr', 'style')
|
||||
.should('eq', 'width: 100%;');
|
||||
cy.get('[col-id="cDate"]')
|
||||
.invoke('text')
|
||||
.should('match', dateTimeRegex);
|
||||
cy.get('[col-id="eDate"]')
|
||||
.invoke('text')
|
||||
.should('match', dateTimeRegex);
|
||||
cy.getByTestId('external-link')
|
||||
.should('have.attr', 'href')
|
||||
.and('contains', 'https://governance.fairground.wtf/proposals/');
|
||||
cy.contains('View terms').should('exist').click();
|
||||
});
|
||||
cy.getByTestId('dialog-title').should('have.text', proposalTitle);
|
||||
cy.get('.language-json').should('exist');
|
||||
cy.getByTestId('icon-cross').click();
|
||||
});
|
||||
|
||||
it('Proposal page displayed on mobile', function () {
|
||||
const proposalTitle = 'Add Lorem Ipsum market';
|
||||
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.navigate_to('governanceProposals', true);
|
||||
cy.getByTestId(proposalHeading).should('be.visible');
|
||||
cy.get('[row-index="0"]').within(() => {
|
||||
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('Able to view new asset proposal', function () {
|
||||
const proposalTitle = 'Test new asset proposal';
|
||||
const newAssetProposalBody = getNewAssetTxBody();
|
||||
cy.VegaWalletSubmitProposal(newAssetProposalBody);
|
||||
|
||||
cy.visit('/');
|
||||
cy.navigate_to('governanceProposals');
|
||||
cy.contains(proposalTitle)
|
||||
.parent()
|
||||
.parent()
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
||||
cy.get_element_by_col_id('type').should('have.text', 'NewAsset');
|
||||
cy.get_element_by_col_id('state').should(
|
||||
'have.text',
|
||||
'Waiting for Node Vote'
|
||||
);
|
||||
cy.getByTestId('vote-progress').should('be.visible');
|
||||
cy.getByTestId('vote-progress-bar-against')
|
||||
.invoke('attr', 'style')
|
||||
.should('eq', 'width: 100%;');
|
||||
cy.get('[col-id="cDate"]')
|
||||
.invoke('text')
|
||||
.should('match', dateTimeRegex);
|
||||
cy.get('[col-id="eDate"]')
|
||||
.invoke('text')
|
||||
.should('match', dateTimeRegex);
|
||||
cy.getByTestId('external-link')
|
||||
.should('have.attr', 'href')
|
||||
.and('contains', 'https://governance.fairground.wtf/proposals/');
|
||||
cy.contains('View terms').should('exist').click();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -40,7 +40,7 @@ context.skip('Transactions page', function () {
|
||||
.first()
|
||||
.click({ force: true });
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.log('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
@@ -78,7 +78,7 @@ context.skip('Transactions page', function () {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cy.slack('Unable to find any transactions on page');
|
||||
cy.log('Unable to find any transactions on page');
|
||||
cy.screenshot();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,7 +7,11 @@ context('Validator page', { tags: '@smoke' }, function () {
|
||||
it('should be able to see validator tiles', function () {
|
||||
cy.getNodes().then((nodes) => {
|
||||
nodes.forEach((node) => {
|
||||
cy.get(`[validator-id="${node.id}"]`).should('be.visible');
|
||||
if (node.rankingScore.performanceScore > 0) {
|
||||
cy.get(`[validator-id="${node.id}"]`).should('be.visible');
|
||||
} else {
|
||||
cy.get(`[validator-id="${node.id}"]`).should('not.exist');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ Cypress.Commands.add('switchToMobile', () => {
|
||||
Cypress.Commands.add('common_switch_to_mobile_and_click_toggle', function () {
|
||||
cy.viewport('iphone-x');
|
||||
cy.visit('/');
|
||||
cy.get('[data-testid="open-menu"]').click();
|
||||
cy.get('[data-testid="button-menu-drawer"]').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('monitor_clipboard', () => {
|
||||
@@ -88,3 +88,49 @@ Cypress.Commands.add('convert_number_to_max_four_decimal', (number) => {
|
||||
maximumFractionDigits: 4,
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('navigate_to', (page, mobileView = false) => {
|
||||
const navigation = {
|
||||
transactions: '/txs',
|
||||
blocks: '/blocks',
|
||||
oracles: '/oracles',
|
||||
validators: '/validators',
|
||||
parties: '/parties',
|
||||
assets: '/assets',
|
||||
markets: '/markets',
|
||||
governanceProposals: '/governance',
|
||||
networkParameters: '/network-parameters',
|
||||
genesisParameters: '/genesis',
|
||||
};
|
||||
|
||||
const topLevelRoutes = ['transactions', 'blocks', 'oracles', 'validators'];
|
||||
|
||||
cy.getByTestId('navigation').within(() => {
|
||||
if (!topLevelRoutes.includes(page) && mobileView === false) {
|
||||
cy.getByTestId('other').first().click();
|
||||
}
|
||||
cy.get(`[href="${navigation[page]}"]`).first().click();
|
||||
});
|
||||
cy.url().should('include', navigation[page]);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('get_element_by_col_id', (elementName) => {
|
||||
cy.get(`[col-id="${elementName}"]`);
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'validate_element_from_table',
|
||||
(tableRowName, tableRowValue) => {
|
||||
cy.contains(tableRowName)
|
||||
.parentsUntil("[data-testid='key-value-table-row']")
|
||||
.siblings()
|
||||
.should('have.text', tableRowValue);
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add(
|
||||
'validate_proposal_change_type',
|
||||
(tableRowName, changeType) => {
|
||||
cy.contains(tableRowName).siblings().should('have.text', changeType);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
import { addSeconds, millisecondsToSeconds } from 'date-fns';
|
||||
|
||||
export function createSuccessorMarketProposal(parentMarketId) {
|
||||
cy.VegaWalletSubmitProposal(getSuccessorTxBody(parentMarketId));
|
||||
}
|
||||
|
||||
function getSuccessorTxBody(parentMarketId) {
|
||||
const MIN_CLOSE_SEC = 500;
|
||||
const MIN_ENACT_SEC = 700;
|
||||
|
||||
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
|
||||
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
|
||||
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
|
||||
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
|
||||
|
||||
return {
|
||||
proposalSubmission: {
|
||||
rationale: {
|
||||
title: 'Test successor market proposal details',
|
||||
description: 'E2E test for successor market',
|
||||
},
|
||||
terms: {
|
||||
newMarket: {
|
||||
changes: {
|
||||
decimalPlaces: '5',
|
||||
positionDecimalPlaces: '5',
|
||||
linearSlippageFactor: '0.001',
|
||||
quadraticSlippageFactor: '0',
|
||||
instrument: {
|
||||
name: 'Token test market',
|
||||
code: 'TEST.24h',
|
||||
future: {
|
||||
settlementAsset:
|
||||
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc',
|
||||
quoteName: 'fUSDC',
|
||||
dataSourceSpecForSettlementData: {
|
||||
external: {
|
||||
oracle: {
|
||||
signers: [
|
||||
{
|
||||
pubKey: {
|
||||
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||
},
|
||||
},
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
key: {
|
||||
name: 'prices.BTC.value',
|
||||
type: 'TYPE_INTEGER',
|
||||
numberDecimalPlaces: '0',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
operator: 'OPERATOR_GREATER_THAN',
|
||||
value: '0',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
external: {
|
||||
oracle: {
|
||||
signers: [
|
||||
{
|
||||
pubKey: {
|
||||
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||
},
|
||||
},
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
key: {
|
||||
name: 'trading.terminated.ETH5',
|
||||
type: 'TYPE_BOOLEAN',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
operator: 'OPERATOR_EQUALS',
|
||||
value: 'true',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty: 'prices.BTC.value',
|
||||
tradingTerminationProperty: 'trading.terminated.ETH5',
|
||||
},
|
||||
},
|
||||
},
|
||||
metadata: [
|
||||
'sector:food',
|
||||
'sector:materials',
|
||||
'source:docs.vega.xyz',
|
||||
],
|
||||
priceMonitoringParameters: {
|
||||
triggers: [
|
||||
{
|
||||
horizon: '43200',
|
||||
probability: '0.9999999',
|
||||
auctionExtension: '600',
|
||||
},
|
||||
],
|
||||
},
|
||||
liquidityMonitoringParameters: {
|
||||
targetStakeParameters: {
|
||||
timeWindow: '3600',
|
||||
scalingFactor: 10,
|
||||
},
|
||||
triggeringRatio: '0.7',
|
||||
auctionExtension: '1',
|
||||
},
|
||||
logNormal: {
|
||||
tau: 0.0001140771161,
|
||||
riskAversionParameter: 0.01,
|
||||
params: {
|
||||
mu: 0,
|
||||
r: 0.016,
|
||||
sigma: 0.5,
|
||||
},
|
||||
},
|
||||
successor: {
|
||||
parentMarketId: parentMarketId,
|
||||
insurancePoolFraction: '0.75',
|
||||
},
|
||||
liquiditySlaParameters: {
|
||||
priceRange: '0.95',
|
||||
commitmentMinTimeFraction: '0.5',
|
||||
performanceHysteresisEpochs: 2,
|
||||
slaCompetitionFactor: '0.75',
|
||||
},
|
||||
},
|
||||
},
|
||||
closingTimestamp,
|
||||
enactmentTimestamp,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function getNewAssetTxBody() {
|
||||
const MIN_CLOSE_SEC = 500;
|
||||
const MIN_ENACT_SEC = 700;
|
||||
const MIN_VALID_SEC = 60;
|
||||
|
||||
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
|
||||
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
|
||||
const validationDate = addSeconds(new Date(), MIN_VALID_SEC);
|
||||
|
||||
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
|
||||
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
|
||||
const validationTimestamp = millisecondsToSeconds(validationDate.getTime());
|
||||
|
||||
return {
|
||||
proposalSubmission: {
|
||||
rationale: {
|
||||
title: 'Test new asset proposal',
|
||||
description: 'E2E test for proposals',
|
||||
},
|
||||
terms: {
|
||||
newAsset: {
|
||||
changes: {
|
||||
name: 'USDT Coin',
|
||||
symbol: 'USDT',
|
||||
decimals: '18',
|
||||
quantum: '1',
|
||||
erc20: {
|
||||
contractAddress: '0xb404c51bbc10dcbe948077f18a4b8e553d160084',
|
||||
withdrawThreshold: '10',
|
||||
lifetimeLimit: '10',
|
||||
},
|
||||
},
|
||||
},
|
||||
closingTimestamp,
|
||||
enactmentTimestamp,
|
||||
validationTimestamp,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.rocks
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||
NX_VEGA_ENV=STAGNET1
|
||||
@@ -9,7 +8,6 @@ NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.rocks/rest
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_VEGA_GOVERNANCE_URL=https://governance.stagnet1.vega.rocks
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# App configuration variables
|
||||
NX_TENDERMINT_URL=http://localhost:26617
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
||||
NX_VEGA_ENV=CUSTOM
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
||||
NX_VEGA_EXPLORER_URL=/
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_TXS_LIST=0
|
||||
|
||||
NX_TENDERMINT_URL=http://localhost:26617
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# App configuration variables
|
||||
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://dev.governance.vega.xyz
|
||||
NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_VEGA_EXPLORER_URL=/
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# App configuration variables
|
||||
NX_TENDERMINT_URL=https://be.vega.community
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
NX_SENTRY_DSN=https://b3a56b03eda842faad731f3ea9dfd1bc@o286262.ingest.sentry.io/6242427
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
||||
NX_VEGA_URL=https://api.vega.community/graphql
|
||||
NX_VEGA_ENV=MAINNET
|
||||
NX_BLOCK_EXPLORER=https://be.vega.community/rest
|
||||
NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
|
||||
NX_VEGA_CONSOLE_URL=https://console.vega.xyz
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
NX_TENDERMINT_URL=https://be.vega.community
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# App configuration variables
|
||||
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
|
||||
NX_VEGA_URL=https://api.mainnet-mirror.vega.rocks/graphql
|
||||
NX_VEGA_ENV=MAINNET-MIRROR
|
||||
NX_VEGA_ENV=MAINNET_MIRROR
|
||||
NX_BLOCK_EXPLORER=https://be.mainnet-mirror.vega.rocks/rest
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://governance.mainnet-mirror.vega.rocks
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks/
|
||||
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
|
||||
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
# .env is stagnet1, so there are no overrides required
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz","STAGNET1":"https://stagnet1.explorer.vega.xyz"}'
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# App configuration variables
|
||||
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
||||
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
||||
|
||||
@@ -4,12 +4,13 @@ NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/maste
|
||||
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
|
||||
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
|
||||
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
||||
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
||||
NX_VEGA_GOVERNANCE_URL=https://governance.validators-testnet.vega.rocks
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
|
||||
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks/
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
||||
|
||||
@@ -3,6 +3,6 @@ NX_TENDERMINT_URL=http://localhost:26607/
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
|
||||
NX_VEGA_ENV=CUSTOM
|
||||
NX_BLOCK_EXPLORER=
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
||||
NX_VEGA_EXPLORER_URL=/
|
||||
NX_VEGA_EXPLORER_URL=/
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
@@ -53,7 +53,7 @@
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/linter:eslint",
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/explorer/**/*.{ts,tsx,js,jsx}"]
|
||||
@@ -63,30 +63,14 @@
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/apps/explorer"],
|
||||
"options": {
|
||||
"jestConfig": "apps/explorer/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"codeCoverage": true
|
||||
}
|
||||
"jestConfig": "apps/explorer/jest.config.ts"
|
||||
}
|
||||
},
|
||||
"generate-types": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/spec-update-v0.72.0-preview.2/specs/v0.72.0-preview.2/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||
]
|
||||
}
|
||||
},
|
||||
"build-netlify": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"cp apps/explorer/netlify.toml netlify.toml",
|
||||
"nx build explorer"
|
||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.73.1/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import '../i18n';
|
||||
import {
|
||||
AppFailure,
|
||||
NetworkLoader,
|
||||
NodeFailure,
|
||||
NodeGuard,
|
||||
NodeSwitcherDialog,
|
||||
useEnvironment,
|
||||
@@ -11,7 +12,8 @@ import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-web
|
||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
|
||||
import { RouterProvider } from 'react-router-dom';
|
||||
import { router } from './routes/router-config';
|
||||
import { useRouterConfig } from './routes/router-config';
|
||||
import { createBrowserRouter } from 'react-router-dom';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
@@ -28,20 +30,27 @@ function App() {
|
||||
);
|
||||
return (
|
||||
<TendermintWebsocketProvider>
|
||||
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
|
||||
<NodeGuard
|
||||
skeleton={<div>{t('Loading')}</div>}
|
||||
failure={<AppFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
|
||||
>
|
||||
<Suspense fallback={splashLoading}>
|
||||
<RouterProvider router={router} fallbackElement={splashLoading} />
|
||||
</Suspense>
|
||||
</NodeGuard>
|
||||
<NodeSwitcherDialog
|
||||
open={nodeSwitcherOpen}
|
||||
setOpen={setNodeSwitcherOpen}
|
||||
/>
|
||||
</NetworkLoader>
|
||||
<Suspense fallback={splashLoading}>
|
||||
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
|
||||
<NodeGuard
|
||||
skeleton={<div>{t('Loading')}</div>}
|
||||
failure={
|
||||
<NodeFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />
|
||||
}
|
||||
>
|
||||
<Suspense fallback={splashLoading}>
|
||||
<RouterProvider
|
||||
router={createBrowserRouter(useRouterConfig())}
|
||||
fallbackElement={splashLoading}
|
||||
/>
|
||||
</Suspense>
|
||||
</NodeGuard>
|
||||
<NodeSwitcherDialog
|
||||
open={nodeSwitcherOpen}
|
||||
setOpen={setNodeSwitcherOpen}
|
||||
/>
|
||||
</NetworkLoader>
|
||||
</Suspense>
|
||||
</TendermintWebsocketProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useAssetDataProvider } from '@vegaprotocol/assets';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { addDecimalsFixedFormatNumber } from '@vegaprotocol/utils';
|
||||
import { AssetLink } from '../links';
|
||||
|
||||
export type AssetBalanceProps = {
|
||||
@@ -23,12 +23,12 @@ const AssetBalance = ({
|
||||
|
||||
const label =
|
||||
!loading && asset && asset.decimals
|
||||
? addDecimalsFormatNumber(price, asset.decimals)
|
||||
? addDecimalsFixedFormatNumber(price, asset.decimals)
|
||||
: price;
|
||||
|
||||
return (
|
||||
<div className="inline-block">
|
||||
<span>{label}</span>{' '}
|
||||
<span className="font-mono">{label}</span>{' '}
|
||||
{showAssetLink && asset?.id ? (
|
||||
<AssetLink showAssetSymbol={showAssetSymbol} assetId={assetId} />
|
||||
) : null}
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
|
||||
import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
|
||||
import {
|
||||
useAssetTypeMapping,
|
||||
useAssetStatusMapping,
|
||||
type AssetFieldsFragment,
|
||||
} from '@vegaprotocol/assets';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { type VegaICellRendererParams } from '@vegaprotocol/datagrid';
|
||||
import { useRef, useLayoutEffect } from 'react';
|
||||
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||
import { type ColDef } from 'ag-grid-community';
|
||||
import type { RowClickedEvent } from 'ag-grid-community';
|
||||
|
||||
type AssetsTableProps = {
|
||||
data: AssetFieldsFragment[] | null;
|
||||
};
|
||||
export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
const assetTypeMapping = useAssetTypeMapping();
|
||||
const assetStatusMapping = useAssetStatusMapping();
|
||||
const navigate = useNavigate();
|
||||
const ref = useRef<AgGridReact>(null);
|
||||
const showColumnsOnDesktop = () => {
|
||||
ref.current?.columnApi.setColumnsVisible(
|
||||
ref.current?.api.setColumnsVisible(
|
||||
['id', 'type', 'status'],
|
||||
window.innerWidth > BREAKPOINT_MD
|
||||
);
|
||||
@@ -47,14 +53,14 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
field: 'source.__typename',
|
||||
hide: window.innerWidth < BREAKPOINT_MD,
|
||||
valueFormatter: ({ value }: { value?: string }) =>
|
||||
value ? AssetTypeMapping[value].value : '',
|
||||
value ? assetTypeMapping[value].value : '',
|
||||
},
|
||||
{
|
||||
headerName: t('Status'),
|
||||
field: 'status',
|
||||
hide: window.innerWidth < BREAKPOINT_MD,
|
||||
valueFormatter: ({ value }: { value?: string }) =>
|
||||
value ? AssetStatusMapping[value].value : '',
|
||||
value ? assetStatusMapping[value].value : '',
|
||||
},
|
||||
{
|
||||
colId: 'actions',
|
||||
@@ -69,7 +75,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
}: VegaICellRendererParams<AssetFieldsFragment, 'id'>) =>
|
||||
value ? (
|
||||
<ButtonLink
|
||||
onClick={(e) => {
|
||||
onClick={() => {
|
||||
navigate(value);
|
||||
}}
|
||||
>
|
||||
@@ -80,7 +86,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
),
|
||||
},
|
||||
],
|
||||
[navigate]
|
||||
[navigate, assetStatusMapping, assetTypeMapping]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,7 +23,7 @@ export const Footer = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<footer className="grid grid-rows-2 lg:grid-cols-[1fr_auto] text-xs md:text-md lg:flex md:col-span-2 px-4 py-2 gap-4 border-t border-vega-light-200 dark:border-vega-dark-200">
|
||||
<footer className="grid grid-cols-[1fr_auto] items-center text-xs md:text-md lg:flex md:col-span-2 px-4 pt-2 pb-3 gap-4 border-t border-vega-light-200 dark:border-vega-dark-200">
|
||||
<div className="flex justify-between gap-2 align-middle">
|
||||
{GIT_COMMIT_HASH && (
|
||||
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
|
||||
@@ -43,9 +43,12 @@ export const Footer = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="content-center flex pl-2 md:border-r border-neutral-700 dark:border-neutral-300 pr-4">
|
||||
{VEGA_URL && <NodeUrl url={VEGA_URL} />}
|
||||
<Link className="ml-2" onClick={() => setNodeSwitcherOpen(true)}>
|
||||
<div className="content-center flex pr-4 md:border-r border-neutral-700 dark:border-neutral-300">
|
||||
<span className="pr-2">{VEGA_URL && <NodeUrl url={VEGA_URL} />}</span>
|
||||
<Link
|
||||
className="ml-2 underline-offset-4"
|
||||
onClick={() => setNodeSwitcherOpen(true)}
|
||||
>
|
||||
{t('Change')}
|
||||
</Link>
|
||||
</div>
|
||||
@@ -59,7 +62,10 @@ export const Footer = () => {
|
||||
) : null}
|
||||
</div>
|
||||
<div className="pl-2 align-center lg:align-right lg:flex lg:justify-end gap-2 align-middle lg:max-w-xs lg:ml-auto">
|
||||
<RouteLink to={`/${Routes.DISCLAIMER}`} className="underline">
|
||||
<RouteLink
|
||||
to={`/${Routes.DISCLAIMER}`}
|
||||
className="underline underline-offset-4"
|
||||
>
|
||||
Disclaimer
|
||||
</RouteLink>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Routes } from '../../routes/route-names';
|
||||
import { NetworkSwitcher } from '@vegaprotocol/environment';
|
||||
import type { Navigable } from '../../routes/router-config';
|
||||
import { isNavigable } from '../../routes/router-config';
|
||||
import { routerConfig } from '../../routes/router-config';
|
||||
import { useRouterConfig } from '../../routes/router-config';
|
||||
import { useMemo } from 'react';
|
||||
import compact from 'lodash/compact';
|
||||
import { Search } from '../search';
|
||||
@@ -26,6 +26,7 @@ const routeToNavigationItem = (r: Navigable) => (
|
||||
);
|
||||
|
||||
export const Header = () => {
|
||||
const routerConfig = useRouterConfig();
|
||||
const isHome = Boolean(useMatch(Routes.HOME));
|
||||
const pages = routerConfig[0].children || [];
|
||||
const mainItems = compact(
|
||||
@@ -95,7 +96,10 @@ export const Header = () => {
|
||||
{mainItems.map(routeToNavigationItem)}
|
||||
{groupedItems && groupedItems.length > 0 && (
|
||||
<NavigationItem>
|
||||
<NavigationTrigger isActive={Boolean(isOnOther)}>
|
||||
<NavigationTrigger
|
||||
isActive={Boolean(isOnOther)}
|
||||
data-testid="other"
|
||||
>
|
||||
{t('Other')}
|
||||
</NavigationTrigger>
|
||||
<NavigationContent>
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import Hash from '../hash';
|
||||
|
||||
export enum EthExplorerLinkTypes {
|
||||
block = 'block',
|
||||
address = 'address',
|
||||
tx = 'tx',
|
||||
}
|
||||
|
||||
export type EthExplorerLinkProps = Partial<typeof HTMLAnchorElement> & {
|
||||
id: string;
|
||||
type: EthExplorerLinkTypes;
|
||||
};
|
||||
|
||||
export const EthExplorerLink = ({
|
||||
id,
|
||||
type,
|
||||
...props
|
||||
}: EthExplorerLinkProps) => {
|
||||
const link = `${DATA_SOURCES.ethExplorerUrl}/${type}/${id}`;
|
||||
return (
|
||||
<a
|
||||
className="underline external font-mono"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
{...props}
|
||||
href={link}
|
||||
>
|
||||
<Hash text={id} />
|
||||
</a>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { ChainIdMapping } from './external-chain';
|
||||
import { SUPPORTED_CHAIN_IDS, SUPPORTED_CHAIN_LABELS } from './external-chain';
|
||||
|
||||
export const SUPPORTED_CHAIN_ICON_URLS: ChainIdMapping = {
|
||||
'1': '/assets/chain-eth-logo.svg',
|
||||
'100': '/assets/chain-gno-logo.svg',
|
||||
'42161': '/assets/chain-arb-logo.svg',
|
||||
'11155111': '/assets/chain-eth-logo.svg',
|
||||
};
|
||||
|
||||
export type ExternalChainIconProps = {
|
||||
chainId?: string;
|
||||
};
|
||||
|
||||
export const ExternalChainIcon = ({
|
||||
// If chainID is not provided, default to a non-existent chain
|
||||
chainId = '-1',
|
||||
}: ExternalChainIconProps) => {
|
||||
if (SUPPORTED_CHAIN_IDS.includes(chainId)) {
|
||||
const url = SUPPORTED_CHAIN_ICON_URLS[chainId];
|
||||
const alt = SUPPORTED_CHAIN_LABELS[chainId];
|
||||
|
||||
return (
|
||||
<img
|
||||
src={url}
|
||||
className="inline-block w-4 h-4 mr-1 dark:invert"
|
||||
alt={alt}
|
||||
title={alt}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
export type ChainIdMapping = {
|
||||
[K in typeof SUPPORTED_CHAIN_IDS[number]]: string;
|
||||
};
|
||||
export const SUPPORTED_CHAIN_IDS: string[] = ['1', '100', '42161', '11155111'];
|
||||
|
||||
export const SUPPORTED_CHAIN_LABELS: ChainIdMapping = {
|
||||
'1': 'Ethereum',
|
||||
'100': 'Gnosis',
|
||||
'42161': 'Arbitrum',
|
||||
'11155111': 'Sepolia',
|
||||
};
|
||||
|
||||
export function getExternalExplorerLink(chainId: string, type: string) {
|
||||
if (SUPPORTED_CHAIN_IDS.includes(chainId)) {
|
||||
switch (chainId) {
|
||||
case '1':
|
||||
return 'https://etherscan.io';
|
||||
case '100':
|
||||
return 'https://gnosisscan.io';
|
||||
case '42161':
|
||||
return 'https://arbiscan.io';
|
||||
case '11155111':
|
||||
return 'https://sepolia.etherscan.io';
|
||||
default:
|
||||
return '#';
|
||||
}
|
||||
} else {
|
||||
return '#';
|
||||
}
|
||||
}
|
||||
|
||||
export function getExternalChainLabel(chainId?: string) {
|
||||
if (chainId && SUPPORTED_CHAIN_IDS.includes(chainId)) {
|
||||
return SUPPORTED_CHAIN_LABELS[chainId];
|
||||
} else {
|
||||
return 'Custom Chain';
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import Hash from '../hash';
|
||||
import { getExternalExplorerLink } from './external-chain';
|
||||
import { ExternalChainIcon } from './external-chain-icon';
|
||||
|
||||
export enum EthExplorerLinkTypes {
|
||||
block = 'block',
|
||||
address = 'address',
|
||||
tx = 'tx',
|
||||
}
|
||||
|
||||
export type ExternalExplorerLinkProps = Partial<typeof HTMLAnchorElement> & {
|
||||
id: string;
|
||||
type: EthExplorerLinkTypes;
|
||||
// Defaults to Ethereum Mainnet, as chain support was added late
|
||||
chain?: string;
|
||||
code?: boolean;
|
||||
};
|
||||
|
||||
export const ExternalExplorerLink = ({
|
||||
id,
|
||||
type,
|
||||
chain = '1',
|
||||
code = false,
|
||||
...props
|
||||
}: ExternalExplorerLinkProps) => {
|
||||
const link = `${getExternalExplorerLink(chain, type)}/${type}/${id}${
|
||||
code ? '#code' : ''
|
||||
}`;
|
||||
return (
|
||||
<a
|
||||
className="underline external font-mono"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
{...props}
|
||||
href={link}
|
||||
>
|
||||
<ExternalChainIcon chainId={chain} />
|
||||
<Hash text={id} />
|
||||
</a>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
export type HashProps = {
|
||||
export type HashProps = React.HTMLProps<HTMLSpanElement> & {
|
||||
text: string;
|
||||
truncate?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -7,10 +8,16 @@ export type HashProps = {
|
||||
* are broken when they need to wrap. This will remove the need
|
||||
* for a lot of the overflow scrolling that currently exists.
|
||||
*/
|
||||
const Hash = ({ text }: HashProps) => {
|
||||
const Hash = ({ text, truncate = false }: HashProps) => {
|
||||
const h = truncate ? text.slice(0, 6) : text;
|
||||
|
||||
return (
|
||||
<code className="break-all font-mono" style={{ wordWrap: 'break-word' }}>
|
||||
{text}
|
||||
<code
|
||||
title={text}
|
||||
className="break-all font-mono"
|
||||
style={{ wordWrap: 'break-word' }}
|
||||
>
|
||||
{h}
|
||||
</code>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,4 +2,5 @@ export { default as BlockLink } from './block-link/block-link';
|
||||
export { default as PartyLink } from './party-link/party-link';
|
||||
export { default as NodeLink } from './node-link/node-link';
|
||||
export { default as MarketLink } from './market-link/market-link';
|
||||
export { default as NetworkParameterLink } from './network-parameter-link/network-parameter-link';
|
||||
export * from './asset-link/asset-link';
|
||||
|
||||
@@ -3,6 +3,7 @@ query ExplorerMarket($id: ID!) {
|
||||
id
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
state
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
@@ -13,9 +14,14 @@ query ExplorerMarket($id: ID!) {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -8,7 +8,7 @@ export type ExplorerMarketQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null };
|
||||
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Perpetual', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Spot' } } } } | null };
|
||||
|
||||
|
||||
export const ExplorerMarketDocument = gql`
|
||||
@@ -17,6 +17,7 @@ export const ExplorerMarketDocument = gql`
|
||||
id
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
state
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
@@ -27,10 +28,15 @@ export const ExplorerMarketDocument = gql`
|
||||
decimals
|
||||
}
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
state
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -61,7 +61,11 @@ describe('Market link component', () => {
|
||||
instrument: {
|
||||
name: 'test-label',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'dai',
|
||||
settlementAsset: {
|
||||
decimals: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -87,6 +91,6 @@ describe('Market link component', () => {
|
||||
};
|
||||
|
||||
const res = render(renderComponent('123', [mock]));
|
||||
expect(await res.findByText('123')).toBeInTheDocument();
|
||||
expect(await res.findByTitle('123')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,6 +23,7 @@ const MarketLink = ({
|
||||
}: MarketLinkProps) => {
|
||||
const { data, error, loading } = useExplorerMarketQuery({
|
||||
variables: { id },
|
||||
fetchPolicy: 'cache-first',
|
||||
});
|
||||
|
||||
let label = <span>{id}</span>;
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import { Routes } from '../../../routes/route-names';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ComponentProps } from 'react';
|
||||
import Hash from '../hash';
|
||||
|
||||
export type NetworkParameterLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
parameter: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Links a given network parameter to the relevant page and anchor on the page
|
||||
*/
|
||||
const NetworkParameterLink = ({
|
||||
parameter,
|
||||
...props
|
||||
}: NetworkParameterLinkProps) => {
|
||||
return (
|
||||
<Link
|
||||
className="underline"
|
||||
{...props}
|
||||
to={`/${Routes.NETWORK_PARAMETERS}#${parameter}`}
|
||||
>
|
||||
<Hash text={parameter} />
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default NetworkParameterLink;
|
||||
@@ -0,0 +1,57 @@
|
||||
import OracleLink, { getStatusString } from './oracle-link';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
|
||||
describe('getStatusString', () => {
|
||||
it("returns 'Unknown' for undefined status", () => {
|
||||
expect(getStatusString(undefined)).toBe('Unknown');
|
||||
});
|
||||
|
||||
it('returns the correct string for a known status', () => {
|
||||
expect(getStatusString('STATUS_ACTIVE')).toBe('Active');
|
||||
expect(getStatusString('STATUS_DEACTIVATED')).toBe('Deactivated');
|
||||
});
|
||||
});
|
||||
|
||||
describe('OracleLink', () => {
|
||||
it('renders the truncated Oracle ID', () => {
|
||||
const id = '123456789';
|
||||
render(
|
||||
<MockedProvider>
|
||||
<MemoryRouter>
|
||||
<OracleLink id={id} />
|
||||
</MemoryRouter>
|
||||
</MockedProvider>
|
||||
);
|
||||
const idElement = screen.getByText(id.slice(0, 6));
|
||||
expect(idElement).toBeInTheDocument();
|
||||
expect(idElement).toHaveAttribute('title', id);
|
||||
});
|
||||
|
||||
it('renders the Oracle status', () => {
|
||||
const id = '123';
|
||||
const status = 'STATUS_ACTIVE';
|
||||
render(
|
||||
<MockedProvider>
|
||||
<MemoryRouter>
|
||||
<OracleLink id={id} status={status} data-testid="link" />
|
||||
</MemoryRouter>
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByTestId('link')).toHaveAttribute('data-status', 'Active');
|
||||
});
|
||||
|
||||
it('renders the Oracle data indicator', () => {
|
||||
const id = '123';
|
||||
const hasSeenOracleReports = true;
|
||||
render(
|
||||
<MockedProvider>
|
||||
<MemoryRouter>
|
||||
<OracleLink id={id} hasSeenOracleReports={hasSeenOracleReports} />
|
||||
</MemoryRouter>
|
||||
</MockedProvider>
|
||||
);
|
||||
expect(screen.getByTestId('oracle-data-indicator')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -3,20 +3,93 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import type { ComponentProps } from 'react';
|
||||
import Hash from '../hash';
|
||||
import { Tooltip, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
DataSourceSpecStatus,
|
||||
DataSourceSpecStatusMapping,
|
||||
} from '@vegaprotocol/types';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
/**
|
||||
* Returns a human-readable string for the given status, or a meaningful
|
||||
* default if the status is unrecognised
|
||||
* @param status string status
|
||||
*/
|
||||
export function getStatusString(status: string | undefined): string {
|
||||
if (status && status in DataSourceSpecStatus) {
|
||||
return DataSourceSpecStatusMapping[status as DataSourceSpecStatus];
|
||||
}
|
||||
|
||||
return t('Unknown');
|
||||
}
|
||||
|
||||
export type OracleLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
// The Oracle ID
|
||||
id: string;
|
||||
// If available, the oracle status
|
||||
status?: string;
|
||||
// If the oracle has corresponding data in the OracleDataConnection
|
||||
hasSeenOracleReports?: boolean;
|
||||
};
|
||||
|
||||
const OracleLink = ({ id, ...props }: OracleLinkProps) => {
|
||||
/**
|
||||
* Given an Oracle ID, renders a data-dense link to the Oracle page. Data density is achieved by:
|
||||
* - Colour coding the link based on the Oracle's status
|
||||
* - Showing a small indicator if the Oracle has matched data
|
||||
* - Showing a tooltip with the Oracle's status and whether it has matched data
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
export const OracleLink = ({
|
||||
id,
|
||||
status,
|
||||
hasSeenOracleReports = false,
|
||||
...props
|
||||
}: OracleLinkProps) => {
|
||||
const bgColour =
|
||||
status === 'STATUS_ACTIVE'
|
||||
? 'bg-yellow-100 hover:bg-yellow-200 border-yellow-200 dark:bg-yellow-200 dark:border-yellow-200 dark:text-gray-900 dark:border-yellow-300'
|
||||
: 'bg-gray-100 hover:bg-gray-200 border-gray-200';
|
||||
const indicatorColour =
|
||||
status === 'STATUS_ACTIVE'
|
||||
? 'bg-yellow-300 hover:bg-yellow-500 dark:bg-yellow-500'
|
||||
: 'bg-gray-300 hover:bg-gray-500';
|
||||
|
||||
const description = (
|
||||
<div>
|
||||
<p>
|
||||
<strong>{`Status: `}</strong>
|
||||
{getStatusString(status)}
|
||||
</p>
|
||||
<p>
|
||||
<strong>{`Matched data: `}</strong>
|
||||
{hasSeenOracleReports ? (
|
||||
<VegaIcon name={VegaIconNames.TICK} />
|
||||
) : (
|
||||
<VegaIcon name={VegaIconNames.CROSS} />
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Link
|
||||
className="underline font-mono"
|
||||
{...props}
|
||||
to={`/${Routes.ORACLES}/${id}`}
|
||||
>
|
||||
<Hash text={id} />
|
||||
</Link>
|
||||
<Tooltip description={description}>
|
||||
<Link
|
||||
className={`pl-2 pr-2 font-mono dark:text-black ${bgColour} rounded-sm border-solid border-2 relative`}
|
||||
{...props}
|
||||
to={`/${Routes.ORACLES}/${id}`}
|
||||
data-status={getStatusString(status)}
|
||||
>
|
||||
<Hash text={id} truncate={true} />
|
||||
{hasSeenOracleReports ? (
|
||||
<strong
|
||||
data-testid="oracle-data-indicator"
|
||||
className={`absolute top-0 right-0 w-1 h-full font-thin ${indicatorColour}`}
|
||||
title="Oracle has matched data"
|
||||
></strong>
|
||||
) : null}
|
||||
</Link>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ const PartyLink = ({ id, truncate = false, ...props }: PartyLinkProps) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="whitespace-nowrap">
|
||||
<span>
|
||||
{useName && <Icon size={4} name="cube" className="mr-2" />}
|
||||
<Link
|
||||
className="underline font-mono"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
query ExplorerProposal($id: ID!) {
|
||||
proposal(id: $id) {
|
||||
id
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
... on Proposal {
|
||||
id
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-5
@@ -8,16 +8,18 @@ export type ExplorerProposalQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null };
|
||||
export type ExplorerProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'BatchProposal' } | { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null };
|
||||
|
||||
|
||||
export const ExplorerProposalDocument = gql`
|
||||
query ExplorerProposal($id: ID!) {
|
||||
proposal(id: $id) {
|
||||
id
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
... on Proposal {
|
||||
id
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,11 @@ import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { render } from '@testing-library/react';
|
||||
import ProposalLink from './proposal-link';
|
||||
import { ExplorerProposalDocument } from './__generated__/Proposal';
|
||||
import {
|
||||
ExplorerProposalDocument,
|
||||
type ExplorerProposalQuery,
|
||||
type ExplorerProposalQueryVariables,
|
||||
} from './__generated__/Proposal';
|
||||
import { GraphQLError } from 'graphql';
|
||||
|
||||
function renderComponent(id: string, mocks: MockedResponse[]) {
|
||||
@@ -23,7 +27,10 @@ describe('Proposal link component', () => {
|
||||
});
|
||||
|
||||
it('Renders the ID on error', async () => {
|
||||
const mock = {
|
||||
const mock: MockedResponse<
|
||||
ExplorerProposalQuery,
|
||||
ExplorerProposalQueryVariables
|
||||
> = {
|
||||
request: {
|
||||
query: ExplorerProposalDocument,
|
||||
variables: {
|
||||
@@ -40,17 +47,22 @@ describe('Proposal link component', () => {
|
||||
});
|
||||
|
||||
it('Renders the proposal title when the query returns a result', async () => {
|
||||
const mock = {
|
||||
const proposalId = '123';
|
||||
const mock: MockedResponse<
|
||||
ExplorerProposalQuery,
|
||||
ExplorerProposalQueryVariables
|
||||
> = {
|
||||
request: {
|
||||
query: ExplorerProposalDocument,
|
||||
variables: {
|
||||
id: '123',
|
||||
id: proposalId,
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
proposal: {
|
||||
id: '123',
|
||||
__typename: 'Proposal',
|
||||
id: proposalId,
|
||||
rationale: {
|
||||
title: 'test-title',
|
||||
description: 'test description',
|
||||
@@ -60,13 +72,16 @@ describe('Proposal link component', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const res = render(renderComponent('123', [mock]));
|
||||
expect(res.getByText('123')).toBeInTheDocument();
|
||||
const res = render(renderComponent(proposalId, [mock]));
|
||||
expect(res.getByText(proposalId)).toBeInTheDocument();
|
||||
expect(await res.findByText('test-title')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Leaves the proposal id when the market is not found', async () => {
|
||||
const mock = {
|
||||
const mock: MockedResponse<
|
||||
ExplorerProposalQuery,
|
||||
ExplorerProposalQueryVariables
|
||||
> = {
|
||||
request: {
|
||||
query: ExplorerProposalDocument,
|
||||
variables: {
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { useExplorerProposalQuery } from './__generated__/Proposal';
|
||||
import {
|
||||
useExplorerProposalQuery,
|
||||
type ExplorerProposalQuery,
|
||||
} from './__generated__/Proposal';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { ENV } from '../../../config/env';
|
||||
import Hash from '../hash';
|
||||
|
||||
export type ProposalLinkProps = {
|
||||
id: string;
|
||||
text?: string;
|
||||
@@ -16,8 +20,13 @@ const ProposalLink = ({ id, text }: ProposalLinkProps) => {
|
||||
variables: { id },
|
||||
});
|
||||
|
||||
const proposal = data?.proposal as Extract<
|
||||
ExplorerProposalQuery['proposal'],
|
||||
{ __typename?: 'Proposal' }
|
||||
>;
|
||||
|
||||
const base = ENV.dataSources.governanceUrl;
|
||||
const label = data?.proposal?.rationale.title || id;
|
||||
const label = proposal?.rationale?.title || id;
|
||||
|
||||
return (
|
||||
<ExternalLink href={`${base}/proposals/${id}`}>
|
||||
|
||||
@@ -1,34 +1,42 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
||||
import { PriceMonitoringBoundsInfoPanel } from '@vegaprotocol/markets';
|
||||
import {
|
||||
LiquidationStrategyInfoPanel,
|
||||
LiquidityPriceRangeInfoPanel,
|
||||
LiquiditySLAParametersInfoPanel,
|
||||
MarginScalingFactorsPanel,
|
||||
PriceMonitoringBoundsInfoPanel,
|
||||
SuccessionLineInfoPanel,
|
||||
getDataSourceSpecForSettlementData,
|
||||
getDataSourceSpecForTradingTermination,
|
||||
} from '@vegaprotocol/markets';
|
||||
import {
|
||||
LiquidityInfoPanel,
|
||||
LiquidityMonitoringParametersInfoPanel,
|
||||
InstrumentInfoPanel,
|
||||
KeyDetailsInfoPanel,
|
||||
LiquidityPriceRangeInfoPanel,
|
||||
MetadataInfoPanel,
|
||||
OracleInfoPanel,
|
||||
RiskFactorsInfoPanel,
|
||||
RiskModelInfoPanel,
|
||||
RiskParametersInfoPanel,
|
||||
SettlementAssetInfoPanel,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { MarketInfoTable } from '@vegaprotocol/markets';
|
||||
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
||||
import type { DataSourceFragment } from '@vegaprotocol/markets';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
if (!market) return null;
|
||||
const { product } = market.tradableInstrument.instrument;
|
||||
const settlementDataSource = getDataSourceSpecForSettlementData(product);
|
||||
const terminationDataSource = getDataSourceSpecForTradingTermination(product);
|
||||
|
||||
const settlementData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||
const terminationData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||
|
||||
const getSigners = (data: DataSourceDefinition) => {
|
||||
const getSigners = ({ data }: DataSourceFragment) => {
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||
const signers = data.sourceType.sourceType.signers || [];
|
||||
const signers =
|
||||
('signers' in data.sourceType.sourceType &&
|
||||
data.sourceType.sourceType.signers) ||
|
||||
[];
|
||||
|
||||
return signers.map(({ signer }, i) => {
|
||||
return (
|
||||
@@ -40,10 +48,13 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
return [];
|
||||
};
|
||||
|
||||
const showTwoOracles = isEqual(
|
||||
getSigners(settlementData),
|
||||
getSigners(terminationData)
|
||||
);
|
||||
const showTwoOracles =
|
||||
settlementDataSource &&
|
||||
terminationDataSource &&
|
||||
isEqual(
|
||||
getSigners(settlementDataSource),
|
||||
getSigners(terminationDataSource)
|
||||
);
|
||||
|
||||
const headerClassName = 'font-alpha calt text-xl mt-4 border-b-2 pb-2';
|
||||
|
||||
@@ -59,8 +70,8 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
<MetadataInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Risk model')}</h2>
|
||||
<RiskModelInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Risk parameters')}</h2>
|
||||
<RiskParametersInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Margin scaling factors')}</h2>
|
||||
<MarginScalingFactorsPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Risk factors')}</h2>
|
||||
<RiskFactorsInfoPanel market={market} />
|
||||
{(market.data?.priceMonitoringBounds || []).map((trigger, i) => (
|
||||
@@ -84,12 +95,16 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
</>
|
||||
)
|
||||
)}
|
||||
<h2 className={headerClassName}>{t('Liquidation strategy')}</h2>
|
||||
<LiquidationStrategyInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity monitoring')}</h2>
|
||||
<LiquidityMonitoringParametersInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity')}</h2>
|
||||
<LiquidityInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity price range')}</h2>
|
||||
<LiquidityPriceRangeInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity SLA protocol')}</h2>
|
||||
<LiquiditySLAParametersInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity')}</h2>
|
||||
<LiquidityInfoPanel market={market} />
|
||||
{showTwoOracles ? (
|
||||
<>
|
||||
<h2 className={headerClassName}>{t('Settlement oracle')}</h2>
|
||||
@@ -103,6 +118,8 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
<OracleInfoPanel market={market} type="settlementData" />
|
||||
</>
|
||||
)}
|
||||
<h2 className={`${headerClassName} mb-4`}>{t('Succession line')}</h2>
|
||||
<SuccessionLineInfoPanel market={market} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||
import { getAsset, type MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueGetterParams,
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import { type ColDef } from 'ag-grid-community';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
type VegaICellRendererParams,
|
||||
type VegaValueGetterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { useRef, useLayoutEffect } from 'react';
|
||||
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
||||
import { MarketStateMapping } from '@vegaprotocol/types';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import type { RowClickedEvent } from 'ag-grid-community';
|
||||
import { type RowClickedEvent } from 'ag-grid-community';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
|
||||
type MarketsTableProps = {
|
||||
@@ -29,7 +29,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
||||
const gridRef = useRef<AgGridReact>(null);
|
||||
useLayoutEffect(() => {
|
||||
const showColumnsOnDesktop = () => {
|
||||
gridRef.current?.columnApi.setColumnsVisible(
|
||||
gridRef.current?.api.setColumnsVisible(
|
||||
['id', 'state', 'asset'],
|
||||
window.innerWidth > BREAKPOINT_MD
|
||||
);
|
||||
@@ -73,8 +73,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
||||
MarketFieldsFragment,
|
||||
'tradableInstrument.instrument.product.settlementAsset.symbol'
|
||||
>) => {
|
||||
const value =
|
||||
data?.tradableInstrument.instrument.product.settlementAsset;
|
||||
const value = data && getAsset(data);
|
||||
return value ? (
|
||||
<ButtonLink
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
import {
|
||||
BORDER_COLOURS,
|
||||
NestedDataList,
|
||||
sortNestedDataByChildren,
|
||||
} from './nested-data-list';
|
||||
import { NestedDataList, sortNestedDataByChildren } from './nested-data-list';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
const mockData = {
|
||||
@@ -61,38 +57,6 @@ describe('NestedDataList', () => {
|
||||
expect(parent[0].querySelector('li')).toHaveClass('pl-4 border-l-4 pt-2');
|
||||
});
|
||||
|
||||
it('should repeat the border colours in the correct order', () => {
|
||||
const colourMockData = {
|
||||
t0: {
|
||||
t1: {
|
||||
t2: {
|
||||
t3: {
|
||||
t4: {
|
||||
t5: {
|
||||
t6: {
|
||||
t7: {
|
||||
t8: {
|
||||
hello: 'world',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const tree = render(<NestedDataList data={colourMockData} />);
|
||||
const { getByTestId } = tree;
|
||||
|
||||
for (let i = 0; i < 8; i++) {
|
||||
const item = getByTestId(`T${i}`);
|
||||
const expected = BORDER_COLOURS.light[i % 5];
|
||||
expect(item.style.borderColor.toUpperCase()).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
it('should sort the data by values with children', () => {
|
||||
const mockData = {
|
||||
nonce: '5980890939790185837',
|
||||
|
||||
@@ -31,6 +31,9 @@ fragment ExplorerDeterministicOrderFields on Order {
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
fragment ExplorerStopOrderFields on StopOrder {
|
||||
id
|
||||
status
|
||||
createdAt
|
||||
trigger {
|
||||
... on StopOrderPrice {
|
||||
price
|
||||
}
|
||||
... on StopOrderTrailingPercentOffset {
|
||||
trailingPercentOffset
|
||||
}
|
||||
}
|
||||
createdAt
|
||||
ocoLinkId
|
||||
triggerDirection
|
||||
order {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
query ExplorerStopOrder($stopOrderId: ID!) {
|
||||
stopOrder(id: $stopOrderId) {
|
||||
...ExplorerStopOrderFields
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } };
|
||||
export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } };
|
||||
|
||||
export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
|
||||
orderId: Types.Scalars['ID'];
|
||||
@@ -11,7 +11,7 @@ export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } } };
|
||||
export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } } };
|
||||
|
||||
export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
|
||||
fragment ExplorerDeterministicOrderFields on Order {
|
||||
@@ -47,6 +47,9 @@ export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerStopOrderFieldsFragment = { __typename?: 'StopOrder', id: string, status: Types.StopOrderStatus, createdAt: any, ocoLinkId?: string | null, triggerDirection: Types.StopOrderTriggerDirection, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, order?: { __typename?: 'Order', id: string } | null };
|
||||
|
||||
export type ExplorerStopOrderQueryVariables = Types.Exact<{
|
||||
stopOrderId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerStopOrderQuery = { __typename?: 'Query', stopOrder?: { __typename?: 'StopOrder', id: string, status: Types.StopOrderStatus, createdAt: any, ocoLinkId?: string | null, triggerDirection: Types.StopOrderTriggerDirection, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, order?: { __typename?: 'Order', id: string } | null } | null };
|
||||
|
||||
export const ExplorerStopOrderFieldsFragmentDoc = gql`
|
||||
fragment ExplorerStopOrderFields on StopOrder {
|
||||
id
|
||||
status
|
||||
createdAt
|
||||
trigger {
|
||||
... on StopOrderPrice {
|
||||
price
|
||||
}
|
||||
... on StopOrderTrailingPercentOffset {
|
||||
trailingPercentOffset
|
||||
}
|
||||
}
|
||||
createdAt
|
||||
ocoLinkId
|
||||
triggerDirection
|
||||
order {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const ExplorerStopOrderDocument = gql`
|
||||
query ExplorerStopOrder($stopOrderId: ID!) {
|
||||
stopOrder(id: $stopOrderId) {
|
||||
...ExplorerStopOrderFields
|
||||
}
|
||||
}
|
||||
${ExplorerStopOrderFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useExplorerStopOrderQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useExplorerStopOrderQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useExplorerStopOrderQuery` 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 } = useExplorerStopOrderQuery({
|
||||
* variables: {
|
||||
* stopOrderId: // value for 'stopOrderId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useExplorerStopOrderQuery(baseOptions: Apollo.QueryHookOptions<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>(ExplorerStopOrderDocument, options);
|
||||
}
|
||||
export function useExplorerStopOrderLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>(ExplorerStopOrderDocument, options);
|
||||
}
|
||||
export type ExplorerStopOrderQueryHookResult = ReturnType<typeof useExplorerStopOrderQuery>;
|
||||
export type ExplorerStopOrderLazyQueryHookResult = ReturnType<typeof useExplorerStopOrderLazyQuery>;
|
||||
export type ExplorerStopOrderQueryResult = Apollo.QueryResult<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>;
|
||||
@@ -17,7 +17,7 @@ function renderAmendOrderDetails(
|
||||
mocks: MockedResponse[]
|
||||
) {
|
||||
return render(
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MockedProvider mocks={mocks}>
|
||||
<MemoryRouter>
|
||||
<AmendOrderDetails version={version} id={id} amend={amend} />
|
||||
</MemoryRouter>
|
||||
@@ -44,18 +44,18 @@ function renderExistingAmend(
|
||||
orderByID: {
|
||||
__typename: 'Order',
|
||||
id: '123',
|
||||
type: 'GTT',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status: Schema.OrderStatus.STATUS_ACTIVE,
|
||||
version: version,
|
||||
version: version ? version.toString() : '',
|
||||
createdAt: '123',
|
||||
updatedAt: '456',
|
||||
expiresAt: '789',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
price: '200',
|
||||
side: 'BUY',
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
peggedOrder: null,
|
||||
remaining: '99',
|
||||
rejectionReason: 'rejection',
|
||||
rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_NOT_FOUND,
|
||||
reference: '123',
|
||||
size: '100',
|
||||
party: {
|
||||
@@ -65,9 +65,9 @@ function renderExistingAmend(
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '789',
|
||||
state: 'STATUS_ACTIVE',
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
positionDecimalPlaces: 2,
|
||||
decimalPlaces: '5',
|
||||
decimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'test',
|
||||
@@ -94,18 +94,18 @@ function renderExistingAmend(
|
||||
orderByID: {
|
||||
__typename: 'Order',
|
||||
id: '123',
|
||||
type: 'GTT',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status: Schema.OrderStatus.STATUS_ACTIVE,
|
||||
version: 100,
|
||||
version: '100',
|
||||
createdAt: '123',
|
||||
updatedAt: '456',
|
||||
expiresAt: '789',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
peggedOrder: null,
|
||||
price: '200',
|
||||
side: 'BUY',
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
remaining: '99',
|
||||
rejectionReason: 'rejection',
|
||||
rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_NOT_FOUND,
|
||||
reference: '123',
|
||||
size: '200',
|
||||
party: {
|
||||
@@ -114,10 +114,10 @@ function renderExistingAmend(
|
||||
},
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'amend-to-order-latest-version',
|
||||
state: 'STATUS_ACTIVE',
|
||||
id: '8888',
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
positionDecimalPlaces: 2,
|
||||
decimalPlaces: '5',
|
||||
decimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'amend-to-order-latest-version-test',
|
||||
@@ -136,13 +136,13 @@ function renderExistingAmend(
|
||||
request: {
|
||||
query: ExplorerMarketDocument,
|
||||
variables: {
|
||||
id: '789',
|
||||
id: '8888',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
market: {
|
||||
id: '789',
|
||||
id: '8888',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 2,
|
||||
state: 'irrelevant-test-data',
|
||||
@@ -150,7 +150,11 @@ function renderExistingAmend(
|
||||
instrument: {
|
||||
name: 'test-label',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'dai',
|
||||
settlementAsset: {
|
||||
decimals: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -215,12 +219,10 @@ describe('Amend order details', () => {
|
||||
|
||||
it('Fetches latest version when version is not specified', async () => {
|
||||
const amend: Amend = {
|
||||
price: '-7879',
|
||||
price: '123',
|
||||
};
|
||||
|
||||
const res = renderExistingAmend('123', undefined, amend);
|
||||
expect(
|
||||
await res.findByText('amend-to-order-latest-version')
|
||||
).toBeInTheDocument();
|
||||
expect(await res.findByText('test-label')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,10 +46,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
<div className={wrapperClasses}>
|
||||
<div className="mb-12 lg:mb-0">
|
||||
<div className="relative block rounded-lg px-3 py-6 md:px-6 lg:-mr-7">
|
||||
<h2 className="text-3xl font-bold mb-4 display-5">
|
||||
<h2 className="display-5 mb-4 text-3xl font-bold">
|
||||
{t('Order not found')}
|
||||
</h2>
|
||||
<p className="text-gray-500 mb-12">
|
||||
<p className="mb-12 text-gray-500">
|
||||
{t('No order created from this transaction')}
|
||||
</p>
|
||||
</div>
|
||||
@@ -68,24 +68,24 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
<div className={wrapperClasses}>
|
||||
<div className="mb-12 lg:mb-0">
|
||||
<div className="relative block px-3 py-6 md:px-6 lg:-mr-7">
|
||||
<h2 className="text-3xl font-bold mb-4 display-5">
|
||||
<h2 className="display-5 mb-4 text-3xl font-bold">
|
||||
{t('Edits to ')}
|
||||
{sideText[o.side]}
|
||||
{t(' order')}
|
||||
</h2>
|
||||
<p className="text-gray-500 mb-4">
|
||||
<div className="mb-4 text-gray-500">
|
||||
In <MarketLink id={o.market.id} />, updated at{' '}
|
||||
<Time date={o.updatedAt} />.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-4 gap-x-6">
|
||||
<div className="grid gap-x-6 md:grid-cols-4">
|
||||
{amend.sizeDelta && amend.sizeDelta !== '0' ? (
|
||||
<div className="mb-12 md:mb-0">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
{t('New size')}
|
||||
</h2>
|
||||
<h5
|
||||
className={`text-lg font-medium text-gray-500 mb-0 capitalize ${getSideDeltaColour(
|
||||
className={`mb-0 text-lg font-medium capitalize text-gray-500 ${getSideDeltaColour(
|
||||
amend.sizeDelta
|
||||
)}`}
|
||||
>
|
||||
@@ -96,10 +96,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
|
||||
{amend.price && amend.price !== '0' ? (
|
||||
<div className="">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
{t('New price')}
|
||||
</h2>
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
<h5 className="mb-0 text-lg font-medium text-gray-500">
|
||||
<PriceInMarket price={amend.price} marketId={o.market.id} />
|
||||
</h5>
|
||||
</div>
|
||||
@@ -108,10 +108,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
{amend.peggedReference &&
|
||||
amend.peggedReference !== 'PEGGED_REFERENCE_UNSPECIFIED' ? (
|
||||
<div className="">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
{t('New reference')}
|
||||
</h2>
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
<h5 className="mb-0 text-lg font-medium text-gray-500">
|
||||
{peggedReference[amend.peggedReference]}
|
||||
</h5>
|
||||
</div>
|
||||
@@ -119,10 +119,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
|
||||
{amend.peggedOffset ? (
|
||||
<div className="">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
{t('New offset')}
|
||||
</h2>
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
<h5 className="mb-0 text-lg font-medium text-gray-500">
|
||||
{amend.peggedOffset}
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Time } from '../time';
|
||||
import { sideText, statusText, tifFull, tifShort } from './lib/order-labels';
|
||||
import SizeInMarket from '../size-in-market/size-in-market';
|
||||
import { TxOrderPeggedReference } from '../txs/details/order/tx-order-peg';
|
||||
import { OrderTypeMapping } from '@vegaprotocol/types';
|
||||
|
||||
export interface DeterministicOrderDetailsProps {
|
||||
id: string;
|
||||
@@ -59,7 +60,7 @@ const DeterministicOrderDetails = ({
|
||||
const o = data.orderByID;
|
||||
return (
|
||||
<div className={wrapperClasses}>
|
||||
<div className="mb-12 lg:mb-0">
|
||||
<div className="mb-0">
|
||||
<div className="relative block px-3 py-6 md:px-6 lg:-mr-7">
|
||||
<h2 className="text-3xl font-bold mb-4 display-5">
|
||||
<abbr title={tifFull[o.timeInForce]} className="bb-dotted mr-2">
|
||||
@@ -69,7 +70,7 @@ const DeterministicOrderDetails = ({
|
||||
<span className="mx-5 text-base">@</span>
|
||||
<PriceInMarket price={o.price} marketId={o.market.id} />
|
||||
</h2>
|
||||
<p className="text-gray-200">
|
||||
<p className="text-gray-400 dark:text-gray-600">
|
||||
In <MarketLink id={o.market.id} /> at <Time date={o.createdAt} />.
|
||||
</p>
|
||||
{o.peggedOrder ? (
|
||||
@@ -83,15 +84,14 @@ const DeterministicOrderDetails = ({
|
||||
/>
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{o.reference ? (
|
||||
<p className="text-gray-500 mt-4">
|
||||
<span>{t('Reference')}</span>: {o.reference}
|
||||
</p>
|
||||
) : null}
|
||||
<div className="grid md:grid-cols-4 gap-x-6 mt-4">
|
||||
<div className="mb-12 md:mb-0">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
<div className="grid grid-cols-2 md:grid-cols-5 gap-x-6 mt-4">
|
||||
<div className="mb-6 md:mb-0">
|
||||
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
|
||||
{t('Status')}
|
||||
</h2>
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0 capitalize">
|
||||
@@ -99,21 +99,33 @@ const DeterministicOrderDetails = ({
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div className="mb-12 md:mb-0">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">{t('Size')}</h2>
|
||||
<div className="mb-6 md:mb-0">
|
||||
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
|
||||
{t('Size')}
|
||||
</h2>
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
<SizeInMarket size={o.size} marketId={o.market.id} />
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div className="">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
<div className="mb-6 md:mb-0">
|
||||
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
|
||||
{t('Version')}
|
||||
</h2>
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
{o.version}
|
||||
</h5>
|
||||
</div>
|
||||
{o.type ? (
|
||||
<div className="mb-6 md:mb-0">
|
||||
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
|
||||
{t('Type')}
|
||||
</h2>
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
{OrderTypeMapping[o.type]}
|
||||
</h5>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@ describe('Order TX Summary component', () => {
|
||||
expect(res.queryByTestId('order-summary')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders nothing if the order passed lacks a price', () => {
|
||||
it('Renders "Market Price" if the order passed lacks a price', () => {
|
||||
const o: Order = {
|
||||
marketId: '123',
|
||||
side: 'SIDE_BUY',
|
||||
@@ -41,7 +41,7 @@ describe('Order TX Summary component', () => {
|
||||
size: '10',
|
||||
};
|
||||
const res = renderComponent(o);
|
||||
expect(res.queryByTestId('order-summary')).not.toBeInTheDocument();
|
||||
expect(res.queryByText('Market Price')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders nothing if the order has an unspecified side', () => {
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { components } from '../../../types/explorer';
|
||||
import PriceInMarket from '../price-in-market/price-in-market';
|
||||
import { sideText } from '../order-details/lib/order-labels';
|
||||
import SizeInMarket from '../size-in-market/size-in-market';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export type OrderSummaryProps = {
|
||||
order: components['schemas']['v1OrderSubmission'];
|
||||
@@ -20,7 +21,6 @@ const OrderTxSummary = ({ order }: OrderSummaryProps) => {
|
||||
if (
|
||||
!order ||
|
||||
!order.marketId ||
|
||||
!order.price ||
|
||||
!order.side ||
|
||||
order.side === 'SIDE_UNSPECIFIED'
|
||||
) {
|
||||
@@ -36,10 +36,14 @@ const OrderTxSummary = ({ order }: OrderSummaryProps) => {
|
||||
'-'
|
||||
)}
|
||||
<i className="text-xs">@</i>
|
||||
<PriceInMarket
|
||||
marketId={order.marketId}
|
||||
price={order.price}
|
||||
></PriceInMarket>
|
||||
{order.price ? (
|
||||
<PriceInMarket
|
||||
marketId={order.marketId}
|
||||
price={order.price}
|
||||
></PriceInMarket>
|
||||
) : (
|
||||
t('Market Price')
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -33,6 +33,8 @@ const PriceInMarket = ({
|
||||
label = addDecimalsFormatNumber(price, data.market.decimalPlaces);
|
||||
} else if (
|
||||
decimalSource === 'SETTLEMENT_ASSET' &&
|
||||
data.market &&
|
||||
'settlementAsset' in data.market.tradableInstrument.instrument.product &&
|
||||
data.market?.tradableInstrument.instrument.product.settlementAsset
|
||||
) {
|
||||
label = addDecimalsFormatNumber(
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { type ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { VoteProgress } from '@vegaprotocol/proposals';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
type VegaICellRendererParams,
|
||||
type VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||
import { type ColDef } from 'ag-grid-community';
|
||||
import type { RowClickedEvent } from 'ag-grid-community';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
@@ -33,7 +34,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.governance_proposal_market_requiredMajority,
|
||||
]);
|
||||
const tokenLink = useLinks(DApp.Token);
|
||||
const tokenLink = useLinks(DApp.Governance);
|
||||
const requiredMajorityPercentage = useMemo(() => {
|
||||
const requiredMajority =
|
||||
params?.governance_proposal_market_requiredMajority ?? 1;
|
||||
@@ -43,11 +44,11 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
const gridRef = useRef<AgGridReact>(null);
|
||||
useLayoutEffect(() => {
|
||||
const showColumnsOnDesktop = () => {
|
||||
gridRef.current?.columnApi.setColumnsVisible(
|
||||
gridRef.current?.api.setColumnsVisible(
|
||||
['voting', 'cDate', 'eDate', 'type'],
|
||||
window.innerWidth > BREAKPOINT_MD
|
||||
);
|
||||
gridRef.current?.columnApi.setColumnWidth(
|
||||
gridRef.current?.api.setColumnWidth(
|
||||
'actions',
|
||||
window.innerWidth > BREAKPOINT_MD ? 221 : 80
|
||||
);
|
||||
@@ -105,7 +106,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
? new BigNumber(0)
|
||||
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
|
||||
return (
|
||||
<div className="uppercase flex h-full items-center justify-center pt-2">
|
||||
<div className="flex h-full items-center justify-center pt-2 uppercase">
|
||||
<VoteProgress
|
||||
threshold={requiredMajorityPercentage}
|
||||
progress={yesPercentage}
|
||||
@@ -137,7 +138,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||
headerName: t('Enactment date'),
|
||||
field: 'terms.enactmentDatetime',
|
||||
valueFormatte: ({
|
||||
valueFormatter: ({
|
||||
value,
|
||||
}: VegaValueFormatterParams<
|
||||
ProposalListFieldsFragment,
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { useState } from 'react';
|
||||
import type { BlockExplorerTransactionResult } from '../../routes/types/block-explorer-response';
|
||||
import {
|
||||
CopyWithTooltip,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
interface SignatureProps {
|
||||
signature: BlockExplorerTransactionResult['signature'];
|
||||
}
|
||||
|
||||
const valueClass =
|
||||
'font-mono px-2.5 py-0.5 text-xs max-w-[200px] cursor-pointer';
|
||||
const valueClassClosed = 'text-ellipsis overflow-hidden';
|
||||
const valueClassOpen = 'break-words text-left';
|
||||
|
||||
/**
|
||||
* Viewer component for a vega signature. Featuers copy and pasting, truncation
|
||||
*
|
||||
* @param signature
|
||||
*/
|
||||
export const Signature = ({ signature }: SignatureProps) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
if (!signature || !signature.value || !signature.version || !signature.algo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="inline-flex border rounded signature-component relative pr-[20px]">
|
||||
<div
|
||||
className="bg-gray-100 px-2.5 py-0.5 text-xs text-gray-500 select-none cursor-default"
|
||||
title={`${signature.algo}`}
|
||||
>
|
||||
<span>v{signature.version}</span>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
isOpen
|
||||
? `${valueClass} ${valueClassOpen}`
|
||||
: `${valueClass} ${valueClassClosed}`
|
||||
}
|
||||
>
|
||||
<CopyWithTooltip text={signature.value}>
|
||||
<span title={signature.value}>{signature.value}</span>
|
||||
</CopyWithTooltip>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="absolute top-[-3px] right-0 pr-2"
|
||||
title={t('Show full signature')}
|
||||
>
|
||||
<VegaIcon name={isOpen ? VegaIconNames.EYE_OFF : VegaIconNames.EYE} />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -22,5 +22,9 @@ export const TimeAgo = ({ date, ...props }: TimeAgoProps) => {
|
||||
return <>{t('Date unknown')}</>;
|
||||
}
|
||||
|
||||
return <span {...props}>{t(`${distanceToNow} ago`)}</span>;
|
||||
return (
|
||||
<span {...props} title={date} className="underline decoration-dotted">
|
||||
{t(`${distanceToNow} ago`)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ import isUndefined from 'lodash/isUndefined';
|
||||
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
|
||||
import { TxDetailsChainEventWithdrawal } from './tx-erc20-withdrawal';
|
||||
import { TxDetailsChainEventErc20AssetDelist } from './tx-erc20-asset-delist';
|
||||
import { TxDetailsContractCall } from './tx-contract-call';
|
||||
|
||||
interface ChainEventProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@@ -38,7 +39,7 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { builtin, erc20, erc20Multisig, stakingEvent } =
|
||||
const { builtin, erc20, erc20Multisig, stakingEvent, contractCall } =
|
||||
txData.command.chainEvent;
|
||||
|
||||
// Builtin Asset events
|
||||
@@ -140,6 +141,10 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (contractCall) {
|
||||
return <TxDetailsContractCall contractCall={contractCall} />;
|
||||
}
|
||||
|
||||
// If we hit this return, tx-shared-details should give a basic overview
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { decodeEthCallResult } from './tx-contract-call';
|
||||
import { base64 } from 'ethers/lib/utils';
|
||||
import { defaultAbiCoder } from '@ethersproject/abi';
|
||||
import { BigNumber } from '@ethersproject/bignumber';
|
||||
|
||||
describe('decodeEthCallResult', () => {
|
||||
it('should decode contractData correctly (mocked)', () => {
|
||||
const mockContractData = base64.encode(
|
||||
defaultAbiCoder.encode(['int256'], [BigNumber.from(123)])
|
||||
);
|
||||
const result = decodeEthCallResult(mockContractData);
|
||||
expect(result).toBe('123');
|
||||
});
|
||||
|
||||
it('should decode contractData correctly (known data)', () => {
|
||||
const mockContractData = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADH8cueyY=';
|
||||
const result = decodeEthCallResult(mockContractData);
|
||||
expect(result).toBe('3435020581670');
|
||||
});
|
||||
|
||||
it('should return "-" when an error occurs', () => {
|
||||
const mockContractData = 'invalid_data';
|
||||
const result = decodeEthCallResult(mockContractData);
|
||||
expect(result).toBe('-');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,102 @@
|
||||
import { TableCell, TableRow } from '../../../table';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
ExternalExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/external-explorer-link/external-explorer-link';
|
||||
import { getExternalChainLabel } from '../../../links/external-explorer-link/external-chain';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { defaultAbiCoder, base64 } from 'ethers/lib/utils';
|
||||
import { BigNumber } from 'ethers';
|
||||
import OracleLink from '../../../links/oracle-link/oracle-link';
|
||||
import { useExplorerOracleSpecByIdQuery } from '../../../../routes/oracles/__generated__/Oracles';
|
||||
import { OracleEthSource } from '../../../../routes/oracles/components/oracle-eth-source';
|
||||
|
||||
/**
|
||||
* Decodes the b64/ABIcoded result from an eth cal
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
export function decodeEthCallResult(contractData: string): string {
|
||||
try {
|
||||
const rawResult = defaultAbiCoder.decode(
|
||||
['int256'],
|
||||
base64.decode(contractData)
|
||||
);
|
||||
|
||||
// Finally, convert the resulting BigNumber in to a string
|
||||
const res = BigNumber.from(rawResult[0]).toString();
|
||||
return res;
|
||||
} catch (e) {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
|
||||
interface TxDetailsContractCallProps {
|
||||
contractCall: components['schemas']['vegaEthContractCallEvent'];
|
||||
}
|
||||
|
||||
export const TxDetailsContractCall = ({
|
||||
contractCall,
|
||||
}: TxDetailsContractCallProps) => {
|
||||
const { data } = useExplorerOracleSpecByIdQuery({
|
||||
variables: {
|
||||
id: contractCall.specId || '1',
|
||||
},
|
||||
});
|
||||
|
||||
if (!contractCall) {
|
||||
return null;
|
||||
}
|
||||
const chainLabel = getExternalChainLabel(contractCall.sourceChainId);
|
||||
return (
|
||||
<>
|
||||
{contractCall.specId && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Oracle')}</TableCell>
|
||||
<TableCell>
|
||||
<OracleLink
|
||||
id={contractCall.specId}
|
||||
hasSeenOracleReports={true}
|
||||
status={data?.oracleSpec?.dataSourceSpec.spec.status || '-'}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{contractCall.blockHeight && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>
|
||||
{chainLabel} {t('block')}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<ExternalExplorerLink
|
||||
chain={contractCall.sourceChainId}
|
||||
id={contractCall.blockHeight}
|
||||
type={EthExplorerLinkTypes.block}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{data?.oracleSpec?.dataSourceSpec && (
|
||||
<OracleEthSource
|
||||
chain={contractCall.sourceChainId}
|
||||
sourceType={data.oracleSpec.dataSourceSpec.spec.data.sourceType}
|
||||
/>
|
||||
)}
|
||||
|
||||
{contractCall.error && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Call error')}</TableCell>
|
||||
<TableCell>{contractCall.error}</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
|
||||
{contractCall.result && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Result')}</TableCell>
|
||||
<TableCell>{decodeEthCallResult(contractCall.result)}</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
+3
-3
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
ExternalExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
} from '../../../links/external-explorer-link/external-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventErc20AssetLimitsUpdatedProps {
|
||||
assetLimitsUpdated: components['schemas']['vegaERC20AssetLimitsUpdated'];
|
||||
@@ -42,7 +42,7 @@ export const TxDetailsChainEventErc20AssetLimitsUpdated = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('ERC20 asset')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
<ExternalExplorerLink
|
||||
id={assetLimitsUpdated.sourceEthereumAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
ExternalExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
} from '../../../links/external-explorer-link/external-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventErc20AssetListProps {
|
||||
assetList: components['schemas']['vegaERC20AssetList'];
|
||||
@@ -32,7 +32,7 @@ export const TxDetailsChainEventErc20AssetList = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
<ExternalExplorerLink
|
||||
id={assetList.assetSource}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink, PartyLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
ExternalExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
} from '../../../links/external-explorer-link/external-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventProps {
|
||||
deposit: components['schemas']['vegaERC20Deposit'];
|
||||
@@ -36,7 +36,7 @@ export const TxDetailsChainEventDeposit = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
<ExternalExplorerLink
|
||||
id={deposit.sourceEthereumAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
ExternalExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
} from '../../../links/external-explorer-link/external-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventWithdrawalProps {
|
||||
withdrawal: components['schemas']['vegaERC20Withdrawal'];
|
||||
@@ -35,7 +35,7 @@ export const TxDetailsChainEventWithdrawal = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Recipient')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
<ExternalExplorerLink
|
||||
id={withdrawal.targetEthereumAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { PartyLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
ExternalExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
} from '../../../links/external-explorer-link/external-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventStakeDepositProps {
|
||||
deposit: components['schemas']['vegaStakeDeposited'];
|
||||
@@ -39,7 +39,7 @@ export const TxDetailsChainEventStakeDeposit = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
<ExternalExplorerLink
|
||||
id={deposit.ethereumAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { PartyLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
ExternalExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
} from '../../../links/external-explorer-link/external-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventStakeRemoveProps {
|
||||
remove: components['schemas']['vegaStakeRemoved'];
|
||||
@@ -39,7 +39,7 @@ export const TxDetailsChainEventStakeRemove = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
<ExternalExplorerLink
|
||||
id={remove.ethereumAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { t } from '@vegaprotocol/i18n';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
ExternalExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
} from '../../../links/external-explorer-link/external-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventStakeTotalSupplyProps {
|
||||
update: components['schemas']['vegaStakeTotalSupply'];
|
||||
@@ -38,7 +38,7 @@ export const TxDetailsChainEventStakeTotalSupply = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
<ExternalExplorerLink
|
||||
id={update.tokenAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
query ExplorerSettlementAssetForMarket($id: ID!) {
|
||||
market(id: $id) {
|
||||
id
|
||||
decimalPlaces
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user