Compare commits
1914 Commits
@0xproject
...
@0xproject
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
599554b785 | ||
|
|
d57d282cab | ||
|
|
562bef98e2 | ||
|
|
900f819be8 | ||
|
|
e7337c2451 | ||
|
|
dc81193132 | ||
|
|
fa868b4963 | ||
|
|
62945ad363 | ||
|
|
61c38d35be | ||
|
|
4e0ec72896 | ||
|
|
c28289e9a8 | ||
|
|
e7e9ddf232 | ||
|
|
f03784ba37 | ||
|
|
2445e23c0b | ||
|
|
cd29483187 | ||
|
|
9bacbdab48 | ||
|
|
551d484fb7 | ||
|
|
ff66432b83 | ||
|
|
a7ae82a2d1 | ||
|
|
5f34b5a80e | ||
|
|
8fca2a8116 | ||
|
|
5472500119 | ||
|
|
8fb5c29b4b | ||
|
|
40a061a5ca | ||
|
|
2ef82592a3 | ||
|
|
14b5448d70 | ||
|
|
e7d45e47bf | ||
|
|
28268d4355 | ||
|
|
50fa02c1d1 | ||
|
|
b36ff9103d | ||
|
|
f032c2466c | ||
|
|
b63ddc9be4 | ||
|
|
171430b617 | ||
|
|
d561043774 | ||
|
|
b1871e9ddd | ||
|
|
b4a5e7258c | ||
|
|
3c75debdf9 | ||
|
|
84d1053f73 | ||
|
|
f9df42f5d9 | ||
|
|
4414ef0a0f | ||
|
|
b7729ada38 | ||
|
|
3da67feeb2 | ||
|
|
8a0d563a32 | ||
|
|
612fc4a949 | ||
|
|
bf915ce403 | ||
|
|
0f9ea9773e | ||
|
|
447a3a6c26 | ||
|
|
f1cc16c44d | ||
|
|
aae16b6343 | ||
|
|
834e1538d1 | ||
|
|
afc489bc2c | ||
|
|
3e061e7364 | ||
|
|
6395c2a8b2 | ||
|
|
c8225288cd | ||
|
|
4a108aa67d | ||
|
|
fd9b3e0dcf | ||
|
|
f94b647e61 | ||
|
|
2eccc3efaf | ||
|
|
972341725e | ||
|
|
40b10fd29d | ||
|
|
b31fcffc76 | ||
|
|
ec222ea0cd | ||
|
|
5533220da0 | ||
|
|
6ee7024457 | ||
|
|
f839ac9c58 | ||
|
|
1a8b1460a6 | ||
|
|
feac0779a4 | ||
|
|
d9eeb0421c | ||
|
|
031f97e97c | ||
|
|
b9e1c3c34f | ||
|
|
1a35107a1d | ||
|
|
d3e086c850 | ||
|
|
ab9cfd293b | ||
|
|
cc840a6911 | ||
|
|
c4a2f70017 | ||
|
|
a26cc7c14d | ||
|
|
7fab782907 | ||
|
|
cf7967e629 | ||
|
|
0eacbac8f6 | ||
|
|
cec76c33b6 | ||
|
|
18dcf98998 | ||
|
|
251218af8b | ||
|
|
c06ed58582 | ||
|
|
4de6221825 | ||
|
|
22f3f57f44 | ||
|
|
b2f362225c | ||
|
|
40ed59ce28 | ||
|
|
839db68571 | ||
|
|
fec6ac3ff0 | ||
|
|
45fa26dc6c | ||
|
|
f49d432fdc | ||
|
|
1a31ceff8e | ||
|
|
cc486cb86d | ||
|
|
7a45a579c0 | ||
|
|
dc58d539c2 | ||
|
|
2ba78eb740 | ||
|
|
f43b275f16 | ||
|
|
509a81a572 | ||
|
|
184232ba4f | ||
|
|
0bc338ba42 | ||
|
|
406e91d387 | ||
|
|
473acafd14 | ||
|
|
7474e6b1c9 | ||
|
|
323955277c | ||
|
|
03b5b09122 | ||
|
|
fe00c06d4b | ||
|
|
ca08dd9705 | ||
|
|
b3e53b609b | ||
|
|
fdeab0475c | ||
|
|
f86cc0dc7a | ||
|
|
0457c959dd | ||
|
|
c520b7f1fb | ||
|
|
5422bf5733 | ||
|
|
a703160226 | ||
|
|
d0905eda49 | ||
|
|
da60008048 | ||
|
|
7c023233f2 | ||
|
|
1e7003a307 | ||
|
|
8cb074657d | ||
|
|
5f72b86ce4 | ||
|
|
09d33792f3 | ||
|
|
a6773b85d2 | ||
|
|
5f678acf46 | ||
|
|
76f9ad0705 | ||
|
|
478f6ed011 | ||
|
|
c94d1b2275 | ||
|
|
7d60356fac | ||
|
|
58fa35641d | ||
|
|
b74957acdf | ||
|
|
6aed4fb1ae | ||
|
|
ad8e12eeae | ||
|
|
31763a018c | ||
|
|
bc20f8a004 | ||
|
|
3f6876c419 | ||
|
|
fb9c774558 | ||
|
|
7df9393d29 | ||
|
|
c6439def2c | ||
|
|
273d3445e4 | ||
|
|
bc3dc52377 | ||
|
|
ef1d484d9e | ||
|
|
63cd5a6296 | ||
|
|
657dc785ea | ||
|
|
461e74d8be | ||
|
|
a7daea1728 | ||
|
|
c4416f9696 | ||
|
|
f9ad34170d | ||
|
|
45f2a8ad06 | ||
|
|
3dad802c90 | ||
|
|
735166f06c | ||
|
|
042df52e5c | ||
|
|
294a65f842 | ||
|
|
bf8550ae1e | ||
|
|
91549ef28c | ||
|
|
95956eff64 | ||
|
|
bcae71dfa4 | ||
|
|
d370296e82 | ||
|
|
f42f608f3f | ||
|
|
f78b5741c3 | ||
|
|
733fe5b335 | ||
|
|
c093aab350 | ||
|
|
44f17c1706 | ||
|
|
8302e1687a | ||
|
|
7ad4380653 | ||
|
|
bea185ce8b | ||
|
|
5a73b8a8e6 | ||
|
|
da62a0af3b | ||
|
|
1137abfd33 | ||
|
|
e972ed8456 | ||
|
|
2e1c2d9dfe | ||
|
|
83dd333eba | ||
|
|
f854f3ee2b | ||
|
|
1055ca6d44 | ||
|
|
a5fea3b9c3 | ||
|
|
62f1430a2c | ||
|
|
1dec6a442e | ||
|
|
97831e3702 | ||
|
|
7eb9444458 | ||
|
|
ebc296ea31 | ||
|
|
75d24dea0e | ||
|
|
a6f72de09d | ||
|
|
96037aed52 | ||
|
|
f9d80adaee | ||
|
|
422e5a19d4 | ||
|
|
3d58b38e4e | ||
|
|
0a044199a1 | ||
|
|
cd5f00ac4d | ||
|
|
23c4027c83 | ||
|
|
eeb08b7fae | ||
|
|
20beb2bdb6 | ||
|
|
c6882d0bd8 | ||
|
|
ce47e83939 | ||
|
|
832e1e2cf7 | ||
|
|
6d61616492 | ||
|
|
d5304fb5bd | ||
|
|
13a61db289 | ||
|
|
93b74cc766 | ||
|
|
28e83c21e2 | ||
|
|
33ed5cd437 | ||
|
|
37c8e21f25 | ||
|
|
7b726650e9 | ||
|
|
d3adb48c2e | ||
|
|
9838124abc | ||
|
|
4df847c349 | ||
|
|
c64ad1af28 | ||
|
|
e83b056bd4 | ||
|
|
eba6dcc497 | ||
|
|
017b5a23d8 | ||
|
|
c7a147f49d | ||
|
|
f84a466d16 | ||
|
|
382a805c7e | ||
|
|
0b38e575d6 | ||
|
|
209266dbed | ||
|
|
20f6d8d3d0 | ||
|
|
09b26645ee | ||
|
|
9f2258ebd9 | ||
|
|
71e2ee62e4 | ||
|
|
6c8ee4d55d | ||
|
|
f94d4b492d | ||
|
|
e01a4fcbb4 | ||
|
|
5ed9b8b1dc | ||
|
|
17f3d5f6ba | ||
|
|
607d738342 | ||
|
|
1b102f9ed3 | ||
|
|
6c38481550 | ||
|
|
9cbd151658 | ||
|
|
419b670aa3 | ||
|
|
a44874d2eb | ||
|
|
e9d70b7b1e | ||
|
|
73c6f11c9c | ||
|
|
a9c5488620 | ||
|
|
906af858a5 | ||
|
|
b699a61f56 | ||
|
|
8eabc49e9d | ||
|
|
9e67e12732 | ||
|
|
2d30183d65 | ||
|
|
fcb0a05880 | ||
|
|
fad7dc9f04 | ||
|
|
7c1e05d33c | ||
|
|
02147f546e | ||
|
|
3d51bc1ada | ||
|
|
95df4433dc | ||
|
|
0f1589a43f | ||
|
|
27262c4e56 | ||
|
|
c9b8f2a397 | ||
|
|
72b2a1c66f | ||
|
|
69a6166b6a | ||
|
|
bf87b1a6af | ||
|
|
2e8a5602b2 | ||
|
|
0ec1c4ad6d | ||
|
|
15a3a8c62f | ||
|
|
f001181e39 | ||
|
|
2c659d3d82 | ||
|
|
5ffff7397e | ||
|
|
1a36459ab8 | ||
|
|
33cc79c13b | ||
|
|
b4cb21b55e | ||
|
|
ae68c3abe4 | ||
|
|
939e2c70c4 | ||
|
|
14b29172b1 | ||
|
|
58794fc8e9 | ||
|
|
91fdd6fc29 | ||
|
|
8dd9124863 | ||
|
|
3fc99dbad5 | ||
|
|
01dd84dced | ||
|
|
6b92ef733c | ||
|
|
fe0f4ae257 | ||
|
|
cf9555debc | ||
|
|
528008b1a9 | ||
|
|
5e3576ed69 | ||
|
|
28ee9e247e | ||
|
|
a054b485d0 | ||
|
|
3585326d7e | ||
|
|
a6046af024 | ||
|
|
adaff92c92 | ||
|
|
0499541e11 | ||
|
|
f08738e133 | ||
|
|
1fbdc14734 | ||
|
|
3e683162e9 | ||
|
|
8e7937bdb6 | ||
|
|
b36587fac8 | ||
|
|
3a1f9d01e8 | ||
|
|
1131d66b3d | ||
|
|
7104ae4752 | ||
|
|
2403323463 | ||
|
|
feb7dfffa1 | ||
|
|
005e633e2a | ||
|
|
127fe971e9 | ||
|
|
3c4bde6ea1 | ||
|
|
dc19690863 | ||
|
|
47604384d4 | ||
|
|
c69984e309 | ||
|
|
b8c611de2b | ||
|
|
9c827a0298 | ||
|
|
766aeaa9e1 | ||
|
|
567768c66a | ||
|
|
deaa5f3211 | ||
|
|
5682cd0048 | ||
|
|
11f1ccf3ff | ||
|
|
2896110d4d | ||
|
|
d05b175e04 | ||
|
|
10a379077c | ||
|
|
ffd9b79100 | ||
|
|
04c07d9006 | ||
|
|
a3cc5c1dd7 | ||
|
|
941342cc24 | ||
|
|
cc471dd127 | ||
|
|
9b535e3cec | ||
|
|
9656895726 | ||
|
|
121b6949a1 | ||
|
|
fb31c49317 | ||
|
|
e51f9b3593 | ||
|
|
d08bfbf705 | ||
|
|
a10e466fed | ||
|
|
35bb010c35 | ||
|
|
0046a0762c | ||
|
|
c453012a8e | ||
|
|
1f82c7eadf | ||
|
|
b6fb8dbb52 | ||
|
|
30256cbe51 | ||
|
|
7f46e9af2c | ||
|
|
417cec9e04 | ||
|
|
62a55c0135 | ||
|
|
72336eb393 | ||
|
|
12d8c0b6af | ||
|
|
5c232b6a8d | ||
|
|
f6fd4281a4 | ||
|
|
4bee63afc6 | ||
|
|
d186f6148b | ||
|
|
2b15c03b9a | ||
|
|
60d879e045 | ||
|
|
858d1768ce | ||
|
|
fc2b7f747b | ||
|
|
207019c7f3 | ||
|
|
b264bbea84 | ||
|
|
32efb3e280 | ||
|
|
1a0d68d49a | ||
|
|
7dd3b2d38b | ||
|
|
4bc65faf1a | ||
|
|
8634551f53 | ||
|
|
089663ccc1 | ||
|
|
d1d26f8bf6 | ||
|
|
1ca86730fa | ||
|
|
12ae7c009d | ||
|
|
51b2fce8c1 | ||
|
|
62fcb51e1a | ||
|
|
cbc55f2ef8 | ||
|
|
679f828e4e | ||
|
|
4a8b4e7398 | ||
|
|
b6a11ca31e | ||
|
|
a30ccf2b25 | ||
|
|
2574405699 | ||
|
|
3ba78553f0 | ||
|
|
4d485fc424 | ||
|
|
85f28ade86 | ||
|
|
f6f2991a44 | ||
|
|
4ea222bbff | ||
|
|
f9f5e04b41 | ||
|
|
ea6706a2af | ||
|
|
64c5c5eb40 | ||
|
|
823f2db09f | ||
|
|
a71e511f82 | ||
|
|
39c0064ffb | ||
|
|
12d5c35d14 | ||
|
|
1a161cc02e | ||
|
|
96f19ba8da | ||
|
|
a63dfb7995 | ||
|
|
97ea1e300a | ||
|
|
d87d93dfac | ||
|
|
3ffcb03d87 | ||
|
|
33b08b90a3 | ||
|
|
cbca2061f7 | ||
|
|
bf4873e519 | ||
|
|
8fc1b38ff2 | ||
|
|
7d957538b4 | ||
|
|
7a8edb5018 | ||
|
|
2193d9ae6e | ||
|
|
79d01fe2d7 | ||
|
|
0d02037a12 | ||
|
|
d263f7783f | ||
|
|
d8ef76fd5e | ||
|
|
bc3c7a30c4 | ||
|
|
7b318b3cc2 | ||
|
|
e5cf41b313 | ||
|
|
74012ad584 | ||
|
|
06b4f007f8 | ||
|
|
a9cf425410 | ||
|
|
5355da6cad | ||
|
|
38f7c4a0d2 | ||
|
|
1fcf3c5dc4 | ||
|
|
20b0afacf5 | ||
|
|
6dbe8dbc50 | ||
|
|
73e23996a6 | ||
|
|
e40bce253c | ||
|
|
74c279ea3a | ||
|
|
6c13b792f9 | ||
|
|
6be7466c4a | ||
|
|
1dbdd7ee1f | ||
|
|
eb89926cee | ||
|
|
7923ff4ac6 | ||
|
|
783314c037 | ||
|
|
15cf64318c | ||
|
|
442017f93a | ||
|
|
4dd9f29769 | ||
|
|
f2f9bd2e7a | ||
|
|
d95b8ef3e1 | ||
|
|
ed0c64fdcf | ||
|
|
9a91e39b3f | ||
|
|
ce3f25d48f | ||
|
|
b669508c34 | ||
|
|
364d8824af | ||
|
|
749354b1c0 | ||
|
|
be73084e04 | ||
|
|
5eb90697c8 | ||
|
|
faedd2fa0b | ||
|
|
c47fb8f9a8 | ||
|
|
27b915789e | ||
|
|
ddc6dca98c | ||
|
|
72aa3d3005 | ||
|
|
e8d4f6d532 | ||
|
|
631e7e9c58 | ||
|
|
3c84ce2050 | ||
|
|
9db1ce7ceb | ||
|
|
e472f7899f | ||
|
|
b053781453 | ||
|
|
f892b7dbf6 | ||
|
|
b146acc69e | ||
|
|
63b941fbaf | ||
|
|
29dc22e208 | ||
|
|
c44f9e56ad | ||
|
|
2fe209d5ff | ||
|
|
41bd0e30d6 | ||
|
|
40f4dd91e9 | ||
|
|
5bf43a3560 | ||
|
|
f0afc0ae45 | ||
|
|
916b4d3a26 | ||
|
|
6d1a587c5c | ||
|
|
bce97c2543 | ||
|
|
34446cf569 | ||
|
|
1e13e927d0 | ||
|
|
3c0fa0b7e6 | ||
|
|
ad894fbdbb | ||
|
|
7d9c6eafbf | ||
|
|
de6f757ec8 | ||
|
|
3eeb8f4d6d | ||
|
|
f44ef7ce59 | ||
|
|
b08c616713 | ||
|
|
3ad693d334 | ||
|
|
7d8badc86e | ||
|
|
854d65b51b | ||
|
|
4aa67e2925 | ||
|
|
260ab2d413 | ||
|
|
a824957de7 | ||
|
|
4017c172a2 | ||
|
|
65b2c936ab | ||
|
|
eee190826a | ||
|
|
20a1deb187 | ||
|
|
9169913a2c | ||
|
|
df773d07f3 | ||
|
|
bf0ef055fb | ||
|
|
4e4842a62f | ||
|
|
a34c9095c3 | ||
|
|
efdbc1ff6c | ||
|
|
84a4b7d1c1 | ||
|
|
a9b5faa787 | ||
|
|
49a54c0ff6 | ||
|
|
70d403e6f8 | ||
|
|
eecf09f515 | ||
|
|
5b69cd4a22 | ||
|
|
61fc3346c2 | ||
|
|
c80b42712a | ||
|
|
8d76d74a17 | ||
|
|
b7e98abc43 | ||
|
|
6f72fed8b5 | ||
|
|
27575e9866 | ||
|
|
986ba175ce | ||
|
|
919b327fc5 | ||
|
|
e05b55d4a5 | ||
|
|
073bf738dd | ||
|
|
68e8d6f304 | ||
|
|
6f24337a53 | ||
|
|
0e8f5004d6 | ||
|
|
524e4707d2 | ||
|
|
22fa5a57a5 | ||
|
|
e30c76b743 | ||
|
|
a0fac663f7 | ||
|
|
277e58c2e5 | ||
|
|
75a51af006 | ||
|
|
24454938e5 | ||
|
|
774ab8a8ef | ||
|
|
21dc94b709 | ||
|
|
d6176872f7 | ||
|
|
c396be42b9 | ||
|
|
89a72ebf0d | ||
|
|
7f7ddee0f9 | ||
|
|
b99c797945 | ||
|
|
59edca4166 | ||
|
|
fbba5e054a | ||
|
|
ea47613d90 | ||
|
|
9d18f751c8 | ||
|
|
9745dfe2f4 | ||
|
|
29d38593d6 | ||
|
|
d76bc18bb7 | ||
|
|
cbe61ac315 | ||
|
|
250d97a7c4 | ||
|
|
249bf0163d | ||
|
|
20aaab0847 | ||
|
|
3e648cfb7e | ||
|
|
2106d7476d | ||
|
|
43e07e7ce3 | ||
|
|
5e4e27fed5 | ||
|
|
6c02722f56 | ||
|
|
5cfebd2680 | ||
|
|
bd20b1747d | ||
|
|
674e56cea6 | ||
|
|
61809130a6 | ||
|
|
f5e6e0eaf7 | ||
|
|
b2c423dd84 | ||
|
|
4a9752d7cd | ||
|
|
7db9a01639 | ||
|
|
e9cb5c069a | ||
|
|
03e4205700 | ||
|
|
fd9278ac02 | ||
|
|
1b7c7037b8 | ||
|
|
913264c811 | ||
|
|
e70b6630f9 | ||
|
|
6d53947fd8 | ||
|
|
1c0d982398 | ||
|
|
a88b4040ff | ||
|
|
e8073cd6f2 | ||
|
|
8281be235c | ||
|
|
9ce03e3515 | ||
|
|
667938696d | ||
|
|
a165281dcf | ||
|
|
185f70f2dd | ||
|
|
cd3e14f45a | ||
|
|
dd87588dfe | ||
|
|
29042e1939 | ||
|
|
4dbf6559aa | ||
|
|
b987b5988d | ||
|
|
6ba6bec105 | ||
|
|
d95b1e2db4 | ||
|
|
c1d6c7ff66 | ||
|
|
6e12794765 | ||
|
|
0f4b05e374 | ||
|
|
695b697cdf | ||
|
|
3aea0e3b2f | ||
|
|
c0e92d511e | ||
|
|
51f2a20b2a | ||
|
|
333a23f222 | ||
|
|
3bf3f479f5 | ||
|
|
6241d06f27 | ||
|
|
9e81d3c87b | ||
|
|
a9b2838c5f | ||
|
|
fbc39614c0 | ||
|
|
b2d6ac8dba | ||
|
|
b090b7b1f2 | ||
|
|
ba0696a0d7 | ||
|
|
b57850a225 | ||
|
|
4d9029bb0e | ||
|
|
bc49dde4d5 | ||
|
|
afe07b2926 | ||
|
|
2411bfc20f | ||
|
|
4d4ea8a4d0 | ||
|
|
595517e68b | ||
|
|
40ab2de393 | ||
|
|
723276ae3f | ||
|
|
76c5945017 | ||
|
|
01c6fd92e8 | ||
|
|
3f230a8fdb | ||
|
|
2a6a71ea6c | ||
|
|
cd23f220a0 | ||
|
|
fab88ea2cc | ||
|
|
688f8615ff | ||
|
|
d187a31e38 | ||
|
|
c6f85464ce | ||
|
|
a220b56736 | ||
|
|
0e33f45f3d | ||
|
|
ff7c3012a5 | ||
|
|
20fec2943b | ||
|
|
08b30b0706 | ||
|
|
bf52ce7e72 | ||
|
|
1bac5019e8 | ||
|
|
19454a92dc | ||
|
|
cdbb3a015f | ||
|
|
644da2b0cb | ||
|
|
57446d78f1 | ||
|
|
3e285c0ef1 | ||
|
|
a322148631 | ||
|
|
33ec9fdf47 | ||
|
|
323826111a | ||
|
|
ddd3d284d9 | ||
|
|
f55a300f43 | ||
|
|
08a69ebd6e | ||
|
|
ddb8e26bec | ||
|
|
57ca611e12 | ||
|
|
1eff120f49 | ||
|
|
4bc6096ec0 | ||
|
|
95eb114051 | ||
|
|
9c856de49c | ||
|
|
d502f79303 | ||
|
|
5224337323 | ||
|
|
ef49192170 | ||
|
|
c9df388731 | ||
|
|
870da2ab22 | ||
|
|
6122840241 | ||
|
|
03b00ef8da | ||
|
|
84b820abc6 | ||
|
|
cc4ff568a9 | ||
|
|
665011174b | ||
|
|
37f210e9f0 | ||
|
|
9c01e3a8a0 | ||
|
|
c4dd9658e7 | ||
|
|
29aa09e448 | ||
|
|
1337b6928a | ||
|
|
ac35d8127e | ||
|
|
a6ae1efadb | ||
|
|
bd7b5c51b2 | ||
|
|
397cd77ef9 | ||
|
|
743c3dbe01 | ||
|
|
9f1c212596 | ||
|
|
defd249565 | ||
|
|
8926dac78c | ||
|
|
18cac3f092 | ||
|
|
01e27426d6 | ||
|
|
0b09cc36b0 | ||
|
|
f3cb484f82 | ||
|
|
0053762760 | ||
|
|
d72b7299c6 | ||
|
|
eb89ef79eb | ||
|
|
066d13f5b7 | ||
|
|
ec06d8d606 | ||
|
|
a2e4aaa9a3 | ||
|
|
26e9696ddb | ||
|
|
343191e936 | ||
|
|
3e3b667366 | ||
|
|
3b45d4727b | ||
|
|
b4f3450d4a | ||
|
|
0a8b7cb494 | ||
|
|
125ace3519 | ||
|
|
109fc41474 | ||
|
|
f30353087f | ||
|
|
d106079d9b | ||
|
|
dc3be992a3 | ||
|
|
bed7d87b7f | ||
|
|
05daab5dea | ||
|
|
170e5589f9 | ||
|
|
538914aa52 | ||
|
|
81deb68c8e | ||
|
|
36986fe9c9 | ||
|
|
5791632933 | ||
|
|
289359bf0d | ||
|
|
81f6487865 | ||
|
|
21b797c3f9 | ||
|
|
de8450d5c9 | ||
|
|
bcb9ee4cc2 | ||
|
|
7c87447241 | ||
|
|
b39d87f357 | ||
|
|
552b14b1fa | ||
|
|
5779ffd01b | ||
|
|
a7c24a17f4 | ||
|
|
8743c40911 | ||
|
|
7ef6bd4b14 | ||
|
|
6af0f08dfc | ||
|
|
54ae94dde0 | ||
|
|
c570f3865f | ||
|
|
ed9d1da297 | ||
|
|
beb483ea85 | ||
|
|
46b7fecafe | ||
|
|
e476682922 | ||
|
|
8478dc8d6d | ||
|
|
9f8e41cbfa | ||
|
|
3916383dd0 | ||
|
|
a60c8f7d8c | ||
|
|
4e5cd472c2 | ||
|
|
e1341bc6d9 | ||
|
|
d437a66019 | ||
|
|
542b46a22f | ||
|
|
6fef533fff | ||
|
|
ec219fc395 | ||
|
|
a555a8a374 | ||
|
|
78e9c48803 | ||
|
|
18d3e5458a | ||
|
|
ac25764d12 | ||
|
|
c55e7fa91a | ||
|
|
e31ba2e12e | ||
|
|
73f8ae9a47 | ||
|
|
32b85625c1 | ||
|
|
629edd3108 | ||
|
|
ee77b81551 | ||
|
|
2c7fdac5cd | ||
|
|
d118116548 | ||
|
|
8d01956c3e | ||
|
|
1dda8c1468 | ||
|
|
111f7e917e | ||
|
|
477daf4168 | ||
|
|
8b52793f2f | ||
|
|
18b9fe5256 | ||
|
|
439e864085 | ||
|
|
f45191d0e8 | ||
|
|
32feadee42 | ||
|
|
c4b4bb9e8e | ||
|
|
8fd705d2af | ||
|
|
3c36135d6c | ||
|
|
02ede26893 | ||
|
|
af21ad1615 | ||
|
|
07fa01528b | ||
|
|
38f716bd77 | ||
|
|
6a410b03ff | ||
|
|
3cd7bce0a3 | ||
|
|
6693540f43 | ||
|
|
647bc5a63e | ||
|
|
4f76bb2a12 | ||
|
|
9991ddecc2 | ||
|
|
3cf2cb89bb | ||
|
|
2875cfa8c7 | ||
|
|
87cbbdad72 | ||
|
|
07de3a1d94 | ||
|
|
27880a6059 | ||
|
|
0367e4117a | ||
|
|
ec582d6e46 | ||
|
|
4ca706d4e6 | ||
|
|
72671c1014 | ||
|
|
a3c31f4f4a | ||
|
|
db8be4a66e | ||
|
|
2f7c19e80d | ||
|
|
7d9c357409 | ||
|
|
abf41b073c | ||
|
|
c9b07107f3 | ||
|
|
773be348a3 | ||
|
|
b7bb8d9b2a | ||
|
|
c7c12371ef | ||
|
|
fb40b10501 | ||
|
|
d4dce41d3a | ||
|
|
293b55e51f | ||
|
|
11bac66046 | ||
|
|
2a438419ab | ||
|
|
0f0aca7de5 | ||
|
|
f699b9a73f | ||
|
|
214096de9e | ||
|
|
a0ccb609cd | ||
|
|
4e05554b3e | ||
|
|
04c08b9fc8 | ||
|
|
86c1c8082d | ||
|
|
c5afc5feb5 | ||
|
|
8392ee4625 | ||
|
|
ac881d149c | ||
|
|
cc4e390c91 | ||
|
|
26c726da45 | ||
|
|
358f3d9b42 | ||
|
|
3337625fa0 | ||
|
|
ae2daa5a6f | ||
|
|
79f521b555 | ||
|
|
fffcb98ac4 | ||
|
|
5468358f21 | ||
|
|
87044313c2 | ||
|
|
794b155827 | ||
|
|
4941ffd354 | ||
|
|
aa8a3ee055 | ||
|
|
c1d17c83f8 | ||
|
|
db030016fa | ||
|
|
ae04f55882 | ||
|
|
b40fab35f6 | ||
|
|
644deee8b5 | ||
|
|
c7302c46e5 | ||
|
|
4948551703 | ||
|
|
d4c1b3b0bd | ||
|
|
bbdb072634 | ||
|
|
d7bf003d51 | ||
|
|
5a827eb3d4 | ||
|
|
b37076136b | ||
|
|
3574ab253f | ||
|
|
312a30578b | ||
|
|
8243e73413 | ||
|
|
5175fe8107 | ||
|
|
2acb767640 | ||
|
|
a9b1dcb32a | ||
|
|
8f8577b7c6 | ||
|
|
0225d34b74 | ||
|
|
8d1e27a1a5 | ||
|
|
e4ea6e1ec3 | ||
|
|
8137d41ce5 | ||
|
|
4b7f0bd374 | ||
|
|
f9ad97b978 | ||
|
|
b145a17d11 | ||
|
|
3430e2bdac | ||
|
|
cdcf925378 | ||
|
|
76029cbf09 | ||
|
|
b9c1653c1c | ||
|
|
f6c01520ae | ||
|
|
0fb4de85c4 | ||
|
|
ffe7363776 | ||
|
|
4a27a7dc58 | ||
|
|
3b3d5b12bc | ||
|
|
380e51ca50 | ||
|
|
aea7207b9f | ||
|
|
9593739938 | ||
|
|
40ebb533b3 | ||
|
|
7fe26ee719 | ||
|
|
28d63ad8e1 | ||
|
|
56eeea1e63 | ||
|
|
642a2cf165 | ||
|
|
e16feb27f4 | ||
|
|
83ae7ba08d | ||
|
|
a86f8a81a2 | ||
|
|
28abcef1ca | ||
|
|
32d15d79f1 | ||
|
|
538ac604a8 | ||
|
|
009b70f5b2 | ||
|
|
f7c1e10b5a | ||
|
|
3f3e8be004 | ||
|
|
cb612360ca | ||
|
|
6a8c2cb717 | ||
|
|
c8a8b851d8 | ||
|
|
ba9a734ba7 | ||
|
|
b08374f0ba | ||
|
|
c2f8858aab | ||
|
|
1f81fa1c6c | ||
|
|
db44a5bca7 | ||
|
|
53e1815c1d | ||
|
|
20985d515f | ||
|
|
0334004b11 | ||
|
|
95e2b37d62 | ||
|
|
dba1b8a7e9 | ||
|
|
ee29ed26ff | ||
|
|
a08ae722c1 | ||
|
|
b3c1c0ccad | ||
|
|
e1fa65f5ef | ||
|
|
a2e848a7fa | ||
|
|
67fbffc964 | ||
|
|
c3b4359e87 | ||
|
|
11ed5d62ba | ||
|
|
5827170815 | ||
|
|
ca25b816fa | ||
|
|
a9db0e8ebe | ||
|
|
a0791455e1 | ||
|
|
efb0ee4c02 | ||
|
|
df1968157c | ||
|
|
355aac2a1a | ||
|
|
b93b66edfb | ||
|
|
92a4e77288 | ||
|
|
7ac646ff94 | ||
|
|
ef6aa9f41b | ||
|
|
df9e7385ad | ||
|
|
e065ac45dc | ||
|
|
745af5309d | ||
|
|
952f1cf8d0 | ||
|
|
86a55fe55a | ||
|
|
88c6694ffc | ||
|
|
20826e0f08 | ||
|
|
e474096119 | ||
|
|
075f286130 | ||
|
|
32e3cab116 | ||
|
|
49ff4299c6 | ||
|
|
4d18a4802d | ||
|
|
d613791104 | ||
|
|
44f7f79bd9 | ||
|
|
1cdfbbadaa | ||
|
|
76a31b6fd6 | ||
|
|
0ad3d06ef9 | ||
|
|
fb0fd8ddc4 | ||
|
|
2a9913b8fb | ||
|
|
9b8d2ed469 | ||
|
|
17148df06d | ||
|
|
d93089fcc0 | ||
|
|
870995933a | ||
|
|
d6c2e47bbd | ||
|
|
e2b2bf1e0d | ||
|
|
c4a18ee64b | ||
|
|
7143996d26 | ||
|
|
22f78a2c52 | ||
|
|
bd7517cfd4 | ||
|
|
9bffce9dc5 | ||
|
|
10f6a17857 | ||
|
|
2197c2481a | ||
|
|
8d90e640b0 | ||
|
|
368870a2fc | ||
|
|
945a19bb61 | ||
|
|
b0abc384bc | ||
|
|
8f45e9a518 | ||
|
|
b06f1d1982 | ||
|
|
4365350430 | ||
|
|
3b158cb726 | ||
|
|
2298a34c37 | ||
|
|
633039c528 | ||
|
|
ee31d5e24d | ||
|
|
f590aa11f7 | ||
|
|
6b7f48644c | ||
|
|
21aac75533 | ||
|
|
95b02a3197 | ||
|
|
be7c444959 | ||
|
|
f02d3f689d | ||
|
|
981752059c | ||
|
|
6c87ebac01 | ||
|
|
a9479b3c01 | ||
|
|
c5afca53a4 | ||
|
|
b4cb88ab26 | ||
|
|
ad4f607643 | ||
|
|
c7d340e822 | ||
|
|
2c501d2380 | ||
|
|
3787e4a83c | ||
|
|
3b77e4ebf1 | ||
|
|
6eebf717d5 | ||
|
|
98f32d6f1f | ||
|
|
62f45f7b41 | ||
|
|
a7d8f6599a | ||
|
|
4da6db8418 | ||
|
|
d991291f2a | ||
|
|
392fb42973 | ||
|
|
13299158d1 | ||
|
|
a6571b09d2 | ||
|
|
870ba445b8 | ||
|
|
caaa70f630 | ||
|
|
56a8e0a09a | ||
|
|
4c08667a07 | ||
|
|
4ac6b6828c | ||
|
|
c050186014 | ||
|
|
63f2606863 | ||
|
|
5160e0ba18 | ||
|
|
0aad2ee005 | ||
|
|
8a58ffda86 | ||
|
|
cea8dcae3d | ||
|
|
fc7e7d9331 | ||
|
|
494bff4bc0 | ||
|
|
824ee8a3dc | ||
|
|
47af38ecb8 | ||
|
|
654c790c3d | ||
|
|
7ebebb5bd9 | ||
|
|
8f921a61da | ||
|
|
cfd734d84f | ||
|
|
342a697e42 | ||
|
|
918f3cde94 | ||
|
|
7b82a8669d | ||
|
|
7116f100ee | ||
|
|
42fce45585 | ||
|
|
9da57daa7f | ||
|
|
e302d23317 | ||
|
|
0edfa83951 | ||
|
|
a5ba049427 | ||
|
|
adba69a589 | ||
|
|
cc73f72d13 | ||
|
|
e4f90996af | ||
|
|
974c0d2b95 | ||
|
|
d1fc2a115e | ||
|
|
a9373c7fb0 | ||
|
|
8b604462ac | ||
|
|
51e4a73439 | ||
|
|
d42cdcfd43 | ||
|
|
c18acd0859 | ||
|
|
9699ee4eff | ||
|
|
c78e504bfb | ||
|
|
0eeaac1f2b | ||
|
|
b578517f91 | ||
|
|
c009e9979e | ||
|
|
22b6097e95 | ||
|
|
8e3446a389 | ||
|
|
1747d7a1bb | ||
|
|
8e5a876b37 | ||
|
|
c71b710d7e | ||
|
|
7440b87596 | ||
|
|
583a17d627 | ||
|
|
caf1a22084 | ||
|
|
29abc5e921 | ||
|
|
098dae9a7e | ||
|
|
aaa7affa46 | ||
|
|
40ca846cdc | ||
|
|
da277f5b27 | ||
|
|
2a24f6e2ea | ||
|
|
98e8105ec5 | ||
|
|
4a94a2b4e8 | ||
|
|
2011349eb1 | ||
|
|
8057f4a678 | ||
|
|
f9ec8a0828 | ||
|
|
a0030c7bdb | ||
|
|
0e4448fd3f | ||
|
|
21d2d59b50 | ||
|
|
295f177271 | ||
|
|
f3154313a8 | ||
|
|
e37f3b4fa3 | ||
|
|
7e5c35d06e | ||
|
|
60756aa02b | ||
|
|
3779ab90de | ||
|
|
5b5037a844 | ||
|
|
03902b0b26 | ||
|
|
883feabb8b | ||
|
|
5fb79e3253 | ||
|
|
c44811fbc2 | ||
|
|
c3eaa694dd | ||
|
|
bd8b8abfea | ||
|
|
1a6c2e2bac | ||
|
|
e2e6ae937d | ||
|
|
5b9c5d2790 | ||
|
|
896a57d4ed | ||
|
|
c3de8d3a67 | ||
|
|
d1a92a0a2e | ||
|
|
5f626495fd | ||
|
|
238f3c89a7 | ||
|
|
6e724eb8a5 | ||
|
|
9aec1feae3 | ||
|
|
8517de128b | ||
|
|
a3e15c910c | ||
|
|
a6303de4d1 | ||
|
|
5356b0e118 | ||
|
|
e31309f213 | ||
|
|
6f8a70834b | ||
|
|
327cc307b3 | ||
|
|
f191ba6e69 | ||
|
|
a2b89411b0 | ||
|
|
f66efed777 | ||
|
|
f61b59fa89 | ||
|
|
6288a72036 | ||
|
|
a941f0ffb6 | ||
|
|
d7373a5c04 | ||
|
|
2ff485d2e0 | ||
|
|
5a67068348 | ||
|
|
d39af6c9eb | ||
|
|
1789025da9 | ||
|
|
696f49497b | ||
|
|
e88eba1877 | ||
|
|
f8b8a10b8f | ||
|
|
01e505a5f4 | ||
|
|
5b2d9a4668 | ||
|
|
71008dc819 | ||
|
|
f27e943258 | ||
|
|
9301173f7d | ||
|
|
60d95475eb | ||
|
|
c8ace2edc0 | ||
|
|
0b1ba9f997 | ||
|
|
f3026e33fd | ||
|
|
f014a97e9a | ||
|
|
ddad09a936 | ||
|
|
5dd0654105 | ||
|
|
b4b664e97a | ||
|
|
551771235b | ||
|
|
eb201c4084 | ||
|
|
7bfc499ec8 | ||
|
|
71e7e9c9c3 | ||
|
|
8521775389 | ||
|
|
61ad8d4c10 | ||
|
|
38a4ccd9f2 | ||
|
|
cf342dd00e | ||
|
|
08ab81c54c | ||
|
|
d355382f70 | ||
|
|
d171ce4fba | ||
|
|
5a90fece80 | ||
|
|
994935b5da | ||
|
|
874e667849 | ||
|
|
1817f6eaf6 | ||
|
|
2e19930178 | ||
|
|
2b01461748 | ||
|
|
24b9df475c | ||
|
|
011bab3c80 | ||
|
|
699c0c3e05 | ||
|
|
5f4b28960e | ||
|
|
3837913855 | ||
|
|
65eb3997d9 | ||
|
|
47411b406d | ||
|
|
f710026a8f | ||
|
|
925e133f50 | ||
|
|
2bdd60ed72 | ||
|
|
9ac1cce26f | ||
|
|
0a597c94d6 | ||
|
|
02f82be094 | ||
|
|
86e26240a1 | ||
|
|
82c5be2564 | ||
|
|
42f4f07268 | ||
|
|
df4db8fa4c | ||
|
|
bd85fe0af3 | ||
|
|
aee15e5dff | ||
|
|
d7a803d9fd | ||
|
|
839e5895e4 | ||
|
|
49a4f0c74c | ||
|
|
5bea8e63de | ||
|
|
e64be284dd | ||
|
|
e11e26a352 | ||
|
|
bee90abbc4 | ||
|
|
8782559c33 | ||
|
|
223ddc0f68 | ||
|
|
4445d1d5a0 | ||
|
|
b7d001da88 | ||
|
|
3592ebef08 | ||
|
|
a783d21409 | ||
|
|
a716e3de74 | ||
|
|
c797c720be | ||
|
|
1b5742fbf0 | ||
|
|
5794349d97 | ||
|
|
456f094913 | ||
|
|
abb9eb0df4 | ||
|
|
9e7b45ea4c | ||
|
|
6c6bd60a48 | ||
|
|
cef82e72dc | ||
|
|
45b9647ba0 | ||
|
|
160f74d53e | ||
|
|
3ab6139522 | ||
|
|
9aa54257e7 | ||
|
|
8eafa62bbe | ||
|
|
968c24f0bc | ||
|
|
e5c755b1fc | ||
|
|
6d56f01c40 | ||
|
|
eefce48e68 | ||
|
|
c7d97c733a | ||
|
|
3db42deb42 | ||
|
|
02603e8926 | ||
|
|
c5003554f4 | ||
|
|
eb223805ca | ||
|
|
244c148a80 | ||
|
|
4dbb2ed167 | ||
|
|
212d680a47 | ||
|
|
a853e35dec | ||
|
|
fdaf9f0bfc | ||
|
|
0afe45b3a8 | ||
|
|
f9a37168b0 | ||
|
|
52232e98c7 | ||
|
|
0fbb443e4b | ||
|
|
8021694b81 | ||
|
|
a2b262c9df | ||
|
|
5906f4c995 | ||
|
|
da8edd2226 | ||
|
|
406aedfdc2 | ||
|
|
67c834841e | ||
|
|
edaa0b0e34 | ||
|
|
31f03fcf3a | ||
|
|
4a57f2a762 | ||
|
|
92b9dbd706 | ||
|
|
6edd7682a9 | ||
|
|
447891b396 | ||
|
|
89bfcafb80 | ||
|
|
a74a04c5d5 | ||
|
|
0c16f0ea22 | ||
|
|
003d43b03a | ||
|
|
6323496945 | ||
|
|
fd5e231a93 | ||
|
|
ae209677de | ||
|
|
d5ca00de95 | ||
|
|
7be84c6ad3 | ||
|
|
425039e4d3 | ||
|
|
6c5333180d | ||
|
|
cb47a51b70 | ||
|
|
e36fb654b0 | ||
|
|
6325fac020 | ||
|
|
c6358d5f22 | ||
|
|
413e8b6062 | ||
|
|
e113a8e7af | ||
|
|
e42891ae5b | ||
|
|
c90770472e | ||
|
|
45df9de5b5 | ||
|
|
2d0940589e | ||
|
|
5908f189a7 | ||
|
|
17328bce53 | ||
|
|
451a0dacbe | ||
|
|
a46199e37d | ||
|
|
e25cc301fd | ||
|
|
5bbb0d1f60 | ||
|
|
a5b8875356 | ||
|
|
3e86df311d | ||
|
|
002f9ebde7 | ||
|
|
72e6e1ce8b | ||
|
|
a3c7af95e1 | ||
|
|
0987c9a7cf | ||
|
|
bbd87daf6d | ||
|
|
30e4613d0a | ||
|
|
79593f52b0 | ||
|
|
bab8c1eeff | ||
|
|
8b6cc95c1b | ||
|
|
90236b87de | ||
|
|
b6a133cc64 | ||
|
|
7aa070f9ea | ||
|
|
c2ec2291e8 | ||
|
|
97fcfb7f6c | ||
|
|
ce677fd55a | ||
|
|
e48a3edacb | ||
|
|
ce0b92d681 | ||
|
|
29c5ba5639 | ||
|
|
cdea618457 | ||
|
|
425a519f97 | ||
|
|
c07d64c6ff | ||
|
|
c07e3a76bb | ||
|
|
8fe844bcc9 | ||
|
|
a0390956a9 | ||
|
|
4f1e6296ca | ||
|
|
0ef372e531 | ||
|
|
06e2894750 | ||
|
|
10e2d4b99c | ||
|
|
ef40cb9687 | ||
|
|
758604fc1a | ||
|
|
34c1134b55 | ||
|
|
a5ef1db0c5 | ||
|
|
748ed40321 | ||
|
|
42063f785e | ||
|
|
1657451f37 | ||
|
|
0bb0bff0b3 | ||
|
|
747732118c | ||
|
|
2aec1501d0 | ||
|
|
39c6bc1106 | ||
|
|
4e451479f8 | ||
|
|
93b2736d65 | ||
|
|
34274a1042 | ||
|
|
fa822caa62 | ||
|
|
ddc30cc2c0 | ||
|
|
9d9cab1711 | ||
|
|
fe8f2d8d89 | ||
|
|
2d561bc8a0 | ||
|
|
f5275d3ad7 | ||
|
|
5fbdf9cfb9 | ||
|
|
0409c9c1e5 | ||
|
|
42a5da1df4 | ||
|
|
0b326a8bbe | ||
|
|
9c8501a84e | ||
|
|
2da7f82171 | ||
|
|
593474031d | ||
|
|
fce10548d2 | ||
|
|
addca63938 | ||
|
|
6961169f89 | ||
|
|
3d66feb89f | ||
|
|
bb157eefc6 | ||
|
|
7f8f4df0a0 | ||
|
|
4b325676f7 | ||
|
|
ecba95250d | ||
|
|
dd116b3cd6 | ||
|
|
eabe96fd19 | ||
|
|
7dd9ce2e32 | ||
|
|
fffaafe4c9 | ||
|
|
0b9646136a | ||
|
|
55f38b9c35 | ||
|
|
709fa9e02e | ||
|
|
f42bdb8bab | ||
|
|
10aed46062 | ||
|
|
6e43e89b2d | ||
|
|
10c0c0b6d2 | ||
|
|
e13924cd2d | ||
|
|
7afe00f06a | ||
|
|
87b9caa7dc | ||
|
|
f689d335c0 | ||
|
|
31f9a848f9 | ||
|
|
3d2c5d67af | ||
|
|
63f8f469b0 | ||
|
|
9929f1acf0 | ||
|
|
42ecc087cb | ||
|
|
93adee36b0 | ||
|
|
0e95fd0b9b | ||
|
|
611ddfeeb8 | ||
|
|
dfe2579eeb | ||
|
|
66b36f6d8f | ||
|
|
1b3a9102f1 | ||
|
|
9993a50903 | ||
|
|
c226509be0 | ||
|
|
ef6f52e722 | ||
|
|
7d8cad8e3a | ||
|
|
15507d3827 | ||
|
|
e2d17d122e | ||
|
|
0d7bf50581 | ||
|
|
a50618fcb0 | ||
|
|
fc2a9a756a | ||
|
|
07721eb99f | ||
|
|
13fed15e0c | ||
|
|
38a308ce5b | ||
|
|
be19316dfb | ||
|
|
c4f65681a1 | ||
|
|
f600226aa9 | ||
|
|
67f2864501 | ||
|
|
c1bbcaba73 | ||
|
|
6685cb3fba | ||
|
|
d770e46208 | ||
|
|
665636e642 | ||
|
|
0028e71ab2 | ||
|
|
7fb66bf71a | ||
|
|
3120d854f8 | ||
|
|
c85c14210f | ||
|
|
0fb81a11a8 | ||
|
|
7b67afae06 | ||
|
|
fe9e319a61 | ||
|
|
097fc477a2 | ||
|
|
f60b00d116 | ||
|
|
3a36e0621f | ||
|
|
b482473e23 | ||
|
|
9a5fd3f784 | ||
|
|
b703ccde9b | ||
|
|
80eca30725 | ||
|
|
7dbc14dc43 | ||
|
|
b3f9010eb5 | ||
|
|
f62d72e548 | ||
|
|
d12352972e | ||
|
|
03d3d84db3 | ||
|
|
6d818c25c7 | ||
|
|
6a8f624e75 | ||
|
|
0801b1ddf9 | ||
|
|
4fd64ca492 | ||
|
|
c4bcf24640 | ||
|
|
0114fc9608 | ||
|
|
8db098eaec | ||
|
|
05c3a66543 | ||
|
|
9349752baa | ||
|
|
974fab7284 | ||
|
|
8a52ffe7b7 | ||
|
|
c6ecdbd86e | ||
|
|
03797545f9 | ||
|
|
2778f96483 | ||
|
|
6cd4e7a17e | ||
|
|
5c91b4bfc6 | ||
|
|
e2b51c5dc4 | ||
|
|
b610b7c192 | ||
|
|
b75fdd6b66 | ||
|
|
060b02eaed | ||
|
|
003e5da00d | ||
|
|
02951d4813 | ||
|
|
db52ed9941 | ||
|
|
af333b1838 | ||
|
|
f62762bd0e | ||
|
|
4b67352278 | ||
|
|
76afb6b116 | ||
|
|
db52e87740 | ||
|
|
e22788abe8 | ||
|
|
bbfbfcda85 | ||
|
|
0dfb36e675 | ||
|
|
95a9d77301 | ||
|
|
ab1f070901 | ||
|
|
8201d5d1f8 | ||
|
|
8704c34a0f | ||
|
|
599adaf1bf | ||
|
|
778e399438 | ||
|
|
485ae4d997 | ||
|
|
8cd2ba3ad6 | ||
|
|
dbad7d1869 | ||
|
|
4d482438f5 | ||
|
|
b53a1b51d6 | ||
|
|
49375c73d4 | ||
|
|
98b78c56c5 | ||
|
|
f3e6ef0fa9 | ||
|
|
18e1c2dea5 | ||
|
|
91ae01e484 | ||
|
|
2897b72967 | ||
|
|
3510985cf4 | ||
|
|
5927e65045 | ||
|
|
13e2041d50 | ||
|
|
4bf530ed9e | ||
|
|
4c797405ad | ||
|
|
713c922e35 | ||
|
|
7f1e789264 | ||
|
|
07d00cc515 | ||
|
|
cd55e346af | ||
|
|
6746428fb1 | ||
|
|
634032d5be | ||
|
|
602abc53dd | ||
|
|
fdbaa9768a | ||
|
|
293d7261e0 | ||
|
|
efb6eb28ce | ||
|
|
ac5531ce85 | ||
|
|
bc2415c70e | ||
|
|
0fd411f83f | ||
|
|
b74ad0ad12 | ||
|
|
4c58836735 | ||
|
|
3206b80dbd | ||
|
|
4910f7a61e | ||
|
|
6e9109eaec | ||
|
|
a04ec14cf0 | ||
|
|
7d3df3c117 | ||
|
|
b3a03f8e3e | ||
|
|
e5668c1e5c | ||
|
|
92e74bc4fa | ||
|
|
7e12269baf | ||
|
|
f3f264f5fd | ||
|
|
2e3c9b87df | ||
|
|
0a113e1cf7 | ||
|
|
fd772c48cf | ||
|
|
1c7dce6054 | ||
|
|
0a2947b860 | ||
|
|
c80877af43 | ||
|
|
e68b9c7e81 | ||
|
|
19198737a5 | ||
|
|
fea4b6aecd | ||
|
|
20e2673b82 | ||
|
|
ef1375b9dd | ||
|
|
58f1939ec1 | ||
|
|
ba57c34adb | ||
|
|
936f6ac10f | ||
|
|
7e04c4f24b | ||
|
|
9495c8f46c | ||
|
|
b3f91600d3 | ||
|
|
ddf4437fb6 | ||
|
|
4153d57849 | ||
|
|
0652790703 | ||
|
|
9c934d903d | ||
|
|
d7a7e28925 | ||
|
|
6dec29e214 | ||
|
|
43cf8d30bd | ||
|
|
254d3f53e2 | ||
|
|
ec198343b5 | ||
|
|
876517d458 | ||
|
|
1233c33116 | ||
|
|
eebf205817 | ||
|
|
e666bb44c6 | ||
|
|
39cb0b5122 | ||
|
|
58003a2811 | ||
|
|
7f2a7cfa77 | ||
|
|
8fba0477a6 | ||
|
|
7ca1ba7e1e | ||
|
|
e6f2c7a382 | ||
|
|
69f5f5e946 | ||
|
|
68a8acbe7b | ||
|
|
852811b314 | ||
|
|
2404ff0304 | ||
|
|
9ff4cacf0f | ||
|
|
e443cb2a3b | ||
|
|
f3c6cce455 | ||
|
|
ae14b0a71d | ||
|
|
3c7ebe2697 | ||
|
|
10fb6061cc | ||
|
|
223df8006a | ||
|
|
1c9428cbba | ||
|
|
18dc5d17b5 | ||
|
|
4d50933189 | ||
|
|
9b3680780f | ||
|
|
a26e77074f | ||
|
|
568e4d33f2 | ||
|
|
fd004032cb | ||
|
|
4b6324050d | ||
|
|
12d62e1157 | ||
|
|
063c6b66b6 | ||
|
|
d9b1d31e73 | ||
|
|
0bad911a16 | ||
|
|
518efa8ad2 | ||
|
|
6e87c9e713 | ||
|
|
b61852b1f5 | ||
|
|
fcbe24a126 | ||
|
|
55312d00ef | ||
|
|
a96e3f3222 | ||
|
|
e35519b50f | ||
|
|
ae775f9664 | ||
|
|
071b1c47d1 | ||
|
|
4cc5bbaf19 | ||
|
|
a264c36a48 | ||
|
|
0c2ab22656 | ||
|
|
47adad5122 | ||
|
|
745f209f7e | ||
|
|
2287597712 | ||
|
|
eea8b15180 | ||
|
|
600a2b40af | ||
|
|
a7c51593e4 | ||
|
|
218876ac19 | ||
|
|
6cda67df10 | ||
|
|
897515c002 | ||
|
|
9deaf612f1 | ||
|
|
b7676d8c46 | ||
|
|
05aa2fa421 | ||
|
|
03f5c9b950 | ||
|
|
4c9c4c487a | ||
|
|
c172b9e080 | ||
|
|
5533a84dcd | ||
|
|
562bcb8571 | ||
|
|
00c07b38a4 | ||
|
|
f44bfa9682 | ||
|
|
7357a0a324 | ||
|
|
36a49966eb | ||
|
|
f818d06b43 | ||
|
|
548246c05f | ||
|
|
2bf1aa975a | ||
|
|
4be8eca3fe | ||
|
|
e17ace397c | ||
|
|
6bdabe72b9 | ||
|
|
00bfc7f889 | ||
|
|
5fcb77e591 | ||
|
|
df8de7ff51 | ||
|
|
67d7540907 | ||
|
|
83d0bad3a1 | ||
|
|
9d80a62bb1 | ||
|
|
629653425d | ||
|
|
03ce1d8641 | ||
|
|
225baeb5cb | ||
|
|
cf171d28c7 | ||
|
|
61434a9121 | ||
|
|
20590b7d35 | ||
|
|
fce7081215 | ||
|
|
83c7c8110d | ||
|
|
c4680a97a8 | ||
|
|
91a5bcf380 | ||
|
|
7e9ae458e2 | ||
|
|
4e284f5e6c | ||
|
|
75ded89790 | ||
|
|
598ce0d401 | ||
|
|
fc3058c1e2 | ||
|
|
d14ae70776 | ||
|
|
882816d609 | ||
|
|
2205e2b9a0 | ||
|
|
855fdd7921 | ||
|
|
99b1f81e89 | ||
|
|
46ad7b1b38 | ||
|
|
7e5b7a7f2a | ||
|
|
156e85a6b3 | ||
|
|
6fce02d25e | ||
|
|
4ddb86df53 | ||
|
|
3565e96f42 | ||
|
|
2c7db23022 | ||
|
|
fe51c9a9a2 | ||
|
|
5324dfa5a7 | ||
|
|
881d32e733 | ||
|
|
1f4cbb7479 | ||
|
|
b17bbdaa7d | ||
|
|
5458a1c1b7 | ||
|
|
fa98450754 | ||
|
|
7b4f2b47de | ||
|
|
400a97e7a8 | ||
|
|
a816fb5958 | ||
|
|
c7ad6ebad6 | ||
|
|
85b4a82a4b | ||
|
|
f18fa8e947 | ||
|
|
44cd185c66 | ||
|
|
890f414b5a | ||
|
|
03b1b12ef1 | ||
|
|
dae6f28f8a | ||
|
|
5aca3a2d7d | ||
|
|
7f257e258f | ||
|
|
6a9d3de0f9 | ||
|
|
05aae36813 | ||
|
|
d5d6079b67 | ||
|
|
bb4c8bf8eb | ||
|
|
3eb40db498 | ||
|
|
576f63d5e4 | ||
|
|
cda1dc82e9 | ||
|
|
2721252d6a | ||
|
|
45ac960308 | ||
|
|
47d74aa24a | ||
|
|
48aa1ad57d | ||
|
|
2eccb28dee | ||
|
|
9c3bfd920f | ||
|
|
76eb1e9e7f | ||
|
|
b7af597668 | ||
|
|
d635559a30 | ||
|
|
58dd90b7b7 | ||
|
|
ead990a734 | ||
|
|
27400fcd5b | ||
|
|
d4631e14b2 | ||
|
|
8df2cc103e | ||
|
|
8e0e9c7d3a | ||
|
|
913930b561 | ||
|
|
994c8db1f3 | ||
|
|
0c6cbb66b1 | ||
|
|
f09393d4f4 | ||
|
|
f6d963d45a | ||
|
|
39e3733be4 | ||
|
|
09659cc304 | ||
|
|
6811bdec40 | ||
|
|
6577d60733 | ||
|
|
c7db837214 | ||
|
|
03cb7233dc | ||
|
|
6682abf89d | ||
|
|
78fbf0f7ba | ||
|
|
89547332ee | ||
|
|
75539bf675 | ||
|
|
eaeb715e56 | ||
|
|
ca55cc99ed | ||
|
|
7cc4a8f5ce | ||
|
|
fa35768fc9 | ||
|
|
4d0ff0dce4 | ||
|
|
8aac6e46d4 | ||
|
|
1feac1a308 | ||
|
|
d3e42e4b3e | ||
|
|
3a1ca32ff1 | ||
|
|
ecf86d1d13 | ||
|
|
adc6170f02 | ||
|
|
02600f40d2 | ||
|
|
16ea0348a9 | ||
|
|
44162811bd | ||
|
|
57acb8db5c | ||
|
|
2bcb7d5639 | ||
|
|
a99e54330a | ||
|
|
e219772b2a | ||
|
|
144a507a2e | ||
|
|
5019c51940 | ||
|
|
da1071526f | ||
|
|
7ad314472d | ||
|
|
4f6168a982 | ||
|
|
218a872968 | ||
|
|
0043c5e1ac | ||
|
|
d0e7046a89 | ||
|
|
52ad16b920 | ||
|
|
5a4c0bff6a | ||
|
|
6205209fbb | ||
|
|
6ebf8a57d1 | ||
|
|
c02dfc4fb1 | ||
|
|
9d62e5fb6f | ||
|
|
6f13d107c4 | ||
|
|
e56b2ceebb | ||
|
|
7de244ed62 | ||
|
|
1e9147b8bb | ||
|
|
2f65fadeaa | ||
|
|
a17091b394 | ||
|
|
ed77c6cb54 | ||
|
|
bc37cc8a91 | ||
|
|
387363283c | ||
|
|
709026bf1a | ||
|
|
f2b2b86786 | ||
|
|
d0fbea76d8 | ||
|
|
8269610a5c | ||
|
|
20c88a46d9 | ||
|
|
661029f7cc | ||
|
|
850d32d60c | ||
|
|
eb881b9729 | ||
|
|
091ba473ff | ||
|
|
fca051c565 | ||
|
|
6463cda204 | ||
|
|
d004df56e3 | ||
|
|
359dd482c4 | ||
|
|
89e98240b4 | ||
|
|
1c1f2ef1ff | ||
|
|
4fa774f866 | ||
|
|
4671999ea0 | ||
|
|
0a73bbe279 | ||
|
|
8d30058a6d | ||
|
|
69151c06e4 | ||
|
|
2e3c02887e | ||
|
|
7603cef308 | ||
|
|
be370c4e19 | ||
|
|
c6dece6bd1 | ||
|
|
93a5b3f457 | ||
|
|
4242176d29 | ||
|
|
1cadbeed88 | ||
|
|
86cc011212 | ||
|
|
c0facfc28f | ||
|
|
ad52a82190 | ||
|
|
60b6ed514f | ||
|
|
ef32822b31 | ||
|
|
bb0cedd2de | ||
|
|
8175c7c085 | ||
|
|
5c2d725721 | ||
|
|
72571628da | ||
|
|
fa6130c907 | ||
|
|
8ccdd54974 | ||
|
|
6c1409b00d | ||
|
|
542a1a11b9 | ||
|
|
63ffa80c5c | ||
|
|
609342be7a | ||
|
|
52394884da | ||
|
|
af08177f79 | ||
|
|
45fdfc2d3d | ||
|
|
d18554e0e8 | ||
|
|
3c3f9ca85b | ||
|
|
005a02efeb | ||
|
|
6206ebc994 | ||
|
|
dd9f5adc2e | ||
|
|
748d805a32 | ||
|
|
4b59bf01b3 | ||
|
|
b4faa4851a | ||
|
|
f37fcc147c | ||
|
|
dc5694e544 | ||
|
|
e588f6f8c3 | ||
|
|
d227f2ad7c | ||
|
|
97c228031a | ||
|
|
ad85011d62 | ||
|
|
a70379625d | ||
|
|
7350333129 | ||
|
|
216420fdc5 | ||
|
|
c559fbbe8c | ||
|
|
71d68f975c | ||
|
|
390534497e | ||
|
|
3f0ec89f11 | ||
|
|
d3aa4f2bc7 | ||
|
|
f58f0ddb67 | ||
|
|
633e3129d4 | ||
|
|
877bdce4c8 | ||
|
|
6e1fbd2d97 | ||
|
|
36bfe62a8f | ||
|
|
b08bd0f9ab | ||
|
|
3998b47d84 | ||
|
|
d965fdb11d | ||
|
|
ddb64b3ec1 | ||
|
|
5055ec8617 | ||
|
|
8a858501f2 | ||
|
|
e1af25c8a6 | ||
|
|
6091f818da | ||
|
|
a45f9b4802 | ||
|
|
9ccf63b44a | ||
|
|
d34135ae43 | ||
|
|
a81f6f9ad1 | ||
|
|
8a80b10cc2 | ||
|
|
22b1ee132a | ||
|
|
ab7f681f15 | ||
|
|
2ac806ef08 | ||
|
|
13ec8ed03c | ||
|
|
fb77817c2d | ||
|
|
ceb8a492b1 | ||
|
|
cfc868bf4d | ||
|
|
7b4e2257d8 | ||
|
|
4ac6e5477d | ||
|
|
614ea14a7f | ||
|
|
ce45f99006 | ||
|
|
9203813a61 | ||
|
|
ba987b0574 | ||
|
|
b20f34adb7 | ||
|
|
63d0d810b1 | ||
|
|
5491400684 | ||
|
|
6a5165e9b3 | ||
|
|
9a7c4442d2 | ||
|
|
0e5363b5c3 | ||
|
|
d41bce36be | ||
|
|
1380cd811e | ||
|
|
d99bb3a87c | ||
|
|
4b9501318d | ||
|
|
e5eec04f92 | ||
|
|
f9c21efc30 | ||
|
|
ae72b71895 | ||
|
|
87e3fe725d | ||
|
|
807d9e3eef | ||
|
|
9e569b3791 | ||
|
|
024f093585 | ||
|
|
996e9e9102 | ||
|
|
d58bfb46cf | ||
|
|
eb0d7df50b | ||
|
|
547bee38c0 | ||
|
|
60614ba250 | ||
|
|
278f68ae77 | ||
|
|
b4375d6f64 | ||
|
|
9f47c72d31 | ||
|
|
de3bf03f42 | ||
|
|
59a39ac57d | ||
|
|
df9c2b193e | ||
|
|
3894311d68 | ||
|
|
35501dd4fc | ||
|
|
e2ca713658 | ||
|
|
a45de6d427 | ||
|
|
a350638526 | ||
|
|
59f9605ed9 | ||
|
|
9521bf8d4f | ||
|
|
7c1c94d39b | ||
|
|
8a74963815 | ||
|
|
3ebd8b7f45 | ||
|
|
ae8cb2e6a8 | ||
|
|
1ccb978612 | ||
|
|
7040a01cf2 | ||
|
|
6bc0e815e9 | ||
|
|
593f7e826c | ||
|
|
835fa0af13 | ||
|
|
0e3bd0c6c1 | ||
|
|
86668eb7b9 | ||
|
|
771f65c858 | ||
|
|
89d6326a83 | ||
|
|
8b81ea162f | ||
|
|
a53e6db537 | ||
|
|
62e3feeb94 | ||
|
|
a950494503 | ||
|
|
3cb310122e | ||
|
|
feace988b4 | ||
|
|
6a56f20928 | ||
|
|
80a46d14be | ||
|
|
fbcbf066cd | ||
|
|
4d30e1115f | ||
|
|
897cfb491c | ||
|
|
c2c7512431 | ||
|
|
568cf4d182 | ||
|
|
f54330f1c5 | ||
|
|
97e01d7a42 | ||
|
|
4be3e000e1 | ||
|
|
b47baa9ee1 | ||
|
|
f6c98112df | ||
|
|
94d29ab22e | ||
|
|
b0b179550a | ||
|
|
41c7ab4f9c | ||
|
|
432c7c63fe | ||
|
|
2bba1ae292 | ||
|
|
7830d518e0 | ||
|
|
571b3c4da8 | ||
|
|
5b6f8d4c3f | ||
|
|
ae57b21b98 | ||
|
|
292c3bbff8 | ||
|
|
065570ebf5 | ||
|
|
1f5dfd71d5 | ||
|
|
31b3ac4b98 | ||
|
|
7f4a383d75 | ||
|
|
de943c5f30 | ||
|
|
e34b0af251 | ||
|
|
fa7237fde7 | ||
|
|
ed530cef72 | ||
|
|
0f8b2703d1 | ||
|
|
a2176f566b | ||
|
|
bef056b084 | ||
|
|
c8c86c44f8 | ||
|
|
f917a4a34a | ||
|
|
78fd942faa | ||
|
|
a3274ac9b1 | ||
|
|
2e67d69434 | ||
|
|
c2d6e78b2a | ||
|
|
7233a11ba0 | ||
|
|
3a1360ce11 | ||
|
|
ba761044a6 | ||
|
|
d8636a2c5d | ||
|
|
9889c8f9e0 | ||
|
|
7e2e392ecc | ||
|
|
6912a67eba | ||
|
|
6abc83de83 | ||
|
|
0ca66a1469 | ||
|
|
a88be1af44 | ||
|
|
ae47fda257 | ||
|
|
6eb5411029 | ||
|
|
73d13d61a7 | ||
|
|
fdf213ef72 | ||
|
|
22fe605b1e | ||
|
|
bcc902a889 | ||
|
|
24ff2ec30c | ||
|
|
4e0c67e2a1 | ||
|
|
0cc21db654 | ||
|
|
dd5d1c00e5 | ||
|
|
cad2555c03 | ||
|
|
005d8184aa | ||
|
|
c228eddc57 | ||
|
|
ae37f8d9b6 | ||
|
|
6a8113af1d | ||
|
|
0c8cf12650 | ||
|
|
2e29a51ccf | ||
|
|
162f1d94dc | ||
|
|
a76bce1f32 | ||
|
|
be20e04c7b | ||
|
|
d9df82f31d | ||
|
|
6210333628 | ||
|
|
a552a790d3 | ||
|
|
9acb745956 | ||
|
|
875edaf96f | ||
|
|
a9afc0f3f0 | ||
|
|
3bbeaabe26 | ||
|
|
c04cbb480a | ||
|
|
2c241c294e | ||
|
|
ce851f3c28 | ||
|
|
817a6d1828 | ||
|
|
4d0735e7f6 | ||
|
|
80291930f0 | ||
|
|
cf8678b979 | ||
|
|
67722c0fb8 | ||
|
|
0b6e246c04 | ||
|
|
3992295678 | ||
|
|
da404b9acc | ||
|
|
da8db153be | ||
|
|
2c90f7324b | ||
|
|
2cdb0de1c3 | ||
|
|
66bd798e80 | ||
|
|
cf37dfb257 | ||
|
|
217f84204e | ||
|
|
fbbe0ec3db | ||
|
|
1ec34767f9 | ||
|
|
14e94a5376 | ||
|
|
08508afdb2 | ||
|
|
4220f25e01 | ||
|
|
4ff5afecc8 | ||
|
|
2eabb439d9 | ||
|
|
2bc9d5d490 | ||
|
|
9e1c142f02 | ||
|
|
1a38893b52 | ||
|
|
f28d75cf7c | ||
|
|
a3c9d0ace5 | ||
|
|
aea1799a64 | ||
|
|
ef76c4c62b | ||
|
|
210e7c5579 | ||
|
|
3fa0046542 | ||
|
|
d6754685cc | ||
|
|
bb5721700b | ||
|
|
5c4a1dcbd5 | ||
|
|
4f488dee61 | ||
|
|
0d33758104 | ||
|
|
15b5fcbaf9 | ||
|
|
0718b0d5b0 | ||
|
|
0af2ba1b7d | ||
|
|
ea2fdecb83 | ||
|
|
07eb250083 | ||
|
|
ee04717e1b | ||
|
|
d7d22c36ed | ||
|
|
36bf91f920 | ||
|
|
98e9c3b800 | ||
|
|
a7f1137db8 | ||
|
|
f86159e717 | ||
|
|
6e93223ea3 | ||
|
|
a6d677043f | ||
|
|
eb1bf198ac | ||
|
|
0a2f82a19d | ||
|
|
27d9fba785 | ||
|
|
e6a783aff8 | ||
|
|
a767c353d2 | ||
|
|
a39d3d7233 | ||
|
|
40c7ee6355 | ||
|
|
eb760aa33f | ||
|
|
262c34abac | ||
|
|
8019b1b823 | ||
|
|
7a56e83fa3 | ||
|
|
a1c38d9cb2 | ||
|
|
734cf5819a | ||
|
|
35e0b6143a | ||
|
|
e019ae4aed | ||
|
|
c700046b76 | ||
|
|
326a6b729f | ||
|
|
e2ef0c5b94 | ||
|
|
c49f68ef3e | ||
|
|
d0f66f8624 | ||
|
|
4dfa720f2d | ||
|
|
f3b8bac477 | ||
|
|
ce6abad97f | ||
|
|
807e908f78 | ||
|
|
94c75b5262 | ||
|
|
eb0dd6b6e9 | ||
|
|
1c542c3e0d | ||
|
|
d46fcb33c5 | ||
|
|
d5e0da0eb6 | ||
|
|
e744e4cd98 | ||
|
|
9a96e8c704 | ||
|
|
31a94f468e | ||
|
|
7422b9b53b | ||
|
|
161a9d6ad2 | ||
|
|
f684cc3711 | ||
|
|
8fe81c9d09 | ||
|
|
9f3acf8e28 | ||
|
|
31c9c82f6c | ||
|
|
ec3d8a034f | ||
|
|
c452294bcc | ||
|
|
d5757499bc | ||
|
|
139c8c2e78 | ||
|
|
215e33fa6c | ||
|
|
3d12b84f1d | ||
|
|
d8adc88c52 | ||
|
|
5119e49e47 | ||
|
|
cfb9f87418 |
@@ -3,26 +3,217 @@ version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
- image: circleci/node:9
|
||||
environment:
|
||||
CONTRACTS_COMMIT_HASH: '9ed05f5'
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- checkout
|
||||
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
|
||||
- restore_cache:
|
||||
key: dependency-cache-v1-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: yarn
|
||||
command: yarn
|
||||
command: yarn --frozen-lockfile
|
||||
- save_cache:
|
||||
key: dependency-cache-{{ checksum "package.json" }}
|
||||
key: dependency-cache-v1-{{ checksum "package.json" }}
|
||||
paths:
|
||||
- ~/.cache/yarn
|
||||
- ./node_modules
|
||||
- run: wget https://s3.amazonaws.com/testrpc-shapshots/${CONTRACTS_COMMIT_HASH}.zip
|
||||
- run: unzip ${CONTRACTS_COMMIT_HASH}.zip -d testrpc_snapshot
|
||||
- run: node ./node_modules/lerna/bin/lerna.js bootstrap
|
||||
- run: yarn lerna:run build
|
||||
- run: yarn build
|
||||
- save_cache:
|
||||
key: repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo
|
||||
test-installation:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn test:installation
|
||||
test-0xjs:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
background: true
|
||||
- run: yarn lerna:run test:circleci
|
||||
- run: yarn wsrun test:circleci 0x.js
|
||||
- save_cache:
|
||||
key: coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/0x.js/coverage/lcov.info
|
||||
test-contracts:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
background: true
|
||||
- run: yarn wsrun test:circleci contracts
|
||||
- save_cache:
|
||||
key: coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/contracts/coverage/lcov.info
|
||||
test-sol-compiler:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
background: true
|
||||
- run: yarn wsrun test:circleci @0xproject/sol-compiler
|
||||
- save_cache:
|
||||
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-compiler/coverage/lcov.info
|
||||
test-rest:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
background: true
|
||||
- run: yarn wsrun test:circleci --exclude contracts --exclude 0x.js --exclude @0xproject/sol-compiler --stages --exclude-missing
|
||||
- save_cache:
|
||||
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/assert/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/connect/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/dev-utils/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/json-schemas/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/subproviders/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/sol-cov/coverage/lcov.info
|
||||
- save_cache:
|
||||
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/metacoin/coverage/lcov.info
|
||||
lint:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn lerna:run lint
|
||||
prettier:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn prettier:ci
|
||||
submit-coverage:
|
||||
docker:
|
||||
- image: circleci/node:9
|
||||
working_directory: ~/repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
keys:
|
||||
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run: yarn report_coverage
|
||||
workflows:
|
||||
version: 2
|
||||
main:
|
||||
jobs:
|
||||
- build
|
||||
- test-installation:
|
||||
requires:
|
||||
- build
|
||||
- test-0xjs:
|
||||
requires:
|
||||
- build
|
||||
- test-contracts:
|
||||
requires:
|
||||
- build
|
||||
- test-sol-compiler:
|
||||
requires:
|
||||
- build
|
||||
- test-rest:
|
||||
requires:
|
||||
- build
|
||||
- prettier:
|
||||
requires:
|
||||
- build
|
||||
- lint:
|
||||
requires:
|
||||
- build
|
||||
- submit-coverage:
|
||||
requires:
|
||||
- test-0xjs
|
||||
- test-sol-compiler
|
||||
- test-rest
|
||||
- test-contracts
|
||||
|
||||
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
# EditorConfig http://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# All files
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.sol linguist-language=Solidity
|
||||
28
.gitignore
vendored
28
.gitignore
vendored
@@ -68,6 +68,30 @@ generated_docs/
|
||||
TODO.md
|
||||
|
||||
packages/website/public/bundle*
|
||||
packages/react-docs/example/public/bundle*
|
||||
|
||||
# generated binaries
|
||||
bin/
|
||||
# server cli
|
||||
packages/testnet-faucets/server/
|
||||
|
||||
# generated contract artifacts/
|
||||
packages/sol-cov/test/fixtures/artifacts/
|
||||
packages/metacoin/artifacts/
|
||||
packages/order-watcher/test/artifacts/
|
||||
packages/contract-wrappers/test/artifacts/
|
||||
|
||||
# generated contract wrappers
|
||||
packages/0x.js/src/contract_wrappers/generated/
|
||||
packages/contracts/src/contract_wrappers/generated/
|
||||
packages/contract-wrappers/src/contract_wrappers/generated/
|
||||
packages/metacoin/src/contract_wrappers
|
||||
packages/fill-scenarios/src/generated_contract_wrappers/
|
||||
packages/order-watcher/src/generated_contract_wrappers/
|
||||
packages/migrations/src/contract_wrappers
|
||||
|
||||
# solc-bin in sol-compiler
|
||||
packages/sol-compiler/solc_bin/
|
||||
|
||||
# Monorepo scripts
|
||||
packages/*/scripts/
|
||||
|
||||
ganache.log
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
.*
|
||||
tsconfig.json
|
||||
tslint.json
|
||||
webpack.config.js
|
||||
yarn.lock
|
||||
docs
|
||||
10
.prettierignore
Normal file
10
.prettierignore
Normal file
@@ -0,0 +1,10 @@
|
||||
lib
|
||||
.nyc_output
|
||||
/packages/0x.js/test/artifacts
|
||||
/packages/contracts/src/artifacts
|
||||
/packages/metacoin/artifacts
|
||||
/packages/contract-wrappers/test/artifacts
|
||||
/packages/order-watcher/test/artifacts
|
||||
/packages/migrations/artifacts/1.0.0
|
||||
package.json
|
||||
scripts/postpublish_utils.js
|
||||
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"printWidth": 120,
|
||||
"trailingComma": all,
|
||||
"singleQuote": true
|
||||
}
|
||||
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at team@0xproject.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -1,5 +1,4 @@
|
||||
0x Contribution Guide
|
||||
---------------------
|
||||
## 0x Contribution Guide
|
||||
|
||||
Thank you for your interest in contributing to 0x protocol! We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes!
|
||||
|
||||
@@ -9,9 +8,9 @@ If you'd like to contribute to 0x protocol, please fork the repo, fix, commit an
|
||||
|
||||
We encourage a “PR early” approach so create the PR as early as possible even without the fix/feature ready, so that devs and other contributors know you have picked up the issue. These early PRs should indicate an 'in progress' status by adding the '[WIP]' prefix to the PR title. Please make sure your contributions adhere to our coding guidelines:
|
||||
|
||||
* Pull requests adding features or refactoring should be opened against the `development` branch
|
||||
* Pull requests fixing bugs in the latest release version should be opened again the `master` branch
|
||||
* Write [good commit messages](https://chris.beams.io/posts/git-commit/)
|
||||
* Pull requests adding features or refactoring should be opened against the `development` branch
|
||||
* Pull requests fixing bugs in the latest release version should be opened again the `master` branch
|
||||
* Write [good commit messages](https://chris.beams.io/posts/git-commit/)
|
||||
|
||||
### Code quality
|
||||
|
||||
@@ -24,7 +23,7 @@ If the sub-package you are modifying has a `CHANGELOG.md` file, make sure to add
|
||||
|
||||
### Styleguide
|
||||
|
||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x.js/tree/development/packages/tslint-config) to keep our code style consistent.
|
||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) to keep our code style consistent.
|
||||
|
||||
To lint your code just run: `yarn lint`
|
||||
|
||||
@@ -32,10 +31,10 @@ We also use [Prettier](https://prettier.io/) to auto-format our code. Be sure to
|
||||
|
||||
If using the Atom text editor, we recommend you install the following packages:
|
||||
|
||||
* [atom-typescript](https://atom.io/packages/atom-typescript)
|
||||
* [linter-tslint](https://atom.io/packages/linter-tslint)
|
||||
* [prettier-atom](https://atom.io/packages/prettier-atom)
|
||||
* [language-ethereum](https://atom.io/packages/language-ethereum)
|
||||
* [atom-typescript](https://atom.io/packages/atom-typescript)
|
||||
* [linter-tslint](https://atom.io/packages/linter-tslint)
|
||||
* [prettier-atom](https://atom.io/packages/prettier-atom)
|
||||
* [language-ethereum](https://atom.io/packages/language-ethereum)
|
||||
|
||||
Our CI will also run TSLint and Prettier as a part of the test run when you submit your PR. Make sure that the CI tests pass for your contribution.
|
||||
|
||||
|
||||
62
ISSUE_TEMPLATE.md
Normal file
62
ISSUE_TEMPLATE.md
Normal file
@@ -0,0 +1,62 @@
|
||||
<!--- Thank you for taking the time to file an Issue -->
|
||||
|
||||
<!--- Before submitting please check to see if this issue was already reported -->
|
||||
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
<!--- If you're describing a bug, tell us what should happen -->
|
||||
|
||||
<!--- If you're suggesting a package change/improvement, tell us how it should work -->
|
||||
|
||||
<!--- If you're suggesting a contract or protocol change/improvement, visit our ZEIPs repo -->
|
||||
|
||||
## Current Behavior
|
||||
|
||||
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||
|
||||
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
|
||||
|
||||
## Possible Solution
|
||||
|
||||
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
||||
|
||||
<!--- or ideas how to implement the addition or change -->
|
||||
|
||||
## Steps to Reproduce (for bugs)
|
||||
|
||||
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
|
||||
|
||||
<!--- reproduce this bug. Include code to reproduce, if relevant -->
|
||||
|
||||
```
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
```
|
||||
|
||||
## Context
|
||||
|
||||
<!--- How has this issue affected you? What are you trying to accomplish? -->
|
||||
|
||||
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
|
||||
|
||||
## Your Environment
|
||||
|
||||
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||
|
||||
| Package | Version |
|
||||
| ------------------: | :------ |
|
||||
| `0x.js` | 0.25.0 |
|
||||
| `Exchange Contract` | v1 |
|
||||
|
||||
| Network |
|
||||
| ------- |
|
||||
| NAME |
|
||||
|
||||
<!-- For example:
|
||||
| mainnet |
|
||||
| kovan |
|
||||
| testrpc |
|
||||
-->
|
||||
@@ -1,2 +1,41 @@
|
||||
This PR:
|
||||
*
|
||||
<!--- Thank you for taking the time to submit a Pull Request -->
|
||||
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
|
||||
## Description
|
||||
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
## Motivation and Context
|
||||
|
||||
<!--- Why is this change required? What problem does it solve? -->
|
||||
|
||||
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||
|
||||
## How Has This Been Tested?
|
||||
|
||||
<!--- Please describe in detail how you tested your changes. -->
|
||||
|
||||
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||
|
||||
<!--- see how your change affects other areas of the code, etc. -->
|
||||
|
||||
## Types of changes
|
||||
|
||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||
|
||||
* [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
* [ ] New feature (non-breaking change which adds functionality)
|
||||
* [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||
|
||||
## Checklist:
|
||||
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
|
||||
* [ ] Change requires a change to the documentation.
|
||||
* [ ] Added tests to cover my changes.
|
||||
* [ ] Added new entries to the relevant CHANGELOG.jsons.
|
||||
* [ ] Labeled this PR with the 'WIP' label if it is a work in progress.
|
||||
* [ ] Labeled this PR with the labels corresponding to the changed package.
|
||||
|
||||
163
README.md
163
README.md
@@ -4,101 +4,176 @@
|
||||
|
||||
[0x][website-url] is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets. A full description of the protocol may be found in our [whitepaper][whitepaper-url].
|
||||
|
||||
This repository contains all the 0x developer tools written in TypeScript. Our hope is that these tools make it easy to build Relayers and other DApps that use the 0x protocol.
|
||||
This repository is a monorepo including the 0x protocol smart contracts and numerous developer tools. Each public sub-package is independently published to NPM.
|
||||
|
||||
[website-url]: https://0xproject.com/
|
||||
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
||||
|
||||
[](https://circleci.com/gh/0xProject/0x.js)
|
||||
[](https://coveralls.io/github/0xProject/0x.js?branch=master)
|
||||
[](https://chat.0xproject.com)
|
||||
[](https://circleci.com/gh/0xProject/0x-monorepo)
|
||||
[](https://coveralls.io/github/0xProject/0x-monorepo?branch=development)
|
||||
[](https://chat.0xproject.com)
|
||||
[](https://gitter.im/0xProject/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://greenkeeper.io/)
|
||||
|
||||
### Published Packages
|
||||
|
||||
| Package | Version | Description |
|
||||
|---------|---------|-------------|
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`@0xproject/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the standard relayer api |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
||||
| [`@0xproject/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
|
||||
| Package | Version | Description |
|
||||
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`@0xproject/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0xproject/base-contract`](/packages/base-contract) | [](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the Standard Relayer API |
|
||||
| [`@0xproject/sol-compiler`](/packages/sol-compiler) | [](https://www.npmjs.com/package/@0xproject/sol-compiler) | A thin wrapper around Solc.js that outputs artifacts, resolves imports, only re-compiles when needed, and other niceties. |
|
||||
| [`@0xproject/dev-utils`](/packages/dev-utils) | [](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | [](https://www.npmjs.com/package/@0xproject/monorepo-scripts) | Monorepo scripts |
|
||||
| [`@0xproject/react-docs`](/packages/react-docs) | [](https://www.npmjs.com/package/@0xproject/react-docs) | React documentation component for rendering TypeDoc & Doxity generated JSON |
|
||||
| [`@0xproject/react-shared`](/packages/react-shared) | [](https://www.npmjs.com/package/@0xproject/react-shared) | 0x shared react components |
|
||||
| [`@0xproject/sra-report`](/packages/sra-report) | [](https://www.npmjs.com/package/@0xproject/sra-report) | Generate reports for standard relayer API compliance |
|
||||
| [`@0xproject/sol-cov`](/packages/sol-cov) | [](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
|
||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
||||
| [`@0xproject/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||
| [`@0xproject/typescript-typings`](/packages/typescript-typings) | [](https://www.npmjs.com/package/@0xproject/typescript-typings) | Repository of types for external packages |
|
||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
|
||||
|
||||
### Private Packages
|
||||
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| [`@0xproject/contracts`](/packages/contracts) | 0x solidity smart contracts & tests |
|
||||
| [`@0xproject/kovan_faucets`](/packages/kovan-faucets) | A faucet micro-service that dispenses test ERC20 tokens or Ether |
|
||||
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | Shared monorepo scripts |
|
||||
| [`@0xproject/website`](/packages/website) | 0x website & Portal DApp |
|
||||
| Package | Description |
|
||||
| --------------------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| [`@0xproject/contracts`](/packages/contracts) | 0x solidity smart contracts & tests |
|
||||
| [`@0xproject/react-docs-example`](/packages/react-docs-example) | Example documentation site created with `@0xproject/react-docs` |
|
||||
| [`@0xproject/testnet-faucets`](/packages/testnet-faucets) | A faucet micro-service that dispenses test ERC20 tokens or Ether |
|
||||
| [`@0xproject/website`](/packages/website) | 0x website & Portal DApp |
|
||||
|
||||
## Usage
|
||||
|
||||
Dedicated documentation pages:
|
||||
- [0x.js Library](https://0xproject.com/docs/0xjs)
|
||||
- [0x Connect](https://0xproject.com/docs/connect)
|
||||
- [Smart contracts](https://0xproject.com/docs/contracts)
|
||||
- [Standard Relayer API](https://github.com/0xProject/standard-relayer-api/blob/master/README.md)
|
||||
|
||||
* [0x.js Library](https://0xproject.com/docs/0xjs)
|
||||
* [0x Connect](https://0xproject.com/docs/connect)
|
||||
* [Smart contracts](https://0xproject.com/docs/contracts)
|
||||
* [Subproviders](https://0xproject.com/docs/subproviders)
|
||||
* [Sol Compiler](https://0xproject.com/docs/sol-compiler)
|
||||
* [Web3-wrapper](https://0xproject.com/docs/web3-wrapper)
|
||||
* [JSON-schemas](https://0xproject.com/docs/json-schemas)
|
||||
* [Sol-cov](https://0xproject.com/docs/sol-cov)
|
||||
* [Standard Relayer API](https://github.com/0xProject/standard-relayer-api/blob/master/README.md)
|
||||
|
||||
Node version >= 6.12 is required.
|
||||
|
||||
Most of the packages require additional typings for external dependencies.
|
||||
You can include those by prepending @0xproject/typescript-typings package to your [`typeRoots`](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html) config.
|
||||
|
||||
```json
|
||||
"typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"],
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](./CONTRIBUTING.md) before getting started.
|
||||
#### Read our [contribution guidelines](./CONTRIBUTING.md).
|
||||
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
Build all packages
|
||||
To build all packages:
|
||||
|
||||
```bash
|
||||
yarn lerna:run build
|
||||
yarn build
|
||||
```
|
||||
|
||||
To build a specific package:
|
||||
|
||||
```bash
|
||||
PKG=@0xproject/web3-wrapper yarn build
|
||||
```
|
||||
|
||||
### Watch
|
||||
|
||||
To re-build all packages on change:
|
||||
|
||||
```bash
|
||||
yarn watch
|
||||
```
|
||||
|
||||
To watch a specific package and all it's dependent packages:
|
||||
|
||||
```bash
|
||||
PKG=[NPM_PACKAGE_NAME] yarn watch
|
||||
|
||||
e.g
|
||||
PKG=@0xproject/web3-wrapper yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
Clean all packages:
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
Clean a specific package
|
||||
|
||||
```bash
|
||||
PKG=0x.js yarn clean
|
||||
```
|
||||
|
||||
### Rebuild
|
||||
|
||||
To re-build (clean & build) all packages:
|
||||
|
||||
```bash
|
||||
yarn rebuild
|
||||
```
|
||||
|
||||
To re-build (clean & build) a specific package & it's deps:
|
||||
|
||||
```bash
|
||||
PKG=0x.js yarn rebuild
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
Lint all packages
|
||||
Lint all packages:
|
||||
|
||||
```bash
|
||||
yarn lerna:run lint
|
||||
yarn lint
|
||||
```
|
||||
|
||||
Lint a specific package:
|
||||
|
||||
```bash
|
||||
PKG=0x.js yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
Before running the tests, you will need to spin up a [TestRPC](https://www.npmjs.com/package/ethereumjs-testrpc) instance and deploy all the 0x smart contracts.
|
||||
Run all tests:
|
||||
|
||||
In a separate terminal, start TestRPC (a convenience command is provided as part of this repo)
|
||||
```bash
|
||||
yarn testrpc
|
||||
yarn test
|
||||
```
|
||||
|
||||
Then in your main terminal run
|
||||
```
|
||||
cd packages/contracts
|
||||
yarn migrate
|
||||
cd ..
|
||||
```
|
||||
Run a specific package's test:
|
||||
|
||||
And finally from the root project directory run
|
||||
```bash
|
||||
yarn lerna:run test
|
||||
PKG=@0xproject/web3-wrapper yarn test
|
||||
```
|
||||
|
||||
22
lerna.json
22
lerna.json
@@ -1,9 +1,17 @@
|
||||
{
|
||||
"lerna": "2.5.1",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "independent",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true
|
||||
"lerna": "2.5.1",
|
||||
"packages": ["packages/*"],
|
||||
"commands": {
|
||||
"publish": {
|
||||
"allowBranch": "development"
|
||||
}
|
||||
},
|
||||
"version": "independent",
|
||||
"commands": {
|
||||
"publish": {
|
||||
"ignore": ["test/**/*", "*.md", "scripts", "lib", "tslint.json", "tsconfig.json"]
|
||||
}
|
||||
},
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true
|
||||
}
|
||||
|
||||
40
package.json
40
package.json
@@ -1,24 +1,46 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "0x.js",
|
||||
"name": "0x-monorepo",
|
||||
"engines": {
|
||||
"node" : ">=6.12"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"scripts": {
|
||||
"testrpc": "testrpc -p 8545 --networkId 50 -m \"${npm_package_config_mnemonic}\"",
|
||||
"ganache": "ganache-cli -p 8545 --networkId 50 -m \"${npm_package_config_mnemonic}\"",
|
||||
"prettier": "prettier --write '**/*.{ts,tsx,json,md}' --config .prettierrc",
|
||||
"prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}' --config .prettierrc",
|
||||
"report_coverage": "lcov-result-merger 'packages/*/coverage/lcov.info' | coveralls",
|
||||
"test:installation": "node ./packages/monorepo-scripts/lib/test_installation.js",
|
||||
"run:publish": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild script:publish",
|
||||
"run:publish:dry": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild script:publish:dry",
|
||||
"script:prepublish_checks": "node ./packages/monorepo-scripts/lib/prepublish_checks.js",
|
||||
"script:publish": "node ./packages/monorepo-scripts/lib/publish.js",
|
||||
"script:publish:dry": "IS_DRY_RUN=true yarn script:publish",
|
||||
"install:all": "yarn install",
|
||||
"wsrun": "wsrun",
|
||||
"lerna:run": "lerna run",
|
||||
"lerna:rebuild": "lerna run clean; lerna run build;",
|
||||
"lerna:publish": "yarn install; lerna run clean; lerna run build; lerna publish --registry=https://registry.npmjs.org/"
|
||||
"watch": "wsrun watch $PKG --fast-exit -r --stages --done-criteria='complete|successfully'",
|
||||
"build": "wsrun build $PKG --fast-exit -r --stages",
|
||||
"build:monorepo_scripts": "PKG=@0xproject/monorepo-scripts yarn build",
|
||||
"clean": "wsrun clean $PKG --fast-exit -r --parallel",
|
||||
"rebuild": "run-s clean build",
|
||||
"test": "wsrun test $PKG --serial --exclude-missing",
|
||||
"stage_docs": "wsrun docs:stage $PKG --parallel --exclude-missing",
|
||||
"lint": "wsrun lint $PKG --parallel --exclude-missing"
|
||||
},
|
||||
"config": {
|
||||
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/utils": "^0.1.0",
|
||||
"async-child-process": "^1.1.1",
|
||||
"ethereumjs-testrpc": "6.0.3",
|
||||
"async-child-process": "1.1.1",
|
||||
"coveralls": "^3.0.0",
|
||||
"ganache-cli": "^6.1.0",
|
||||
"lcov-result-merger": "^3.0.0",
|
||||
"lerna": "^2.5.1",
|
||||
"publish-release": "0xproject/publish-release",
|
||||
"semver-sort": "^0.0.4"
|
||||
"npm-run-all": "4.1.2",
|
||||
"prettier": "1.12.1",
|
||||
"wsrun": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
13
packages/0x.js/.npmignore
Normal file
13
packages/0x.js/.npmignore
Normal file
@@ -0,0 +1,13 @@
|
||||
.*
|
||||
tsconfig.json
|
||||
webpack.config.js
|
||||
yarn-error.log
|
||||
test/
|
||||
/src/
|
||||
/_bundles/
|
||||
/contract_templates/
|
||||
/generated_docs/
|
||||
/scripts/
|
||||
/lib/src/monorepo_scripts/
|
||||
/lib/test/
|
||||
ganache.log
|
||||
1113
packages/0x.js/CHANGELOG.json
Normal file
1113
packages/0x.js/CHANGELOG.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,145 @@
|
||||
# CHANGELOG
|
||||
<!--
|
||||
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
|
||||
Edit the package's CHANGELOG.json file only.
|
||||
-->
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.38.5 - _July 9, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.38.4 - _June 19, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.38.3 - _May 29, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.38.2 - _May 29, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.38.1 - _May 29, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.38.0 - _May 22, 2018_
|
||||
|
||||
* Renamed createOrderStateWatcher to createOrderWatcherAsync since it is now async (#579)
|
||||
* Renamed ZeroExError to ContractWrappersErrors since they now lives in the @0xproject/contract-wrappers subpackage (#579)
|
||||
|
||||
## v0.37.2 - _May 5, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.37.1 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.37.0 - _May 4, 2018_
|
||||
|
||||
* Fixed expiration watcher comparator to handle orders with equal expiration times (#526)
|
||||
* Update Web3 Provider Engine to 14.0.4 (#555)
|
||||
* Add `zeroEx.getProvider()` (#559)
|
||||
* Move `ZeroExError.InvalidSignature` to `@0xproject/order-utils` `OrderError.InvalidSignature` (#559)
|
||||
|
||||
## v0.36.3 - _April 18, 2018_
|
||||
|
||||
* Move @0xproject/migrations to devDependencies
|
||||
|
||||
## v0.36.2 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.36.1 - _April 18, 2018_
|
||||
|
||||
* Internal changes and refactoring
|
||||
* Fix redundant expired order removal bug (#527)
|
||||
|
||||
## v0.36.0 - _April 11, 2018_
|
||||
|
||||
* Moved Web3.Provider to `@0xproject/types:Provider` (#501)
|
||||
* Add `zeroEx.exchange.getOrderStateAsync` to allow obtaining current OrderState for a signedOrder (#510)
|
||||
|
||||
## v0.35.0 - _April 2, 2018_
|
||||
|
||||
* Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3-wrapper' `Web3WrapperErrors.TransactionMiningTimeout` (#485)
|
||||
|
||||
## v0.34.0 - _April 2, 2018_
|
||||
|
||||
* Fix the bug causing `zeroEx.exchange.fillOrdersUpToAsync` validation to fail if there were some extra orders passed (#470)
|
||||
* Remove automatic instantiation of `zeroEx.orderStateWatcher` (#488)
|
||||
* Add `zeroEx.createOrderStateWatcher` to allow creating arbitrary number of OrderStateWatchers (#488)
|
||||
* Added `stateLayer` setting to `OrderStateWatcherConfig` so OrderStateWatcher can be set to monitor different blockchain state layers (#488)
|
||||
|
||||
## v0.33.2 - _March 17, 2018_
|
||||
|
||||
* Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452)
|
||||
* Consolidate `Order`, `SignedOrder`, and `ECSignature` into the `@0xproject/types` package (#456)
|
||||
|
||||
## v0.33.1 - _March 7, 2018_
|
||||
|
||||
* Add missing EthersJs typescript typings as dependency
|
||||
|
||||
## v0.33.0 - _March 3, 2018_
|
||||
|
||||
* Validate and lowercase all addresses in public methods (#373)
|
||||
* Improve validation to force passing contract addresses on private networks (#385)
|
||||
* Change `LogErrorContractEventArgs.errorId` type from `BigNumber` to `number` (#413)
|
||||
* Rename all public `_unsubscribeAll` methods to `unsubscribeAll` (#415)
|
||||
* Move web3 typings from devDep to dep since cannot use this package without it (#429)
|
||||
|
||||
## v0.32.2 - _February 8, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
## v0.32.1 - _February 6, 2018_
|
||||
|
||||
* Reorganized `BlockParamLiteral` export into `@0xproject/types` package (#355)
|
||||
* Now using `abi-gen` package to generate ContractEventArgs types (#371)
|
||||
|
||||
## v0.32.0 - _February 4, 2018_
|
||||
|
||||
* Add `zeroEx.etherToken.getContractAddressIfExists` (#350)
|
||||
* Fixed the bug causing order watcher to throw if there is an event with the same signature but different indexed fields (#366)
|
||||
|
||||
## v0.31.1 - _January 31, 2018_
|
||||
|
||||
* Fix the bug causing order watcher to throw if makerToken === zrx (#357)
|
||||
|
||||
## v0.31.0 - _January 29, 2018_
|
||||
|
||||
* Add the `shouldAddPersonalMessagePrefix` parameter to `signOrderHashAsync` so that the caller can decide on whether to add the personalMessage prefix before relaying the request to the signer. Parity Signer, Ledger and TestRPC add the prefix themselves, Metamask expects it to have already been added. (#349)
|
||||
|
||||
## v0.30.2 - _January 28, 2018_
|
||||
|
||||
* Add Rinkeby testnet addresses to artifacts (#337)
|
||||
* Move @0xproject/types to dependencies from devDependencies fixing missing type errors
|
||||
|
||||
## v0.30.1 - _January 23, 2018_
|
||||
|
||||
* Fix a bug allowing negative fill values (#212)
|
||||
* Fix a bug that made it impossible to pass a custom ZRX address (#341)
|
||||
|
||||
## v0.30.0 - _January 16, 2018_
|
||||
|
||||
* Add an error parameter to the order watcher callback (#312)
|
||||
* Fix a bug making it impossible to catch some errors from awaitTransactionMinedAsync (#312)
|
||||
* Fix a bug in fillOrdersUpTo validation making it impossible to fill up to if user doesn't have enough balance to fully fill all the orders (#321)
|
||||
|
||||
## v0.29.1 - _January 10, 2018_
|
||||
|
||||
* Fixed bignumber config issue #301 (#305)
|
||||
|
||||
## v0.29.0 - _December 27, 2017_
|
||||
|
||||
v0.29.0 - _December 28, 2017_
|
||||
------------------------
|
||||
* Assert baseUnit amount supplied to `toUnitAmount` is integer amount. (#287)
|
||||
* `toBaseUnitAmount` throws if amount supplied has too many decimals (#287)
|
||||
|
||||
v0.28.0 - _December 20, 2017_
|
||||
------------------------
|
||||
## v0.28.0 - _December 19, 2017_
|
||||
|
||||
* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken` (#267)
|
||||
* Removed accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry` (#267)
|
||||
* Removed `etherTokenContractAddress` from `ZeroEx` constructor arg `ZeroExConfig` (#267)
|
||||
@@ -17,12 +150,12 @@ v0.28.0 - _December 20, 2017_
|
||||
* Support `Deposit` and `Withdraw` events on etherToken (#277)
|
||||
* Improve the error message when taker is not a string (#278)
|
||||
|
||||
v0.27.1 - _November 28, 2017_
|
||||
------------------------
|
||||
## v0.27.1 - _November 27, 2017_
|
||||
|
||||
* Export `TransactionOpts` type
|
||||
|
||||
v0.27.0 - _November 28, 2017_
|
||||
------------------------
|
||||
## v0.27.0 - _November 27, 2017_
|
||||
|
||||
* Make `ZeroExConfig` required parameter of `ZeroEx` constructor (#233)
|
||||
* Add a required property `networkId` to `ZeroExConfig` (#233)
|
||||
* Make all `getContractAddress` functions, `zeroEx.exchange.subscribe`, `zeroEx.exchange.getZRXTokenAddress` sync (#233)
|
||||
@@ -33,150 +166,150 @@ v0.27.0 - _November 28, 2017_
|
||||
* All transaction sending methods now call `estimateGas` if no gas amount was supplied (#235)
|
||||
* Modify order validation methods to validate against the `latest` block, not against the `pending` block (#236)
|
||||
|
||||
v0.26.0 - _November 21, 2017_
|
||||
------------------------
|
||||
## v0.26.0 - _November 20, 2017_
|
||||
|
||||
* Add post-formatter for logs converting `blockNumber`, `logIndex`, `transactionIndex` from hexes to numbers (#231)
|
||||
* Remove support for Async callback types when used in Subscribe functions (#222)
|
||||
* In OrderWatcher subscribe to ZRX Token Transfer and Approval events when maker token is different (#225)
|
||||
|
||||
v0.25.1 - _November 13, 2017_
|
||||
------------------------
|
||||
## v0.25.1 - _November 12, 2017_
|
||||
|
||||
* Standardise on Cancelled over Canceled (#217)
|
||||
* Add missing `DecodedLogEvent` type to exported types (#205)
|
||||
* Normalized the transactionReceipt status to be `null|0|1`, 1 meaning transaction execution successful, 0 unsuccessful and `null` if it is a pre-byzantinium transaction. (#200)
|
||||
|
||||
v0.23.0 - _November 12, 2017_
|
||||
------------------------
|
||||
## v0.23.0 - _November 11, 2017_
|
||||
|
||||
* Fixed unhandled promise rejection error in subscribe methods (#209)
|
||||
* Subscribe callbacks now receive an error object as their first argument
|
||||
|
||||
v0.22.6 - _November 10, 2017_
|
||||
------------------------
|
||||
## v0.22.6 - _November 9, 2017_
|
||||
|
||||
* Add a timeout parameter to transaction awaiting (#206)
|
||||
|
||||
v0.22.5 - _November 7, 2017_
|
||||
------------------------
|
||||
## v0.22.5 - _November 6, 2017_
|
||||
|
||||
* Re-publish v0.22.4 to fix publishing issue
|
||||
|
||||
v0.22.4 - _October 25, 2017_
|
||||
------------------------
|
||||
## v0.22.4 - _October 24, 2017_
|
||||
|
||||
* Upgraded bignumber.js to a new version that ships with native typings
|
||||
|
||||
v0.22.3 - _October 25, 2017_
|
||||
------------------------
|
||||
## v0.22.3 - _October 24, 2017_
|
||||
|
||||
* Fixed an issue with new version of testrpc and unlimited proxy allowance (#199)
|
||||
|
||||
v0.22.2 - _October 24, 2017_
|
||||
------------------------
|
||||
## v0.22.2 - _October 23, 2017_
|
||||
|
||||
* Fixed rounding of maker fill amount and incorrect validation of partial fees (#197)
|
||||
|
||||
v0.22.0 - _October 16, 2017_
|
||||
------------------------
|
||||
## v0.22.0 - _October 15, 2017_
|
||||
|
||||
* Started using `OrderFillRequest` interface instead of `OrderFillOrKillRequest` interface for `zeroEx.exchange.batchFillOrKill` (#187)
|
||||
* Removed `OrderFillOrKillRequest` (#187)
|
||||
|
||||
v0.21.4 - _October 13, 2017_
|
||||
------------------------
|
||||
## v0.21.4 - _October 12, 2017_
|
||||
|
||||
* Made 0x.js more type-safe by making `getLogsAsync` and `subscribe/subscribeAsync` generics parametrized with arg type (#194)
|
||||
|
||||
v0.21.3 - _October 12, 2017_
|
||||
------------------------
|
||||
## v0.21.3 - _October 11, 2017_
|
||||
|
||||
* Fixed a bug causing order fills to throw `INSUFFICIENT_TAKER_ALLOWANCE` (#193)
|
||||
|
||||
v0.21.2 - _October 11, 2017_
|
||||
------------------------
|
||||
## v0.21.2 - _October 10, 2017_
|
||||
|
||||
* Exported `ContractEventArg` as a public type (#190)
|
||||
|
||||
v0.21.1 - _October 11, 2017_
|
||||
------------------------
|
||||
## v0.21.1 - _October 10, 2017_
|
||||
|
||||
* Fixed a bug in subscriptions (#189)
|
||||
|
||||
v0.21.0 - _October 10, 2017_
|
||||
------------------------
|
||||
## v0.21.0 - _October 9, 2017_
|
||||
|
||||
* Complete rewrite of subscription logic (#182)
|
||||
* Subscriptions no longer return historical logs. If you want them - use `getLogsAsync`
|
||||
* Subscriptions now use [ethereumjs-blockstream](https://github.com/ethereumjs/ethereumjs-blockstream) under the hood
|
||||
* Subscriptions correctly handle block re-orgs (forks)
|
||||
* Subscriptions correctly backfill logs (connection problems)
|
||||
* They no longer setup filters on the underlying nodes, so you can use them with infura without a filter Subprovider
|
||||
* Removed `ContractEventEmitter` and added `LogEvent`
|
||||
* Renamed `zeroEx.token.subscribeAsync` to `zeroEx.token.subscribe`
|
||||
* Added `zeroEx.token.unsubscribe` and `zeroEx.exchange.unsubscribe`
|
||||
* Renamed `zeroEx.exchange.stopWatchingAllEventsAsync` to `zeroEx.exhange.unsubscribeAll`
|
||||
* Renamed `zeroEx.token.stopWatchingAllEventsAsync` to `zeroEx.token.unsubscribeAll`
|
||||
* Subscriptions no longer return historical logs. If you want them - use `getLogsAsync`
|
||||
* Subscriptions now use [ethereumjs-blockstream](https://github.com/ethereumjs/ethereumjs-blockstream) under the hood
|
||||
* Subscriptions correctly handle block re-orgs (forks)
|
||||
* Subscriptions correctly backfill logs (connection problems)
|
||||
* They no longer setup filters on the underlying nodes, so you can use them with infura without a filter Subprovider
|
||||
* Removed `ContractEventEmitter` and added `LogEvent`
|
||||
* Renamed `zeroEx.token.subscribeAsync` to `zeroEx.token.subscribe`
|
||||
* Added `zeroEx.token.unsubscribe` and `zeroEx.exchange.unsubscribe`
|
||||
* Renamed `zeroEx.exchange.stopWatchingAllEventsAsync` to `zeroEx.exhange.unsubscribeAll`
|
||||
* Renamed `zeroEx.token.stopWatchingAllEventsAsync` to `zeroEx.token.unsubscribeAll`
|
||||
* Fixed the batch fills validation by emulating all balance & proxy allowance changes (#185)
|
||||
|
||||
v0.20.0 - _October 5, 2017_
|
||||
------------------------
|
||||
## v0.20.0 - _October 4, 2017_
|
||||
|
||||
* Add `zeroEx.token.getLogsAsync` (#178)
|
||||
* Add `zeroEx.exchange.getLogsAsync` (#178)
|
||||
* Fixed fees validation when one of the tokens transferred is ZRX (#181)
|
||||
|
||||
v0.19.0 - _September 29, 2017_
|
||||
------------------------
|
||||
## v0.19.0 - _September 28, 2017_
|
||||
|
||||
* Made order validation optional (#172)
|
||||
* Added Ropsten testnet support (#173)
|
||||
* Fixed a bug causing awaitTransactionMinedAsync to DDos backend nodes (#175)
|
||||
|
||||
v0.18.0 - _September 26, 2017_
|
||||
------------------------
|
||||
## v0.18.0 - _September 25, 2017_
|
||||
|
||||
* Added `zeroEx.exchange.validateOrderFillableOrThrowAsync` to simplify orderbook pruning (#170)
|
||||
|
||||
v0.17.0 - _September 26, 2017_
|
||||
------------------------
|
||||
## v0.17.0 - _September 25, 2017_
|
||||
|
||||
* Made `zeroEx.exchange.getZRXTokenAddressAsync` public (#171)
|
||||
|
||||
v0.16.0 - _September 20, 2017_
|
||||
------------------------
|
||||
## v0.16.0 - _September 19, 2017_
|
||||
|
||||
* Added the ability to specify custom contract addresses to be used with 0x.js (#165)
|
||||
* ZeroExConfig.exchangeContractAddress
|
||||
* ZeroExConfig.tokenRegistryContractAddress
|
||||
* ZeroExConfig.etherTokenContractAddress
|
||||
* ZeroExConfig.exchangeContractAddress
|
||||
* ZeroExConfig.tokenRegistryContractAddress
|
||||
* ZeroExConfig.etherTokenContractAddress
|
||||
* Added `zeroEx.tokenRegistry.getContractAddressAsync` (#165)
|
||||
|
||||
v0.15.0 - _September 8, 2017_
|
||||
------------------------
|
||||
## v0.15.0 - _September 7, 2017_
|
||||
|
||||
* Added the ability to specify a historical `blockNumber` at which to query the blockchain's state when calling a token or exchange method (#161)
|
||||
|
||||
v0.14.2 - _September 7, 2017_
|
||||
------------------------
|
||||
## v0.14.2 - _September 6, 2017_
|
||||
|
||||
* Fixed an issue with bignumber.js types not found (#160)
|
||||
|
||||
v0.14.1 - _September 7, 2017_
|
||||
------------------------
|
||||
## v0.14.1 - _September 6, 2017_
|
||||
|
||||
* Fixed an issue with Artifact type not found (#159)
|
||||
|
||||
v0.14.0 - _September 6, 2017_
|
||||
------------------------
|
||||
## v0.14.0 - _September 5, 2017_
|
||||
|
||||
* Added `zeroEx.exchange.throwLogErrorsAsErrors` method to public interface (#157)
|
||||
* Fixed an issue with overlapping async intervals in `zeroEx.awaitTransactionMinedAsync` (#157)
|
||||
* Fixed an issue with log decoder returning `BigNumber`s as `strings` (#157)
|
||||
|
||||
v0.13.0 - _September 6, 2017_
|
||||
------------------------
|
||||
## v0.13.0 - _September 5, 2017_
|
||||
|
||||
* Made all the functions submitting transactions to the network to immediately return transaction hash (#151)
|
||||
* Added `zeroEx.awaitTransactionMinedAsync` (#151)
|
||||
* Added `TransactionReceiptWithDecodedLogs`, `LogWithDecodedArgs`, `DecodedLogArgs` to public types (#151)
|
||||
* Added signature validation to `validateFillOrderThrowIfInvalidAsync` (#152)
|
||||
|
||||
v0.12.1 - _September 2, 2017_
|
||||
------------------------
|
||||
## v0.12.1 - _September 1, 2017_
|
||||
|
||||
* Added the support for web3@1.x.x provider (#142)
|
||||
* Added the optional `zeroExConfig` parameter to the constructor of `ZeroEx` (#139)
|
||||
* Added the ability to specify `gasPrice` when instantiating `ZeroEx` (#139)
|
||||
|
||||
v0.11.0 - _August 24, 2017_
|
||||
------------------------
|
||||
## v0.11.0 - _August 23, 2017_
|
||||
|
||||
* Added `zeroEx.token.setUnlimitedProxyAllowanceAsync` (#137)
|
||||
* Added `zeroEx.token.setUnlimitedAllowanceAsync` (#137)
|
||||
* Added `zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS` (#137)
|
||||
|
||||
v0.10.4 - _Aug 24, 2017_
|
||||
------------------------
|
||||
## v0.10.4 - _August 23, 2017_
|
||||
|
||||
* Fixed a bug where checksummed addresses were being pulled from artifacts and not lower-cased. (#135)
|
||||
|
||||
v0.10.1 - _Aug 24, 2017_
|
||||
------------------------
|
||||
## v0.10.1 - _August 23, 2017_
|
||||
|
||||
* Added `zeroEx.exchange.validateFillOrderThrowIfInvalidAsync` (#128)
|
||||
* Added `zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync` (#128)
|
||||
* Added `zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync` (#128)
|
||||
@@ -190,21 +323,21 @@ v0.10.1 - _Aug 24, 2017_
|
||||
* Added clear error message when checksummed address is passed to a public method (#124)
|
||||
* Fixes the description of `shouldThrowOnInsufficientBalanceOrAllowance` in docs (#127)
|
||||
|
||||
v0.9.3 - _Aug 22, 2017_
|
||||
------------------------
|
||||
## v0.9.3 - _August 21, 2017_
|
||||
|
||||
* Update contract artifacts to include latest Kovan and Mainnet deploys (#118)
|
||||
|
||||
v0.9.2 - _Aug 21, 2017_
|
||||
------------------------
|
||||
## v0.9.2 - _August 20, 2017_
|
||||
|
||||
* *This version was unpublished because of a publishing issue.*
|
||||
* Update contract artifacts to include latest Kovan and Mainnet deploys (#118)
|
||||
|
||||
v0.9.1 - _Aug. 16, 2017_
|
||||
------------------------
|
||||
## v0.9.1 - _August 15, 2017_
|
||||
|
||||
* Fixed the bug causing `zeroEx.token.getBalanceAsync()` to fail if no addresses available (#120)
|
||||
|
||||
v0.9.0 - _Jul. 26, 2017_
|
||||
------------------------
|
||||
## v0.9.0 - _July 25, 2017_
|
||||
|
||||
* Migrated to the new version of smart contracts (#101)
|
||||
* Removed the ability to call methods on multiple authorized Exchange smart contracts (#106)
|
||||
* Made `zeroEx.getOrderHashHex` a static method (#107)
|
||||
@@ -214,48 +347,48 @@ v0.9.0 - _Jul. 26, 2017_
|
||||
* Updated to typescript v2.4 (#104)
|
||||
* Fixed an issue with incorrect balance/allowance validation when ZRX is one of the tokens traded (#109)
|
||||
|
||||
v0.8.0 - _Jul. 4, 2017_
|
||||
------------------------
|
||||
## v0.8.0 - _July 3, 2017_
|
||||
|
||||
* Added the ability to call methods on different authorized versions of the Exchange smart contract (#82)
|
||||
* Updated contract artifacts to reflect latest changes to the smart contracts (0xproject/contracts#59)
|
||||
* Added `zeroEx.proxy.isAuthorizedAsync` and `zeroEx.proxy.getAuthorizedAddressesAsync` (#89)
|
||||
* Added `zeroEx.token.subscribeAsync` (#90)
|
||||
* Made contract invalidation functions private (#90)
|
||||
* `zeroEx.token.invalidateContractInstancesAsync`
|
||||
* `zeroEx.exchange.invalidateContractInstancesAsync`
|
||||
* `zeroEx.proxy.invalidateContractInstance`
|
||||
* `zeroEx.tokenRegistry.invalidateContractInstance`
|
||||
* `zeroEx.token.invalidateContractInstancesAsync`
|
||||
* `zeroEx.exchange.invalidateContractInstancesAsync`
|
||||
* `zeroEx.proxy.invalidateContractInstance`
|
||||
* `zeroEx.tokenRegistry.invalidateContractInstance`
|
||||
* Fixed the bug where `zeroEx.setProviderAsync` didn't invalidate etherToken contract's instance
|
||||
|
||||
v0.7.1 - _Jun. 26, 2017_
|
||||
------------------------
|
||||
## v0.7.1 - _June 25, 2017_
|
||||
|
||||
* Added the ability to convert Ether to wrapped Ether tokens and back via `zeroEx.etherToken.depostAsync` and `zeroEx.etherToken.withdrawAsync` (#81)
|
||||
|
||||
v0.7.0 - _Jun. 22, 2017_
|
||||
------------------------
|
||||
## v0.7.0 - _June 21, 2017_
|
||||
|
||||
* Added Kovan smart contract artifacts (#78)
|
||||
* Started returning fillAmount from `fillOrderAsync` and `fillUpToAsync` (#72)
|
||||
* Started returning cancelledAmount from `cancelOrderAsync` (#72)
|
||||
* Renamed type `LogCancelArgs` to `LogCancelContractEventArgs` and `LogFillArgs` to `LogFillContractEventArgs`
|
||||
|
||||
v0.6.2 - _Jun. 21, 2017_
|
||||
------------------------
|
||||
## v0.6.2 - _June 20, 2017_
|
||||
|
||||
* Reduced bundle size
|
||||
* Improved documentation
|
||||
|
||||
v0.6.1 - _Jun. 19, 2017_
|
||||
------------------------
|
||||
## v0.6.1 - _June 18, 2017_
|
||||
|
||||
* Improved documentation
|
||||
|
||||
v0.6.0 - _Jun. 19, 2017_
|
||||
------------------------
|
||||
## v0.6.0 - _June 18, 2017_
|
||||
|
||||
* Made `ZeroEx` class accept `Web3Provider` instance instead of `Web3` instance
|
||||
* Added types for contract event arguments
|
||||
|
||||
v0.5.2 - _Jun. 15, 2017_
|
||||
------------------------
|
||||
## v0.5.2 - _June 14, 2017_
|
||||
|
||||
* Fixed the bug in `postpublish` script that caused that only unminified UMD bundle was uploaded to release page
|
||||
|
||||
v0.5.1 - _Jun. 15, 2017_
|
||||
------------------------
|
||||
## v0.5.1 - _June 14, 2017_
|
||||
|
||||
* Added `postpublish` script to publish to Github Releases with assets.
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
0x.js
|
||||
-----
|
||||
## 0x.js
|
||||
|
||||
A TypeScript/Javascript library for interacting with the 0x protocol.
|
||||
|
||||
### Read the [Documentation](https://0xproject.com/docs/0x.js).
|
||||
|
||||
## Installation
|
||||
|
||||
0x.js ships as both a [UMD](https://github.com/umdjs/umd) module and a [CommonJS](https://en.wikipedia.org/wiki/CommonJS) package.
|
||||
|
||||
#### CommonJS *(recommended)*:
|
||||
#### CommonJS _(recommended)_:
|
||||
|
||||
**Install**
|
||||
|
||||
@@ -16,14 +19,22 @@ npm install 0x.js --save
|
||||
**Import**
|
||||
|
||||
```javascript
|
||||
import {ZeroEx} from '0x.js';
|
||||
import { ZeroEx } from '0x.js';
|
||||
```
|
||||
|
||||
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
|
||||
|
||||
```json
|
||||
"compilerOptions": {
|
||||
"typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"],
|
||||
}
|
||||
```
|
||||
|
||||
#### UMD:
|
||||
|
||||
**Install**
|
||||
|
||||
Download the UMD module from our [releases page](https://github.com/0xProject/0x.js/releases) and add it to your project.
|
||||
Download the UMD module from our [releases page](https://github.com/0xProject/0x-monorepo/releases) and add it to your project.
|
||||
|
||||
**Import**
|
||||
|
||||
@@ -31,10 +42,54 @@ Download the UMD module from our [releases page](https://github.com/0xProject/0x
|
||||
<script type="text/javascript" src="0x.js"></script>
|
||||
```
|
||||
|
||||
## Documentation
|
||||
## Contributing
|
||||
|
||||
Extensive documentation of 0x.js can be found on [our website][docs-url].
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of 0x protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
[website-url]: https://0xproject.com/
|
||||
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
||||
[docs-url]: https://0xproject.com/docs/0xjs
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
PKG=0x.js yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=0x.js yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* This file is auto-generated using abi-gen. Don't edit directly.
|
||||
* Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates.
|
||||
*/
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import {TxData, TxDataPayable} from '@0xproject/types';
|
||||
import {classUtils, promisify} from '@0xproject/utils';
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {BaseContract} from './base_contract';
|
||||
|
||||
export class {{contractName}}Contract extends BaseContract {
|
||||
{{#each methods}}
|
||||
{{#this.constant}}
|
||||
{{> call contractName=../contractName}}
|
||||
{{/this.constant}}
|
||||
{{^this.constant}}
|
||||
{{> tx contractName=../contractName}}
|
||||
{{/this.constant}}
|
||||
{{/each}}
|
||||
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
|
||||
super(web3ContractInstance, defaults);
|
||||
classUtils.bindAll(this, ['web3ContractInstance', 'defaults']);
|
||||
}
|
||||
} // tslint:disable:max-file-line-count
|
||||
@@ -1,15 +0,0 @@
|
||||
public {{this.name}} = {
|
||||
async callAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
defaultBlock?: Web3.BlockParam,
|
||||
): Promise<{{> return_type outputs=outputs}}> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const result = await promisify<{{> return_type outputs=outputs}}>(
|
||||
self.web3ContractInstance.{{this.name}}.call,
|
||||
self.web3ContractInstance,
|
||||
)(
|
||||
{{> params inputs=inputs}}
|
||||
);
|
||||
return result;
|
||||
},
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
{{#singleReturnValue}}
|
||||
{{#returnType outputs.0.type}}{{/returnType}}
|
||||
{{/singleReturnValue}}
|
||||
{{^singleReturnValue}}
|
||||
[{{#each outputs}}{{#returnType type}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||
{{/singleReturnValue}}
|
||||
@@ -1,51 +0,0 @@
|
||||
public {{this.name}} = {
|
||||
async sendTransactionAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
{{#this.payable}}
|
||||
txData: TxDataPayable = {},
|
||||
{{/this.payable}}
|
||||
{{^this.payable}}
|
||||
txData: TxData = {},
|
||||
{{/this.payable}}
|
||||
): Promise<string> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const txDataWithDefaults = await self.applyDefaultsToTxDataAsync(
|
||||
txData,
|
||||
self.{{this.name}}.estimateGasAsync.bind(
|
||||
self,
|
||||
{{> params inputs=inputs}}
|
||||
),
|
||||
);
|
||||
const txHash = await promisify<string>(
|
||||
self.web3ContractInstance.{{this.name}}, self.web3ContractInstance,
|
||||
)(
|
||||
{{> params inputs=inputs}}
|
||||
txDataWithDefaults,
|
||||
);
|
||||
return txHash;
|
||||
},
|
||||
async estimateGasAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
txData: TxData = {},
|
||||
): Promise<number> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const txDataWithDefaults = await self.applyDefaultsToTxDataAsync(
|
||||
txData,
|
||||
);
|
||||
const gas = await promisify<number>(
|
||||
self.web3ContractInstance.{{this.name}}.estimateGas, self.web3ContractInstance,
|
||||
)(
|
||||
{{> params inputs=inputs}}
|
||||
txDataWithDefaults,
|
||||
);
|
||||
return gas;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
{{> typed_params inputs=inputs}}
|
||||
txData: TxData = {},
|
||||
): string {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const abiEncodedTransactionData = self.web3ContractInstance.{{this.name}}.getData();
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
{{#each inputs}}
|
||||
{{name}}: {{#parameterType type}}{{/parameterType}},
|
||||
{{/each}}
|
||||
0
packages/0x.js/coverage/.gitkeep
Normal file
0
packages/0x.js/coverage/.gitkeep
Normal file
@@ -1,104 +1,116 @@
|
||||
{
|
||||
"name": "0x.js",
|
||||
"version": "0.28.0",
|
||||
"description": "A javascript library for interacting with the 0x protocol",
|
||||
"keywords": [
|
||||
"0x.js",
|
||||
"0xproject",
|
||||
"ethereum",
|
||||
"tokens",
|
||||
"exchange"
|
||||
],
|
||||
"main": "lib/src/index.js",
|
||||
"types": "lib/src/index.d.ts",
|
||||
"scripts": {
|
||||
"prebuild": "run-s clean generate_contract_wrappers",
|
||||
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
|
||||
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json",
|
||||
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abiGlob 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --templates contract_templates --output src/contract_wrappers/generated",
|
||||
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
||||
"test:circleci": "run-s test:coverage report_test_coverage && if [ $CIRCLE_BRANCH = \"development\" ]; then yarn test:umd; fi",
|
||||
"test": "run-s clean test:commonjs",
|
||||
"test:umd": "./scripts/test_umd.sh",
|
||||
"test:coverage": "nyc npm run test --all",
|
||||
"report_test_coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||
"update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../0x.js/src/artifacts; done;",
|
||||
"clean": "shx rm -rf _bundles lib test_temp",
|
||||
"build:umd:dev": "webpack",
|
||||
"build:umd:prod": "NODE_ENV=production webpack",
|
||||
"build:commonjs": "tsc && copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts;",
|
||||
"test:commonjs": "run-s build:commonjs run_mocha",
|
||||
"pretest:umd": "run-s clean build:umd:dev build:commonjs",
|
||||
"substitute_umd_bundle": "shx mv _bundles/* lib/src",
|
||||
"run_mocha": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit"
|
||||
},
|
||||
"config": {
|
||||
"artifacts": "TokenTransferProxy Exchange TokenRegistry Token EtherToken"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x.js"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/abi-gen": "^0.0.3",
|
||||
"@0xproject/dev-utils": "^0.0.2",
|
||||
"@0xproject/tslint-config": "^0.3.0",
|
||||
"@0xproject/types": "^0.1.1",
|
||||
"@types/bintrees": "^1.0.2",
|
||||
"@types/jsonschema": "^1.1.1",
|
||||
"@types/lodash": "^4.14.86",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/node": "^8.0.53",
|
||||
"@types/sinon": "^2.2.2",
|
||||
"@types/uuid": "^3.4.2",
|
||||
"awesome-typescript-loader": "^3.1.3",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-as-promised-typescript-typings": "^0.0.3",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"chai-typescript-typings": "^0.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"coveralls": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"mocha": "^4.0.1",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"opn-cli": "^3.1.0",
|
||||
"request": "^2.81.0",
|
||||
"request-promise-native": "^1.0.4",
|
||||
"shx": "^0.2.2",
|
||||
"sinon": "^4.0.0",
|
||||
"source-map-support": "^0.5.0",
|
||||
"truffle-hdwallet-provider": "^0.0.3",
|
||||
"tslint": "5.8.0",
|
||||
"typedoc": "~0.8.0",
|
||||
"typescript": "~2.6.1",
|
||||
"web3-provider-engine": "^13.0.1",
|
||||
"web3-typescript-typings": "^0.7.2",
|
||||
"webpack": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^0.0.8",
|
||||
"@0xproject/json-schemas": "^0.7.0",
|
||||
"@0xproject/utils": "^0.1.1",
|
||||
"@0xproject/web3-wrapper": "^0.1.1",
|
||||
"bignumber.js": "~4.1.0",
|
||||
"bintrees": "^1.0.2",
|
||||
"bn.js": "^4.11.8",
|
||||
"compare-versions": "^3.0.1",
|
||||
"ethereumjs-abi": "^0.6.4",
|
||||
"ethereumjs-blockstream": "^2.0.6",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"find-versions": "^2.0.0",
|
||||
"js-sha3": "^0.6.1",
|
||||
"lodash": "^4.17.4",
|
||||
"uuid": "^3.1.0",
|
||||
"web3": "^0.20.0"
|
||||
}
|
||||
"name": "0x.js",
|
||||
"version": "0.38.5",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "A javascript library for interacting with the 0x protocol",
|
||||
"keywords": [
|
||||
"0x.js",
|
||||
"0xproject",
|
||||
"ethereum",
|
||||
"tokens",
|
||||
"exchange"
|
||||
],
|
||||
"main": "lib/src/index.js",
|
||||
"types": "lib/src/index.d.ts",
|
||||
"scripts": {
|
||||
"watch": "tsc -w",
|
||||
"prebuild": "run-s clean generate_contract_wrappers",
|
||||
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
||||
"generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
|
||||
"lint": "tslint --project .",
|
||||
"test:circleci": "run-s test:coverage",
|
||||
"test": "run-s clean test:commonjs",
|
||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||
"clean": "shx rm -rf _bundles lib test_temp scripts src/contract_wrappers/generated",
|
||||
"build:umd:prod": "NODE_ENV=production webpack",
|
||||
"build:commonjs": "tsc && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
||||
"test:commonjs": "run-s build:commonjs run_mocha",
|
||||
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
|
||||
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
|
||||
"docs:stage": "node scripts/stage_docs.js",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
|
||||
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
|
||||
},
|
||||
"config": {
|
||||
"compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry",
|
||||
"postpublish": {
|
||||
"assets": [
|
||||
"packages/0x.js/_bundles/index.js",
|
||||
"packages/0x.js/_bundles/index.min.js"
|
||||
],
|
||||
"docPublishConfigs": {
|
||||
"extraFileIncludes": [
|
||||
"../types/src/index.ts",
|
||||
"../contract-wrappers/src/types.ts",
|
||||
"../contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts",
|
||||
"../contract-wrappers/src/contract_wrappers/exchange_wrapper.ts",
|
||||
"../contract-wrappers/src/contract_wrappers/token_registry_wrapper.ts",
|
||||
"../contract-wrappers/src/contract_wrappers/token_transfer_proxy_wrapper.ts",
|
||||
"../contract-wrappers/src/contract_wrappers/token_wrapper.ts",
|
||||
"../order-watcher/src/order_watcher/order_watcher.ts",
|
||||
"./src/contract_wrappers/generated/ether_token.ts",
|
||||
"./src/contract_wrappers/generated/token.ts",
|
||||
"./src/contract_wrappers/generated/exchange.ts"
|
||||
],
|
||||
"s3BucketPath": "s3://doc-jsons/0x.js/",
|
||||
"s3StagingBucketPath": "s3://staging-doc-jsons/0x.js/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@0xproject/abi-gen": "^0.3.3",
|
||||
"@0xproject/dev-utils": "^0.4.5",
|
||||
"@0xproject/migrations": "^0.0.9",
|
||||
"@0xproject/monorepo-scripts": "^0.2.2",
|
||||
"@0xproject/tslint-config": "^0.4.21",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "2.2.48",
|
||||
"@types/node": "9.6.0",
|
||||
"@types/sinon": "2.3.7",
|
||||
"awesome-typescript-loader": "3.5.0",
|
||||
"chai": "4.1.2",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"chai-bignumber": "2.0.1",
|
||||
"copyfiles": "1.2.0",
|
||||
"dirty-chai": "2.0.1",
|
||||
"json-loader": "0.5.7",
|
||||
"make-promises-safe": "1.1.0",
|
||||
"mocha": "4.1.0",
|
||||
"npm-run-all": "4.1.2",
|
||||
"nyc": "11.6.0",
|
||||
"opn-cli": "3.1.0",
|
||||
"prettier": "1.12.1",
|
||||
"shx": "0.2.2",
|
||||
"sinon": "4.4.9",
|
||||
"source-map-support": "0.5.4",
|
||||
"tslint": "5.8.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.7.1",
|
||||
"webpack": "3.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^0.2.13",
|
||||
"@0xproject/base-contract": "^0.3.5",
|
||||
"@0xproject/contract-wrappers": "^0.1.0",
|
||||
"@0xproject/order-utils": "^0.0.8",
|
||||
"@0xproject/order-watcher": "^0.0.7",
|
||||
"@0xproject/sol-compiler": "^0.5.3",
|
||||
"@0xproject/types": "^0.8.2",
|
||||
"@0xproject/typescript-typings": "^0.4.2",
|
||||
"@0xproject/utils": "^0.7.2",
|
||||
"@0xproject/web3-wrapper": "^0.7.2",
|
||||
"ethers": "3.0.22",
|
||||
"lodash": "4.17.10"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
const execAsync = require('async-child-process').execAsync;
|
||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
|
||||
const packageJSON = require('../package.json');
|
||||
|
||||
const cwd = __dirname + '/..';
|
||||
const subPackageName = packageJSON.name;
|
||||
const S3BucketPath = 's3://0xjs-docs-jsons/';
|
||||
|
||||
let tag;
|
||||
let version;
|
||||
postpublish_utils.getLatestTagAndVersionAsync(subPackageName)
|
||||
.then(function(result) {
|
||||
tag = result.tag;
|
||||
version = result.version;
|
||||
const releaseName = postpublish_utils.getReleaseName(subPackageName, version);
|
||||
const assets = [
|
||||
__dirname + '/../_bundles/index.js',
|
||||
__dirname + '/../_bundles/index.min.js',
|
||||
];
|
||||
return postpublish_utils.publishReleaseNotes(tag, releaseName, assets);
|
||||
})
|
||||
.then(function(release) {
|
||||
console.log('POSTPUBLISH: Release successful, generating docs...');
|
||||
const jsonFilePath = __dirname + '/../' + postpublish_utils.generatedDocsDirectoryName + '/index.json';
|
||||
return execAsync(
|
||||
'JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_DIR=' + __dirname + '/.. yarn docs:json',
|
||||
{
|
||||
cwd,
|
||||
}
|
||||
);
|
||||
})
|
||||
.then(function(result) {
|
||||
if (result.stderr !== '') {
|
||||
throw new Error(result.stderr);
|
||||
}
|
||||
const fileName = 'v' + version + '.json';
|
||||
console.log('POSTPUBLISH: Doc generation successful, uploading docs... as ', fileName);
|
||||
const s3Url = S3BucketPath + fileName;
|
||||
return execAsync('S3_URL=' + s3Url + ' yarn upload_docs_json', {
|
||||
cwd,
|
||||
});
|
||||
}).catch (function(err) {
|
||||
throw err;
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# This script runs umd tests and cleans up after them while preserving the `return_code` for CI
|
||||
# UMD tests should only be run after building the commonjs because they reuse some of the commonjs build artifacts
|
||||
run-s substitute_umd_bundle run_mocha
|
||||
return_code=$?
|
||||
exit $return_code
|
||||
@@ -1,36 +1,27 @@
|
||||
import {schemas, SchemaValidator} from '@0xproject/json-schemas';
|
||||
import {bigNumberConfigs, intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import { assert } from '@0xproject/assert';
|
||||
import {
|
||||
ContractWrappers,
|
||||
ContractWrappersConfig,
|
||||
EtherTokenWrapper,
|
||||
ExchangeWrapper,
|
||||
TokenRegistryWrapper,
|
||||
TokenTransferProxyWrapper,
|
||||
TokenWrapper,
|
||||
} from '@0xproject/contract-wrappers';
|
||||
import {
|
||||
generatePseudoRandomSalt,
|
||||
getOrderHashHex,
|
||||
isValidOrderHash,
|
||||
isValidSignature,
|
||||
signOrderHashAsync,
|
||||
} from '@0xproject/order-utils';
|
||||
import { OrderWatcher, OrderWatcherConfig } from '@0xproject/order-watcher';
|
||||
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from './artifacts';
|
||||
import {EtherTokenWrapper} from './contract_wrappers/ether_token_wrapper';
|
||||
import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper';
|
||||
import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper';
|
||||
import {TokenTransferProxyWrapper} from './contract_wrappers/token_transfer_proxy_wrapper';
|
||||
import {TokenWrapper} from './contract_wrappers/token_wrapper';
|
||||
import {OrderStateWatcher} from './order_watcher/order_state_watcher';
|
||||
import {zeroExConfigSchema} from './schemas/zero_ex_config_schema';
|
||||
import {
|
||||
ECSignature,
|
||||
Order,
|
||||
SignedOrder,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
Web3Provider,
|
||||
ZeroExConfig,
|
||||
ZeroExError,
|
||||
} from './types';
|
||||
import {AbiDecoder} from './utils/abi_decoder';
|
||||
import {assert} from './utils/assert';
|
||||
import {constants} from './utils/constants';
|
||||
import {decorators} from './utils/decorators';
|
||||
import {signatureUtils} from './utils/signature_utils';
|
||||
import {utils} from './utils/utils';
|
||||
|
||||
// Customize our BigNumber instances
|
||||
bigNumberConfigs.configure();
|
||||
import { constants } from './utils/constants';
|
||||
|
||||
/**
|
||||
* The ZeroEx class is the single entry-point into the 0x.js library. It contains all of the library's functionality
|
||||
@@ -43,7 +34,6 @@ export class ZeroEx {
|
||||
* this constant for your convenience.
|
||||
*/
|
||||
public static NULL_ADDRESS = constants.NULL_ADDRESS;
|
||||
|
||||
/**
|
||||
* An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract.
|
||||
*/
|
||||
@@ -67,13 +57,16 @@ export class ZeroEx {
|
||||
* tokenTransferProxy smart contract.
|
||||
*/
|
||||
public proxy: TokenTransferProxyWrapper;
|
||||
private _contractWrappers: ContractWrappers;
|
||||
/**
|
||||
* An instance of the OrderStateWatcher class containing methods for watching a set of orders for relevant
|
||||
* blockchain state changes.
|
||||
* Generates a pseudo-random 256-bit salt.
|
||||
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
|
||||
* and will not collide with other outstanding orders that are identical in all other parameters.
|
||||
* @return A pseudo-random 256-bit number that can be used as a salt.
|
||||
*/
|
||||
public orderStateWatcher: OrderStateWatcher;
|
||||
private _web3Wrapper: Web3Wrapper;
|
||||
private _abiDecoder: AbiDecoder;
|
||||
public static generatePseudoRandomSalt(): BigNumber {
|
||||
return generatePseudoRandomSalt();
|
||||
}
|
||||
/**
|
||||
* Verifies that the elliptic curve signature `signature` was generated
|
||||
* by signing `data` with the private key corresponding to the `signerAddress` address.
|
||||
@@ -83,26 +76,15 @@ export class ZeroEx {
|
||||
* @return Whether the signature is valid for the supplied signerAddress and data.
|
||||
*/
|
||||
public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
||||
assert.isHexString('data', data);
|
||||
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
|
||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||
|
||||
const isValidSignature = signatureUtils.isValidSignature(data, signature, signerAddress);
|
||||
return isValidSignature;
|
||||
return isValidSignature(data, signature, signerAddress);
|
||||
}
|
||||
/**
|
||||
* Generates a pseudo-random 256-bit salt.
|
||||
* The salt can be included in an 0x order, ensuring that the order generates a unique orderHash
|
||||
* and will not collide with other outstanding orders that are identical in all other parameters.
|
||||
* @return A pseudo-random 256-bit number that can be used as a salt.
|
||||
* Computes the orderHash for a supplied order.
|
||||
* @param order An object that conforms to the Order or SignedOrder interface definitions.
|
||||
* @return The resulting orderHash from hashing the supplied order.
|
||||
*/
|
||||
public static generatePseudoRandomSalt(): BigNumber {
|
||||
// BigNumber.random returns a pseudo-random number between 0 & 1 with a passed in number of decimal places.
|
||||
// Source: https://mikemcl.github.io/bignumber.js/#random
|
||||
const randomNumber = BigNumber.random(constants.MAX_DIGITS_IN_UNSIGNED_256_INT);
|
||||
const factor = new BigNumber(10).pow(constants.MAX_DIGITS_IN_UNSIGNED_256_INT - 1);
|
||||
const salt = randomNumber.times(factor).round();
|
||||
return salt;
|
||||
public static getOrderHashHex(order: Order | SignedOrder): string {
|
||||
return getOrderHashHex(order);
|
||||
}
|
||||
/**
|
||||
* Checks if the supplied hex encoded order hash is valid.
|
||||
@@ -112,12 +94,7 @@ export class ZeroEx {
|
||||
* @return Whether the supplied orderHash has the expected format.
|
||||
*/
|
||||
public static isValidOrderHash(orderHash: string): boolean {
|
||||
// Since this method can be called to check if any arbitrary string conforms to an orderHash's
|
||||
// format, we only assert that we were indeed passed a string.
|
||||
assert.isString('orderHash', orderHash);
|
||||
const schemaValidator = new SchemaValidator();
|
||||
const isValidOrderHash = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid;
|
||||
return isValidOrderHash;
|
||||
return isValidOrderHash(orderHash);
|
||||
}
|
||||
/**
|
||||
* A unit amount is defined as the amount of a token above the specified decimal places (integer part).
|
||||
@@ -130,10 +107,8 @@ export class ZeroEx {
|
||||
public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber {
|
||||
assert.isValidBaseUnitAmount('amount', amount);
|
||||
assert.isNumber('decimals', decimals);
|
||||
|
||||
const aUnit = new BigNumber(10).pow(decimals);
|
||||
const unit = amount.div(aUnit);
|
||||
return unit;
|
||||
const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
|
||||
return unitAmount;
|
||||
}
|
||||
/**
|
||||
* A baseUnit is defined as the smallest denomination of a token. An amount expressed in baseUnits
|
||||
@@ -146,70 +121,25 @@ export class ZeroEx {
|
||||
public static toBaseUnitAmount(amount: BigNumber, decimals: number): BigNumber {
|
||||
assert.isBigNumber('amount', amount);
|
||||
assert.isNumber('decimals', decimals);
|
||||
|
||||
const unit = new BigNumber(10).pow(decimals);
|
||||
const baseUnitAmount = amount.times(unit);
|
||||
const hasDecimals = baseUnitAmount.decimalPlaces() !== 0;
|
||||
if (hasDecimals) {
|
||||
throw new Error(`Invalid unit amount: ${amount.toString()} - Too many decimal places`);
|
||||
}
|
||||
const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, decimals);
|
||||
return baseUnitAmount;
|
||||
}
|
||||
/**
|
||||
* Computes the orderHash for a supplied order.
|
||||
* @param order An object that conforms to the Order or SignedOrder interface definitions.
|
||||
* @return The resulting orderHash from hashing the supplied order.
|
||||
*/
|
||||
@decorators.syncZeroExErrorHandler
|
||||
public static getOrderHashHex(order: Order|SignedOrder): string {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
const orderHashHex = utils.getOrderHashHex(order);
|
||||
return orderHashHex;
|
||||
}
|
||||
/**
|
||||
* Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library.
|
||||
* @param provider The Web3.js Provider instance you would like the 0x.js library to use for interacting with
|
||||
* @param provider The Provider instance you would like the 0x.js library to use for interacting with
|
||||
* the Ethereum network.
|
||||
* @param config The configuration object. Look up the type for the description.
|
||||
* @return An instance of the 0x.js ZeroEx class.
|
||||
*/
|
||||
constructor(provider: Web3Provider, config: ZeroExConfig) {
|
||||
constructor(provider: Provider, config: ContractWrappersConfig) {
|
||||
assert.isWeb3Provider('provider', provider);
|
||||
assert.doesConformToSchema('config', config, zeroExConfigSchema);
|
||||
const artifactJSONs = _.values(artifacts);
|
||||
const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
|
||||
this._abiDecoder = new AbiDecoder(abiArrays);
|
||||
const defaults = {
|
||||
gasPrice: config.gasPrice,
|
||||
};
|
||||
this._web3Wrapper = new Web3Wrapper(provider, defaults);
|
||||
this.proxy = new TokenTransferProxyWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
config.tokenTransferProxyContractAddress,
|
||||
);
|
||||
this.token = new TokenWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
this._abiDecoder,
|
||||
this.proxy,
|
||||
);
|
||||
this.exchange = new ExchangeWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
this._abiDecoder,
|
||||
this.token,
|
||||
config.exchangeContractAddress,
|
||||
);
|
||||
this.tokenRegistry = new TokenRegistryWrapper(
|
||||
this._web3Wrapper, config.networkId, config.tokenRegistryContractAddress,
|
||||
);
|
||||
this.etherToken = new EtherTokenWrapper(
|
||||
this._web3Wrapper, config.networkId, this._abiDecoder, this.token,
|
||||
);
|
||||
this.orderStateWatcher = new OrderStateWatcher(
|
||||
this._web3Wrapper, this._abiDecoder, this.token, this.exchange, config.orderWatcherConfig,
|
||||
);
|
||||
this._contractWrappers = new ContractWrappers(provider, config);
|
||||
|
||||
this.proxy = this._contractWrappers.proxy;
|
||||
this.token = this._contractWrappers.token;
|
||||
this.exchange = this._contractWrappers.exchange;
|
||||
this.tokenRegistry = this._contractWrappers.tokenRegistry;
|
||||
this.etherToken = this._contractWrappers.etherToken;
|
||||
}
|
||||
/**
|
||||
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
|
||||
@@ -217,20 +147,24 @@ export class ZeroEx {
|
||||
* @param provider The Web3Provider you would like the 0x.js library to use from now on.
|
||||
* @param networkId The id of the network your provider is connected to
|
||||
*/
|
||||
public setProvider(provider: Web3Provider, networkId: number): void {
|
||||
this._web3Wrapper.setProvider(provider, networkId);
|
||||
(this.exchange as any)._invalidateContractInstances();
|
||||
(this.tokenRegistry as any)._invalidateContractInstance();
|
||||
(this.token as any)._invalidateContractInstances();
|
||||
(this.proxy as any)._invalidateContractInstance();
|
||||
(this.etherToken as any)._invalidateContractInstance();
|
||||
public setProvider(provider: Provider, networkId: number): void {
|
||||
this._contractWrappers.setProvider(provider, networkId);
|
||||
}
|
||||
/**
|
||||
* Get the provider instance currently used by 0x.js
|
||||
* @return Web3 provider instance
|
||||
*/
|
||||
public getProvider(): Provider {
|
||||
return this._contractWrappers.getProvider();
|
||||
}
|
||||
/**
|
||||
* Get user Ethereum addresses available through the supplied web3 provider available for sending transactions.
|
||||
* @return An array of available user Ethereum addresses.
|
||||
*/
|
||||
public async getAvailableAddressesAsync(): Promise<string[]> {
|
||||
const availableAddresses = await this._web3Wrapper.getAvailableAddressesAsync();
|
||||
// Hack: Get Web3Wrapper from ContractWrappers
|
||||
const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
|
||||
const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
return availableAddresses;
|
||||
}
|
||||
/**
|
||||
@@ -238,50 +172,24 @@ export class ZeroEx {
|
||||
* This method currently supports TestRPC, Geth and Parity above and below V1.6.6
|
||||
* @param orderHash Hex encoded orderHash to sign.
|
||||
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
|
||||
* must be available via the Web3.Provider supplied to 0x.js.
|
||||
* must be available via the Provider supplied to 0x.js.
|
||||
* @param shouldAddPersonalMessagePrefix Some signers add the personal message prefix `\x19Ethereum Signed Message`
|
||||
* themselves (e.g Parity Signer, Ledger, TestRPC) and others expect it to already be done by the client
|
||||
* (e.g Metamask). Depending on which signer this request is going to, decide on whether to add the prefix
|
||||
* before sending the request.
|
||||
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
|
||||
*/
|
||||
public async signOrderHashAsync(orderHash: string, signerAddress: string): Promise<ECSignature> {
|
||||
assert.isHexString('orderHash', orderHash);
|
||||
await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper);
|
||||
|
||||
let msgHashHex;
|
||||
const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
|
||||
const isParityNode = utils.isParityNode(nodeVersion);
|
||||
const isTestRpc = utils.isTestRpc(nodeVersion);
|
||||
if (isParityNode || isTestRpc) {
|
||||
// Parity and TestRpc nodes add the personalMessage prefix itself
|
||||
msgHashHex = orderHash;
|
||||
} else {
|
||||
const orderHashBuff = ethUtil.toBuffer(orderHash);
|
||||
const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff);
|
||||
msgHashHex = ethUtil.bufferToHex(msgHashBuff);
|
||||
}
|
||||
|
||||
const signature = await this._web3Wrapper.signTransactionAsync(signerAddress, msgHashHex);
|
||||
|
||||
// HACK: There is no consensus on whether the signatureHex string should be formatted as
|
||||
// v + r + s OR r + s + v, and different clients (even different versions of the same client)
|
||||
// return the signature params in different orders. In order to support all client implementations,
|
||||
// we parse the signature in both ways, and evaluate if either one is a valid signature.
|
||||
const validVParamValues = [27, 28];
|
||||
const ecSignatureVRS = signatureUtils.parseSignatureHexAsVRS(signature);
|
||||
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
|
||||
const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, signerAddress);
|
||||
if (isValidVRSSignature) {
|
||||
return ecSignatureVRS;
|
||||
}
|
||||
}
|
||||
|
||||
const ecSignatureRSV = signatureUtils.parseSignatureHexAsRSV(signature);
|
||||
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
|
||||
const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, signerAddress);
|
||||
if (isValidRSVSignature) {
|
||||
return ecSignatureRSV;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(ZeroExError.InvalidSignature);
|
||||
public async signOrderHashAsync(
|
||||
orderHash: string,
|
||||
signerAddress: string,
|
||||
shouldAddPersonalMessagePrefix: boolean,
|
||||
): Promise<ECSignature> {
|
||||
return signOrderHashAsync(
|
||||
this._contractWrappers.getProvider(),
|
||||
orderHash,
|
||||
signerAddress,
|
||||
shouldAddPersonalMessagePrefix,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Waits for a transaction to be mined and returns the transaction receipt.
|
||||
@@ -291,46 +199,31 @@ export class ZeroEx {
|
||||
* @return Transaction receipt with decoded log args.
|
||||
*/
|
||||
public async awaitTransactionMinedAsync(
|
||||
txHash: string, pollingIntervalMs = 1000, timeoutMs?: number): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
let timeoutExceeded = false;
|
||||
if (timeoutMs) {
|
||||
setTimeout(() => timeoutExceeded = true, timeoutMs);
|
||||
}
|
||||
|
||||
const txReceiptPromise = new Promise(
|
||||
(resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => {
|
||||
const intervalId = intervalUtils.setAsyncExcludingInterval(async () => {
|
||||
if (timeoutExceeded) {
|
||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
||||
return reject(ZeroExError.TransactionMiningTimeout);
|
||||
}
|
||||
|
||||
const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
|
||||
if (!_.isNull(transactionReceipt)) {
|
||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
||||
const logsWithDecodedArgs = _.map(
|
||||
transactionReceipt.logs,
|
||||
this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder),
|
||||
);
|
||||
const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
|
||||
...transactionReceipt,
|
||||
logs: logsWithDecodedArgs,
|
||||
};
|
||||
resolve(transactionReceiptWithDecodedLogArgs);
|
||||
}
|
||||
}, pollingIntervalMs);
|
||||
});
|
||||
|
||||
return txReceiptPromise;
|
||||
txHash: string,
|
||||
pollingIntervalMs: number = 1000,
|
||||
timeoutMs?: number,
|
||||
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||
// Hack: Get Web3Wrapper from ContractWrappers
|
||||
const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
|
||||
const transactionReceiptWithDecodedLogs = await web3Wrapper.awaitTransactionMinedAsync(
|
||||
txHash,
|
||||
pollingIntervalMs,
|
||||
timeoutMs,
|
||||
);
|
||||
return transactionReceiptWithDecodedLogs;
|
||||
}
|
||||
/*
|
||||
* HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from
|
||||
* an `ExchangeWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders, creating a dependency cycle.
|
||||
* In order to break this - we create this function here and pass it as a parameter to the `TokenWrapper`
|
||||
* and `ProxyWrapper`.
|
||||
/**
|
||||
* Instantiates and returns a new OrderWatcher instance.
|
||||
* Defaults to watching the pending state.
|
||||
* @param config The configuration object. Look up the type for the description.
|
||||
* @return An instance of the 0x.js OrderWatcher class.
|
||||
*/
|
||||
private async _getTokenTransferProxyAddressAsync(): Promise<string> {
|
||||
const tokenTransferProxyAddress = await (this.exchange as any)._getTokenTransferProxyAddressAsync();
|
||||
return tokenTransferProxyAddress;
|
||||
public async createOrderWatcherAsync(config?: OrderWatcherConfig): Promise<OrderWatcher> {
|
||||
// Hack: Get Web3Wrapper from ContractWrappers
|
||||
const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
|
||||
const networkId = await web3Wrapper.getNetworkIdAsync();
|
||||
const provider = this._contractWrappers.getProvider();
|
||||
const orderWatcher = new OrderWatcher(provider, networkId, config);
|
||||
return orderWatcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import * as DummyTokenArtifact from './artifacts/DummyToken.json';
|
||||
import * as EtherTokenArtifact from './artifacts/EtherToken.json';
|
||||
import * as ExchangeArtifact from './artifacts/Exchange.json';
|
||||
import * as TokenArtifact from './artifacts/Token.json';
|
||||
import * as TokenRegistryArtifact from './artifacts/TokenRegistry.json';
|
||||
import * as TokenTransferProxyArtifact from './artifacts/TokenTransferProxy.json';
|
||||
import * as ZRXArtifact from './artifacts/ZRX.json';
|
||||
import {Artifact} from './types';
|
||||
|
||||
export const artifacts = {
|
||||
ZRXArtifact: ZRXArtifact as any as Artifact,
|
||||
DummyTokenArtifact: DummyTokenArtifact as any as Artifact,
|
||||
TokenArtifact: TokenArtifact as any as Artifact,
|
||||
ExchangeArtifact: ExchangeArtifact as any as Artifact,
|
||||
EtherTokenArtifact: EtherTokenArtifact as any as Artifact,
|
||||
TokenRegistryArtifact: TokenRegistryArtifact as any as Artifact,
|
||||
TokenTransferProxyArtifact: TokenTransferProxyArtifact as any as Artifact,
|
||||
};
|
||||
@@ -1,284 +0,0 @@
|
||||
{
|
||||
"contract_name": "EtherToken",
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [],
|
||||
"name": "deposit",
|
||||
"outputs": [],
|
||||
"payable": true,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"payable": true,
|
||||
"type": "fallback"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Deposit",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Withdrawal",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
|
||||
},
|
||||
"3": {
|
||||
"address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,607 +0,0 @@
|
||||
{
|
||||
"contract_name": "Exchange",
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "numerator",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "denominator",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "target",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "isRoundingError",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "filled",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "cancelled",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5][]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6][]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8[]"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32[]"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "fillOrdersUpTo",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6]"
|
||||
},
|
||||
{
|
||||
"name": "cancelTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "cancelOrder",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "ZRX_TOKEN_CONTRACT",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5][]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6][]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmounts",
|
||||
"type": "uint256[]"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8[]"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32[]"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "batchFillOrKillOrders",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "fillOrKillOrder",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "getUnavailableTakerTokenAmount",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "signer",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "hash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "isValidSignature",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "numerator",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "denominator",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "target",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "getPartialAmount",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "TOKEN_TRANSFER_PROXY_CONTRACT",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5][]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6][]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmounts",
|
||||
"type": "uint256[]"
|
||||
},
|
||||
{
|
||||
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8[]"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32[]"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "batchFillOrders",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5][]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6][]"
|
||||
},
|
||||
{
|
||||
"name": "cancelTakerTokenAmounts",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"name": "batchCancelOrders",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "fillOrder",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "filledTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6]"
|
||||
}
|
||||
],
|
||||
"name": "getOrderHash",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "EXTERNAL_QUERY_GAS_LIMIT",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "VERSION",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_zrxToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_tokenTransferProxy",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "maker",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "taker",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "feeRecipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "makerToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "takerToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "filledMakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "filledTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "paidMakerFee",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "paidTakerFee",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "tokens",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "LogFill",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "maker",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "feeRecipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "makerToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "takerToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "cancelledMakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "cancelledTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "tokens",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "LogCancel",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "errorId",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "LogError",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0x12459c951127e0c374ff9105dda097662a027093"
|
||||
},
|
||||
"3": {
|
||||
"address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
{
|
||||
"contract_name": "Token",
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "supply",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "balance",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "remaining",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,544 +0,0 @@
|
||||
{
|
||||
"contract_name": "TokenRegistry",
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_index",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "removeToken",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_name",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "getTokenAddressByName",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_symbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "getTokenAddressBySymbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "setTokenSwarmHash",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getTokenMetaData",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "_symbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "_decimals",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "_ipfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "_swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "addToken",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_name",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "setTokenName",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "tokens",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "symbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "decimals",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "ipfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "tokenAddresses",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_name",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "getTokenByName",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getTokenAddresses",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_ipfsHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "setTokenIpfsHash",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_symbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "getTokenBySymbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_symbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "setTokenSymbol",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "symbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "decimals",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "ipfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "LogAddToken",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "symbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "decimals",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "ipfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "LogRemoveToken",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "oldName",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "newName",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "LogTokenNameChange",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "oldSymbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "newSymbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "LogTokenSymbolChange",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "oldIpfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "newIpfsHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "LogTokenIpfsHashChange",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "oldSwarmHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "newSwarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "LogTokenSwarmHashChange",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0x926a74c5c36adf004c87399e65f75628b0f98d2c"
|
||||
},
|
||||
"3": {
|
||||
"address": "0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed"
|
||||
},
|
||||
"42": {
|
||||
"address": "0xf18e504561f4347bea557f3d4558f559dddbae7f"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
{
|
||||
"contract_name": "TokenTransferProxy",
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "addAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "authorities",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "removeAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "authorized",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getAuthorizedAddresses",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "caller",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "LogAuthorizedAddressAdded",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "caller",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "LogAuthorizedAddressRemoved",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0x8da0d80f5007ef1e431dd2127178d224e32c2ef4"
|
||||
},
|
||||
"3": {
|
||||
"address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"contract_name": "ZRX",
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
|
||||
},
|
||||
"3": {
|
||||
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"contract_name": "DummyToken",
|
||||
"abi":
|
||||
[
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
287
packages/0x.js/src/compact_artifacts/EtherToken.json
Normal file
287
packages/0x.js/src/compact_artifacts/EtherToken.json
Normal file
@@ -0,0 +1,287 @@
|
||||
{
|
||||
"contract_name": "EtherToken",
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [],
|
||||
"name": "deposit",
|
||||
"outputs": [],
|
||||
"payable": true,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"payable": true,
|
||||
"type": "fallback"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Deposit",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Withdrawal",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
|
||||
},
|
||||
"3": {
|
||||
"address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
|
||||
},
|
||||
"4": {
|
||||
"address": "0xc778417e063141139fce010982780140aa0cd5ab"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
|
||||
}
|
||||
}
|
||||
}
|
||||
610
packages/0x.js/src/compact_artifacts/Exchange.json
Normal file
610
packages/0x.js/src/compact_artifacts/Exchange.json
Normal file
@@ -0,0 +1,610 @@
|
||||
{
|
||||
"contract_name": "Exchange",
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "numerator",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "denominator",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "target",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "isRoundingError",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "filled",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "cancelled",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5][]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6][]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8[]"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32[]"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "fillOrdersUpTo",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6]"
|
||||
},
|
||||
{
|
||||
"name": "cancelTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "cancelOrder",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "ZRX_TOKEN_CONTRACT",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5][]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6][]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmounts",
|
||||
"type": "uint256[]"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8[]"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32[]"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "batchFillOrKillOrders",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "fillOrKillOrder",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "getUnavailableTakerTokenAmount",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "signer",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "hash",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "isValidSignature",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "numerator",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "denominator",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "target",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "getPartialAmount",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "TOKEN_TRANSFER_PROXY_CONTRACT",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5][]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6][]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmounts",
|
||||
"type": "uint256[]"
|
||||
},
|
||||
{
|
||||
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8[]"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32[]"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "batchFillOrders",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5][]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6][]"
|
||||
},
|
||||
{
|
||||
"name": "cancelTakerTokenAmounts",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"name": "batchCancelOrders",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6]"
|
||||
},
|
||||
{
|
||||
"name": "fillTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"name": "v",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "r",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"name": "s",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "fillOrder",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "filledTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "orderAddresses",
|
||||
"type": "address[5]"
|
||||
},
|
||||
{
|
||||
"name": "orderValues",
|
||||
"type": "uint256[6]"
|
||||
}
|
||||
],
|
||||
"name": "getOrderHash",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "EXTERNAL_QUERY_GAS_LIMIT",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "VERSION",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_zrxToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_tokenTransferProxy",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "maker",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "taker",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "feeRecipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "makerToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "takerToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "filledMakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "filledTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "paidMakerFee",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "paidTakerFee",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "tokens",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "LogFill",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "maker",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "feeRecipient",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "makerToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "takerToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "cancelledMakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "cancelledTakerTokenAmount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "tokens",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "LogCancel",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "errorId",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "LogError",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0x12459c951127e0c374ff9105dda097662a027093"
|
||||
},
|
||||
"3": {
|
||||
"address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac"
|
||||
},
|
||||
"4": {
|
||||
"address": "0x1d16ef40fac01cec8adac2ac49427b9384192c05"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
|
||||
}
|
||||
}
|
||||
}
|
||||
172
packages/0x.js/src/compact_artifacts/Token.json
Normal file
172
packages/0x.js/src/compact_artifacts/Token.json
Normal file
@@ -0,0 +1,172 @@
|
||||
{
|
||||
"contract_name": "Token",
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "supply",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "balance",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "success",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "remaining",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
||||
}
|
||||
547
packages/0x.js/src/compact_artifacts/TokenRegistry.json
Normal file
547
packages/0x.js/src/compact_artifacts/TokenRegistry.json
Normal file
@@ -0,0 +1,547 @@
|
||||
{
|
||||
"contract_name": "TokenRegistry",
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_index",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "removeToken",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_name",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "getTokenAddressByName",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_symbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "getTokenAddressBySymbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "setTokenSwarmHash",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getTokenMetaData",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "_symbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "_decimals",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "_ipfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "_swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "addToken",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_name",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "setTokenName",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "tokens",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "symbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "decimals",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "ipfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "tokenAddresses",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_name",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "getTokenByName",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getTokenAddresses",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_ipfsHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "setTokenIpfsHash",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_symbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "getTokenBySymbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_symbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "setTokenSymbol",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "symbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "decimals",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "ipfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "LogAddToken",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "symbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "decimals",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "ipfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "swarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "LogRemoveToken",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "oldName",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "newName",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "LogTokenNameChange",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "oldSymbol",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "newSymbol",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "LogTokenSymbolChange",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "oldIpfsHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "newIpfsHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "LogTokenIpfsHashChange",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "oldSwarmHash",
|
||||
"type": "bytes"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "newSwarmHash",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "LogTokenSwarmHashChange",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0x926a74c5c36adf004c87399e65f75628b0f98d2c"
|
||||
},
|
||||
"3": {
|
||||
"address": "0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed"
|
||||
},
|
||||
"4": {
|
||||
"address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
|
||||
},
|
||||
"42": {
|
||||
"address": "0xf18e504561f4347bea557f3d4558f559dddbae7f"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082"
|
||||
}
|
||||
}
|
||||
}
|
||||
187
packages/0x.js/src/compact_artifacts/TokenTransferProxy.json
Normal file
187
packages/0x.js/src/compact_artifacts/TokenTransferProxy.json
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"contract_name": "TokenTransferProxy",
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "addAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "authorities",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "removeAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "authorized",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getAuthorizedAddresses",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "caller",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "LogAuthorizedAddressAdded",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "caller",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "LogAuthorizedAddressRemoved",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0x8da0d80f5007ef1e431dd2127178d224e32c2ef4"
|
||||
},
|
||||
"3": {
|
||||
"address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
|
||||
},
|
||||
"4": {
|
||||
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48"
|
||||
}
|
||||
}
|
||||
}
|
||||
20
packages/0x.js/src/compact_artifacts/ZRX.json
Normal file
20
packages/0x.js/src/compact_artifacts/ZRX.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"contract_name": "ZRX",
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
|
||||
},
|
||||
"3": {
|
||||
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
|
||||
},
|
||||
"4": {
|
||||
"address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
dummy_token.ts
|
||||
ether_token.ts
|
||||
exchange.ts
|
||||
token_registry.ts
|
||||
token_transfer_proxy.ts
|
||||
token.ts
|
||||
@@ -1,33 +0,0 @@
|
||||
import {TxData, TxDataPayable} from '@0xproject/types';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export class BaseContract {
|
||||
protected web3ContractInstance: Web3.ContractInstance;
|
||||
protected defaults: Partial<TxData>;
|
||||
protected async applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>(
|
||||
txData: T,
|
||||
estimateGasAsync?: (txData: T) => Promise<number>,
|
||||
): Promise<TxData> {
|
||||
// Gas amount sourced with the following priorities:
|
||||
// 1. Optional param passed in to public method call
|
||||
// 2. Global config passed in at library instantiation
|
||||
// 3. Gas estimate calculation + safety margin
|
||||
const removeUndefinedProperties = _.pickBy;
|
||||
const txDataWithDefaults = {
|
||||
...removeUndefinedProperties(this.defaults),
|
||||
...removeUndefinedProperties(txData as any),
|
||||
// HACK: TS can't prove that T is spreadable.
|
||||
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
|
||||
};
|
||||
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
|
||||
const estimatedGas = await estimateGasAsync(txData);
|
||||
txDataWithDefaults.gas = estimatedGas;
|
||||
}
|
||||
return txDataWithDefaults;
|
||||
}
|
||||
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
|
||||
this.web3ContractInstance = web3ContractInstance;
|
||||
this.defaults = defaults;
|
||||
}
|
||||
}
|
||||
68
packages/0x.js/src/globals.d.ts
vendored
68
packages/0x.js/src/globals.d.ts
vendored
@@ -1,74 +1,6 @@
|
||||
/// <reference types='chai-typescript-typings' />
|
||||
/// <reference types='chai-as-promised-typescript-typings' />
|
||||
declare module 'web3_beta';
|
||||
declare module 'chai-bignumber';
|
||||
declare module 'dirty-chai';
|
||||
declare module 'request-promise-native';
|
||||
declare module 'web3-provider-engine';
|
||||
declare module 'web3-provider-engine/subproviders/rpc';
|
||||
|
||||
// HACK: In order to merge the bignumber declaration added by chai-bignumber to the chai Assertion
|
||||
// interface we must use `namespace` as the Chai definitelyTyped definition does. Since we otherwise
|
||||
// disallow `namespace`, we disable tslint for the following.
|
||||
/* tslint:disable */
|
||||
declare namespace Chai {
|
||||
interface Assertion {
|
||||
bignumber: Assertion;
|
||||
// HACK: In order to comply with chai-as-promised we make eventually a `PromisedAssertion` not an `Assertion`
|
||||
eventually: PromisedAssertion;
|
||||
}
|
||||
}
|
||||
/* tslint:enable */
|
||||
|
||||
declare module '*.json' {
|
||||
const json: any;
|
||||
/* tslint:disable */
|
||||
export default json;
|
||||
/* tslint:enable */
|
||||
}
|
||||
|
||||
// find-version declarations
|
||||
declare function findVersions(version: string): string[];
|
||||
declare module 'find-versions' {
|
||||
export = findVersions;
|
||||
}
|
||||
|
||||
// compare-version declarations
|
||||
declare function compareVersions(firstVersion: string, secondVersion: string): number;
|
||||
declare module 'compare-versions' {
|
||||
export = compareVersions;
|
||||
}
|
||||
|
||||
declare module 'ethereumjs-abi' {
|
||||
const soliditySHA3: (argTypes: string[], args: any[]) => Buffer;
|
||||
}
|
||||
|
||||
// truffle-hdwallet-provider declarations
|
||||
declare module 'truffle-hdwallet-provider' {
|
||||
import * as Web3 from 'web3';
|
||||
class HDWalletProvider implements Web3.Provider {
|
||||
constructor(mnemonic: string, rpcUrl: string);
|
||||
public sendAsync(
|
||||
payload: Web3.JSONRPCRequestPayload,
|
||||
callback: (err: Error, result: Web3.JSONRPCResponsePayload) => void,
|
||||
): void;
|
||||
}
|
||||
export = HDWalletProvider;
|
||||
}
|
||||
|
||||
// abi-decoder declarations
|
||||
interface DecodedLogArg {
|
||||
}
|
||||
interface DecodedLog {
|
||||
name: string;
|
||||
events: DecodedLogArg[];
|
||||
}
|
||||
declare module 'abi-decoder' {
|
||||
import * as Web3 from 'web3';
|
||||
const addABI: (abi: Web3.AbiDefinition) => void;
|
||||
const decodeLogs: (logs: Web3.LogEntry[]) => DecodedLog[];
|
||||
}
|
||||
|
||||
declare module 'web3/lib/solidity/coder' {
|
||||
const decodeParams: (types: string[], data: string) => any[];
|
||||
}
|
||||
|
||||
23
packages/0x.js/src/globalsAugment.d.ts
vendored
23
packages/0x.js/src/globalsAugment.d.ts
vendored
@@ -1,23 +0,0 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
// HACK: This module overrides the Chai namespace so that we can use BigNumber types inside.
|
||||
// Source: https://github.com/Microsoft/TypeScript/issues/7352#issuecomment-191547232
|
||||
declare global {
|
||||
// HACK: In order to merge the bignumber declaration added by chai-bignumber to the chai Assertion
|
||||
// interface we must use `namespace` as the Chai definitelyTyped definition does. Since we otherwise
|
||||
// disallow `namespace`, we disable tslint for the following.
|
||||
/* tslint:disable */
|
||||
namespace Chai {
|
||||
interface NumberComparer {
|
||||
(value: number|BigNumber, message?: string): Assertion;
|
||||
}
|
||||
interface NumericComparison {
|
||||
greaterThan: NumberComparer;
|
||||
}
|
||||
}
|
||||
/* tslint:enable */
|
||||
interface DecodedLogArg {
|
||||
name: string;
|
||||
value: string|BigNumber;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,53 @@
|
||||
export {ZeroEx} from './0x';
|
||||
export { ZeroEx } from './0x';
|
||||
|
||||
export {
|
||||
Order,
|
||||
BlockParamLiteral,
|
||||
FilterObject,
|
||||
BlockParam,
|
||||
ContractEventArg,
|
||||
ExchangeContractErrs,
|
||||
LogWithDecodedArgs,
|
||||
Order,
|
||||
Provider,
|
||||
SignedOrder,
|
||||
ECSignature,
|
||||
ZeroExError,
|
||||
EventCallback,
|
||||
ExchangeContractErrs,
|
||||
ContractEvent,
|
||||
OrderStateValid,
|
||||
OrderStateInvalid,
|
||||
OrderState,
|
||||
Token,
|
||||
ExchangeEvents,
|
||||
TokenEvents,
|
||||
TransactionReceipt,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
} from '@0xproject/types';
|
||||
|
||||
export { OrderWatcherConfig } from '@0xproject/order-watcher';
|
||||
|
||||
export {
|
||||
EventCallback,
|
||||
ContractEvent,
|
||||
IndexedFilterValues,
|
||||
BlockRange,
|
||||
BlockParam,
|
||||
OrderCancellationRequest,
|
||||
OrderFillRequest,
|
||||
ContractEventArgs,
|
||||
MethodOpts,
|
||||
OrderTransactionOpts,
|
||||
TransactionOpts,
|
||||
LogEvent,
|
||||
DecodedLogEvent,
|
||||
OnOrderStateChangeCallback,
|
||||
ContractWrappersError,
|
||||
EtherTokenContractEventArgs,
|
||||
WithdrawalContractEventArgs,
|
||||
DepositContractEventArgs,
|
||||
EtherTokenEvents,
|
||||
TransferContractEventArgs,
|
||||
ApprovalContractEventArgs,
|
||||
TokenContractEventArgs,
|
||||
TokenEvents,
|
||||
LogErrorContractEventArgs,
|
||||
LogCancelContractEventArgs,
|
||||
LogFillContractEventArgs,
|
||||
ExchangeContractEventArgs,
|
||||
TransferContractEventArgs,
|
||||
ApprovalContractEventArgs,
|
||||
TokenContractEventArgs,
|
||||
EtherTokenContractEventArgs,
|
||||
WithdrawalContractEventArgs,
|
||||
DepositContractEventArgs,
|
||||
ContractEventArgs,
|
||||
ContractEventArg,
|
||||
Web3Provider,
|
||||
ZeroExConfig,
|
||||
EtherTokenEvents,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
LogWithDecodedArgs,
|
||||
MethodOpts,
|
||||
OrderTransactionOpts,
|
||||
TransactionOpts,
|
||||
FilterObject,
|
||||
LogEvent,
|
||||
DecodedLogEvent,
|
||||
EventWatcherCallback,
|
||||
OnOrderStateChangeCallback,
|
||||
OrderStateValid,
|
||||
OrderStateInvalid,
|
||||
OrderState,
|
||||
} from './types';
|
||||
|
||||
export {
|
||||
TransactionReceipt,
|
||||
} from '@0xproject/types';
|
||||
ExchangeEvents,
|
||||
ContractWrappersConfig,
|
||||
} from '@0xproject/contract-wrappers';
|
||||
|
||||
8
packages/0x.js/src/monorepo_scripts/postpublish.ts
Normal file
8
packages/0x.js/src/monorepo_scripts/postpublish.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { postpublishUtils } from '@0xproject/monorepo-scripts';
|
||||
|
||||
import * as packageJSON from '../package.json';
|
||||
import * as tsConfigJSON from '../tsconfig.json';
|
||||
|
||||
const cwd = `${__dirname}/..`;
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
postpublishUtils.runAsync(packageJSON, tsConfigJSON, cwd);
|
||||
8
packages/0x.js/src/monorepo_scripts/stage_docs.ts
Normal file
8
packages/0x.js/src/monorepo_scripts/stage_docs.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { postpublishUtils } from '@0xproject/monorepo-scripts';
|
||||
|
||||
import * as packageJSON from '../package.json';
|
||||
import * as tsConfigJSON from '../tsconfig.json';
|
||||
|
||||
const cwd = `${__dirname}/..`;
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
postpublishUtils.publishDocsToStagingAsync(packageJSON, tsConfigJSON, cwd);
|
||||
@@ -1,86 +0,0 @@
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
EventWatcherCallback,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {assert} from '../utils/assert';
|
||||
|
||||
const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200;
|
||||
|
||||
enum LogEventState {
|
||||
Removed,
|
||||
Added,
|
||||
}
|
||||
|
||||
/*
|
||||
* The EventWatcher watches for blockchain events at the specified block confirmation
|
||||
* depth.
|
||||
*/
|
||||
export class EventWatcher {
|
||||
private _web3Wrapper: Web3Wrapper;
|
||||
private _pollingIntervalMs: number;
|
||||
private _intervalIdIfExists?: NodeJS.Timer;
|
||||
private _lastEvents: Web3.LogEntry[] = [];
|
||||
constructor(web3Wrapper: Web3Wrapper, pollingIntervalIfExistsMs: undefined|number) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs) ?
|
||||
DEFAULT_EVENT_POLLING_INTERVAL_MS :
|
||||
pollingIntervalIfExistsMs;
|
||||
}
|
||||
public subscribe(callback: EventWatcherCallback): void {
|
||||
assert.isFunction('callback', callback);
|
||||
if (!_.isUndefined(this._intervalIdIfExists)) {
|
||||
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
|
||||
}
|
||||
this._intervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
||||
this._pollForBlockchainEventsAsync.bind(this, callback), this._pollingIntervalMs,
|
||||
);
|
||||
}
|
||||
public unsubscribe(): void {
|
||||
this._lastEvents = [];
|
||||
if (!_.isUndefined(this._intervalIdIfExists)) {
|
||||
intervalUtils.clearAsyncExcludingInterval(this._intervalIdIfExists);
|
||||
delete this._intervalIdIfExists;
|
||||
}
|
||||
}
|
||||
private async _pollForBlockchainEventsAsync(callback: EventWatcherCallback): Promise<void> {
|
||||
const pendingEvents = await this._getEventsAsync();
|
||||
if (pendingEvents.length === 0) {
|
||||
// HACK: Sometimes when node rebuilds the pending block we get back the empty result.
|
||||
// We don't want to emit a lot of removal events and bring them back after a couple of miliseconds,
|
||||
// that's why we just ignore those cases.
|
||||
return;
|
||||
}
|
||||
const removedEvents = _.differenceBy(this._lastEvents, pendingEvents, JSON.stringify);
|
||||
const newEvents = _.differenceBy(pendingEvents, this._lastEvents, JSON.stringify);
|
||||
await this._emitDifferencesAsync(removedEvents, LogEventState.Removed, callback);
|
||||
await this._emitDifferencesAsync(newEvents, LogEventState.Added, callback);
|
||||
this._lastEvents = pendingEvents;
|
||||
}
|
||||
private async _getEventsAsync(): Promise<Web3.LogEntry[]> {
|
||||
const eventFilter = {
|
||||
fromBlock: BlockParamLiteral.Pending,
|
||||
toBlock: BlockParamLiteral.Pending,
|
||||
};
|
||||
const events = await this._web3Wrapper.getLogsAsync(eventFilter);
|
||||
return events;
|
||||
}
|
||||
private async _emitDifferencesAsync(
|
||||
logs: Web3.LogEntry[], logEventState: LogEventState, callback: EventWatcherCallback,
|
||||
): Promise<void> {
|
||||
for (const log of logs) {
|
||||
const logEvent = {
|
||||
removed: logEventState === LogEventState.Removed,
|
||||
...log,
|
||||
};
|
||||
if (!_.isUndefined(this._intervalIdIfExists)) {
|
||||
callback(logEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,5 @@
|
||||
export const zeroExConfigSchema = {
|
||||
id: '/ZeroExConfig',
|
||||
properties: {
|
||||
networkId: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
gasPrice: {$ref: '/Number'},
|
||||
exchangeContractAddress: {$ref: '/Address'},
|
||||
tokenRegistryContractAddress: {$ref: '/Address'},
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
pollingIntervalMs: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
numConfirmations: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
oneOf: [{ $ref: '/ZeroExPrivateNetworkConfig' }, { $ref: '/ZeroExPublicNetworkConfig' }],
|
||||
type: 'object',
|
||||
required: ['networkId'],
|
||||
};
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
export const zeroExPrivateNetworkConfigSchema = {
|
||||
id: '/ZeroExPrivateNetworkConfig',
|
||||
properties: {
|
||||
networkId: {
|
||||
type: 'number',
|
||||
minimum: 1,
|
||||
},
|
||||
gasPrice: { $ref: '/Number' },
|
||||
zrxContractAddress: { $ref: '/Address' },
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
tokenRegistryContractAddress: { $ref: '/Address' },
|
||||
tokenTransferProxyContractAddress: { $ref: '/Address' },
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
pollingIntervalMs: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
numConfirmations: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'object',
|
||||
required: [
|
||||
'networkId',
|
||||
'zrxContractAddress',
|
||||
'exchangeContractAddress',
|
||||
'tokenRegistryContractAddress',
|
||||
'tokenTransferProxyContractAddress',
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
const networkNameToId: { [networkName: string]: number } = {
|
||||
mainnet: 1,
|
||||
ropsten: 3,
|
||||
rinkeby: 4,
|
||||
kovan: 42,
|
||||
ganache: 50,
|
||||
};
|
||||
|
||||
export const zeroExPublicNetworkConfigSchema = {
|
||||
id: '/ZeroExPublicNetworkConfig',
|
||||
properties: {
|
||||
networkId: {
|
||||
type: 'number',
|
||||
enum: [
|
||||
networkNameToId.mainnet,
|
||||
networkNameToId.ropsten,
|
||||
networkNameToId.rinkeby,
|
||||
networkNameToId.kovan,
|
||||
networkNameToId.ganache,
|
||||
],
|
||||
},
|
||||
gasPrice: { $ref: '/Number' },
|
||||
zrxContractAddress: { $ref: '/Address' },
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
tokenRegistryContractAddress: { $ref: '/Address' },
|
||||
tokenTransferProxyContractAddress: { $ref: '/Address' },
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
pollingIntervalMs: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
numConfirmations: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'object',
|
||||
required: ['networkId'],
|
||||
};
|
||||
@@ -1,29 +1,15 @@
|
||||
import {TransactionReceipt} from '@0xproject/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export enum ZeroExError {
|
||||
ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
|
||||
ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
|
||||
EtherTokenContractDoesNotExist = 'ETHER_TOKEN_CONTRACT_DOES_NOT_EXIST',
|
||||
TokenTransferProxyContractDoesNotExist = 'TOKEN_TRANSFER_PROXY_CONTRACT_DOES_NOT_EXIST',
|
||||
TokenRegistryContractDoesNotExist = 'TOKEN_REGISTRY_CONTRACT_DOES_NOT_EXIST',
|
||||
TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST',
|
||||
UnhandledError = 'UNHANDLED_ERROR',
|
||||
UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES',
|
||||
InvalidSignature = 'INVALID_SIGNATURE',
|
||||
ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
|
||||
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
|
||||
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
|
||||
InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT',
|
||||
InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL',
|
||||
InvalidJump = 'INVALID_JUMP',
|
||||
OutOfGas = 'OUT_OF_GAS',
|
||||
NoNetworkId = 'NO_NETWORK_ID',
|
||||
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
|
||||
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
|
||||
TransactionMiningTimeout = 'TRANSACTION_MINING_TIMEOUT',
|
||||
}
|
||||
import {
|
||||
BlockParam,
|
||||
BlockParamLiteral,
|
||||
ContractAbi,
|
||||
ContractEventArg,
|
||||
ExchangeContractErrs,
|
||||
FilterObject,
|
||||
LogWithDecodedArgs,
|
||||
Order,
|
||||
OrderState,
|
||||
SignedOrder,
|
||||
} from '@0xproject/types';
|
||||
|
||||
export enum InternalZeroExError {
|
||||
NoAbiDecoder = 'NO_ABI_DECODER',
|
||||
@@ -31,375 +17,4 @@ export enum InternalZeroExError {
|
||||
WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY',
|
||||
}
|
||||
|
||||
/**
|
||||
* Elliptic Curve signature
|
||||
*/
|
||||
export interface ECSignature {
|
||||
v: number;
|
||||
r: string;
|
||||
s: string;
|
||||
}
|
||||
|
||||
export type OrderAddresses = [string, string, string, string, string];
|
||||
|
||||
export type OrderValues = [BigNumber, BigNumber, BigNumber,
|
||||
BigNumber, BigNumber, BigNumber];
|
||||
|
||||
export type LogEvent = Web3.LogEntryEvent;
|
||||
export interface DecodedLogEvent<ArgsType> {
|
||||
isRemoved: boolean;
|
||||
log: LogWithDecodedArgs<ArgsType>;
|
||||
}
|
||||
|
||||
export type EventCallback<ArgsType> = (err: null|Error, log?: DecodedLogEvent<ArgsType>) => void;
|
||||
export type EventWatcherCallback = (log: LogEvent) => void;
|
||||
|
||||
export enum SolidityTypes {
|
||||
Address = 'address',
|
||||
Uint256 = 'uint256',
|
||||
Uint8 = 'uint8',
|
||||
Uint = 'uint',
|
||||
}
|
||||
|
||||
export enum ExchangeContractErrCodes {
|
||||
ERROR_FILL_EXPIRED, // Order has already expired
|
||||
ERROR_FILL_NO_VALUE, // Order has already been fully filled or cancelled
|
||||
ERROR_FILL_TRUNCATION, // Rounding error too large
|
||||
ERROR_FILL_BALANCE_ALLOWANCE, // Insufficient balance or allowance for token transfer
|
||||
ERROR_CANCEL_EXPIRED, // Order has already expired
|
||||
ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled
|
||||
}
|
||||
|
||||
export enum ExchangeContractErrs {
|
||||
OrderFillExpired = 'ORDER_FILL_EXPIRED',
|
||||
OrderCancelExpired = 'ORDER_CANCEL_EXPIRED',
|
||||
OrderCancelAmountZero = 'ORDER_CANCEL_AMOUNT_ZERO',
|
||||
OrderAlreadyCancelledOrFilled = 'ORDER_ALREADY_CANCELLED_OR_FILLED',
|
||||
OrderFillAmountZero = 'ORDER_FILL_AMOUNT_ZERO',
|
||||
OrderRemainingFillAmountZero = 'ORDER_REMAINING_FILL_AMOUNT_ZERO',
|
||||
OrderFillRoundingError = 'ORDER_FILL_ROUNDING_ERROR',
|
||||
FillBalanceAllowanceError = 'FILL_BALANCE_ALLOWANCE_ERROR',
|
||||
InsufficientTakerBalance = 'INSUFFICIENT_TAKER_BALANCE',
|
||||
InsufficientTakerAllowance = 'INSUFFICIENT_TAKER_ALLOWANCE',
|
||||
InsufficientMakerBalance = 'INSUFFICIENT_MAKER_BALANCE',
|
||||
InsufficientMakerAllowance = 'INSUFFICIENT_MAKER_ALLOWANCE',
|
||||
InsufficientTakerFeeBalance = 'INSUFFICIENT_TAKER_FEE_BALANCE',
|
||||
InsufficientTakerFeeAllowance = 'INSUFFICIENT_TAKER_FEE_ALLOWANCE',
|
||||
InsufficientMakerFeeBalance = 'INSUFFICIENT_MAKER_FEE_BALANCE',
|
||||
InsufficientMakerFeeAllowance = 'INSUFFICIENT_MAKER_FEE_ALLOWANCE',
|
||||
TransactionSenderIsNotFillOrderTaker = 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER',
|
||||
MultipleMakersInSingleCancelBatchDisallowed = 'MULTIPLE_MAKERS_IN_SINGLE_CANCEL_BATCH_DISALLOWED',
|
||||
InsufficientRemainingFillAmount = 'INSUFFICIENT_REMAINING_FILL_AMOUNT',
|
||||
MultipleTakerTokensInFillUpToDisallowed = 'MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED',
|
||||
BatchOrdersMustHaveSameExchangeAddress = 'BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS',
|
||||
BatchOrdersMustHaveAtLeastOneItem = 'BATCH_ORDERS_MUST_HAVE_AT_LEAST_ONE_ITEM',
|
||||
}
|
||||
|
||||
export type RawLog = Web3.LogEntry;
|
||||
|
||||
export interface ContractEvent {
|
||||
logIndex: number;
|
||||
transactionIndex: number;
|
||||
transactionHash: string;
|
||||
blockHash: string;
|
||||
blockNumber: number;
|
||||
address: string;
|
||||
type: string;
|
||||
event: string;
|
||||
args: ContractEventArgs;
|
||||
}
|
||||
|
||||
export interface LogFillContractEventArgs {
|
||||
maker: string;
|
||||
taker: string;
|
||||
feeRecipient: string;
|
||||
makerToken: string;
|
||||
takerToken: string;
|
||||
filledMakerTokenAmount: BigNumber;
|
||||
filledTakerTokenAmount: BigNumber;
|
||||
paidMakerFee: BigNumber;
|
||||
paidTakerFee: BigNumber;
|
||||
tokens: string;
|
||||
orderHash: string;
|
||||
}
|
||||
export interface LogCancelContractEventArgs {
|
||||
maker: string;
|
||||
feeRecipient: string;
|
||||
makerToken: string;
|
||||
takerToken: string;
|
||||
cancelledMakerTokenAmount: BigNumber;
|
||||
cancelledTakerTokenAmount: BigNumber;
|
||||
tokens: string;
|
||||
orderHash: string;
|
||||
}
|
||||
export interface LogErrorContractEventArgs {
|
||||
errorId: BigNumber;
|
||||
orderHash: string;
|
||||
}
|
||||
export type ExchangeContractEventArgs = LogFillContractEventArgs|LogCancelContractEventArgs|LogErrorContractEventArgs;
|
||||
export interface TransferContractEventArgs {
|
||||
_from: string;
|
||||
_to: string;
|
||||
_value: BigNumber;
|
||||
}
|
||||
export interface ApprovalContractEventArgs {
|
||||
_owner: string;
|
||||
_spender: string;
|
||||
_value: BigNumber;
|
||||
}
|
||||
export interface DepositContractEventArgs {
|
||||
_owner: string;
|
||||
_value: BigNumber;
|
||||
}
|
||||
export interface WithdrawalContractEventArgs {
|
||||
_owner: string;
|
||||
_value: BigNumber;
|
||||
}
|
||||
export type TokenContractEventArgs = TransferContractEventArgs|ApprovalContractEventArgs;
|
||||
export type EtherTokenContractEventArgs = TokenContractEventArgs|DepositContractEventArgs|WithdrawalContractEventArgs;
|
||||
export type ContractEventArgs = ExchangeContractEventArgs|TokenContractEventArgs|EtherTokenContractEventArgs;
|
||||
export type ContractEventArg = string|BigNumber;
|
||||
|
||||
export interface Order {
|
||||
maker: string;
|
||||
taker: string;
|
||||
makerFee: BigNumber;
|
||||
takerFee: BigNumber;
|
||||
makerTokenAmount: BigNumber;
|
||||
takerTokenAmount: BigNumber;
|
||||
makerTokenAddress: string;
|
||||
takerTokenAddress: string;
|
||||
salt: BigNumber;
|
||||
exchangeContractAddress: string;
|
||||
feeRecipient: string;
|
||||
expirationUnixTimestampSec: BigNumber;
|
||||
}
|
||||
|
||||
export interface SignedOrder extends Order {
|
||||
ecSignature: ECSignature;
|
||||
}
|
||||
|
||||
// [address, name, symbol, decimals, ipfsHash, swarmHash]
|
||||
export type TokenMetadata = [string, string, string, BigNumber, string, string];
|
||||
|
||||
export interface Token {
|
||||
name: string;
|
||||
address: string;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
}
|
||||
|
||||
export interface TxOpts {
|
||||
from: string;
|
||||
gas?: number;
|
||||
value?: BigNumber;
|
||||
gasPrice?: BigNumber;
|
||||
}
|
||||
|
||||
export interface TokenAddressBySymbol {
|
||||
[symbol: string]: string;
|
||||
}
|
||||
|
||||
export enum ExchangeEvents {
|
||||
LogFill = 'LogFill',
|
||||
LogCancel = 'LogCancel',
|
||||
LogError = 'LogError',
|
||||
}
|
||||
|
||||
export enum TokenEvents {
|
||||
Transfer = 'Transfer',
|
||||
Approval = 'Approval',
|
||||
}
|
||||
|
||||
export enum EtherTokenEvents {
|
||||
Transfer = 'Transfer',
|
||||
Approval = 'Approval',
|
||||
Deposit = 'Deposit',
|
||||
Withdrawal = 'Withdrawal',
|
||||
}
|
||||
|
||||
export type ContractEvents = TokenEvents|ExchangeEvents|EtherTokenEvents;
|
||||
|
||||
export interface IndexedFilterValues {
|
||||
[index: string]: ContractEventArg;
|
||||
}
|
||||
|
||||
// Earliest is omitted by design. It is simply an alias for the `0` constant and
|
||||
// is thus not very helpful. Moreover, this type is used in places that only accept
|
||||
// `latest` or `pending`.
|
||||
export enum BlockParamLiteral {
|
||||
Latest = 'latest',
|
||||
Pending = 'pending',
|
||||
}
|
||||
|
||||
export type BlockParam = BlockParamLiteral|number;
|
||||
|
||||
export interface BlockRange {
|
||||
fromBlock: BlockParam;
|
||||
toBlock: BlockParam;
|
||||
}
|
||||
|
||||
export type DoneCallback = (err?: Error) => void;
|
||||
|
||||
export interface OrderCancellationRequest {
|
||||
order: Order|SignedOrder;
|
||||
takerTokenCancelAmount: BigNumber;
|
||||
}
|
||||
|
||||
export interface OrderFillRequest {
|
||||
signedOrder: SignedOrder;
|
||||
takerTokenFillAmount: BigNumber;
|
||||
}
|
||||
|
||||
export type AsyncMethod = (...args: any[]) => Promise<any>;
|
||||
export type SyncMethod = (...args: any[]) => any;
|
||||
|
||||
/**
|
||||
* We re-export the `Web3.Provider` type specified in the Web3 Typescript typings
|
||||
* since it is the type of the `provider` argument to the `ZeroEx` constructor.
|
||||
* It is however a `Web3` library type, not a native `0x.js` type. To learn more
|
||||
* about providers, visit https://0xproject.com/wiki#Web3-Provider-Explained
|
||||
*/
|
||||
export type Web3Provider = Web3.Provider;
|
||||
|
||||
export interface JSONRPCPayload {
|
||||
params: any[];
|
||||
method: string;
|
||||
}
|
||||
|
||||
/*
|
||||
* orderExpirationCheckingIntervalMs: How often to check for expired orders. Default: 50
|
||||
* eventPollingIntervalMs: How often to poll the Ethereum node for new events. Defaults: 200
|
||||
* expirationMarginMs: Amount of time before order expiry that you'd like to be notified
|
||||
* of an orders expiration. Defaults: 0
|
||||
* cleanupJobIntervalMs: How often to run a cleanup job which revalidates all the orders. Defaults: 1h
|
||||
*/
|
||||
export interface OrderStateWatcherConfig {
|
||||
orderExpirationCheckingIntervalMs?: number;
|
||||
eventPollingIntervalMs?: number;
|
||||
expirationMarginMs?: number;
|
||||
cleanupJobIntervalMs?: number;
|
||||
}
|
||||
|
||||
/*
|
||||
* networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 42-kovan, 50-testrpc)
|
||||
* gasPrice: Gas price to use with every transaction
|
||||
* exchangeContractAddress: The address of an exchange contract to use
|
||||
* tokenRegistryContractAddress: The address of a token registry contract to use
|
||||
* tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use
|
||||
* orderWatcherConfig: All the configs related to the orderWatcher
|
||||
*/
|
||||
export interface ZeroExConfig {
|
||||
networkId: number;
|
||||
gasPrice?: BigNumber;
|
||||
exchangeContractAddress?: string;
|
||||
tokenRegistryContractAddress?: string;
|
||||
tokenTransferProxyContractAddress?: string;
|
||||
orderWatcherConfig?: OrderStateWatcherConfig;
|
||||
}
|
||||
|
||||
export enum AbiType {
|
||||
Function = 'function',
|
||||
Constructor = 'constructor',
|
||||
Event = 'event',
|
||||
Fallback = 'fallback',
|
||||
}
|
||||
|
||||
export interface DecodedLogArgs {
|
||||
[argName: string]: ContractEventArg;
|
||||
}
|
||||
|
||||
export interface LogWithDecodedArgs<ArgsType> extends Web3.DecodedLogEntry<ArgsType> {}
|
||||
|
||||
export interface TransactionReceiptWithDecodedLogs extends TransactionReceipt {
|
||||
logs: Array<LogWithDecodedArgs<DecodedLogArgs>|Web3.LogEntry>;
|
||||
}
|
||||
|
||||
export type ArtifactContractName = 'ZRX'|'TokenTransferProxy'|'TokenRegistry'|'Token'|'Exchange'|'EtherToken';
|
||||
|
||||
export interface Artifact {
|
||||
contract_name: ArtifactContractName;
|
||||
abi: Web3.ContractAbi;
|
||||
networks: {
|
||||
[networkId: number]: {
|
||||
address: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* expectedFillTakerTokenAmount: If specified, the validation method will ensure that the
|
||||
* supplied order maker has a sufficient allowance/balance to fill this amount of the order's
|
||||
* takerTokenAmount. If not specified, the validation method ensures that the maker has a sufficient
|
||||
* allowance/balance to fill the entire remaining order amount.
|
||||
*/
|
||||
export interface ValidateOrderFillableOpts {
|
||||
expectedFillTakerTokenAmount?: BigNumber;
|
||||
}
|
||||
|
||||
/*
|
||||
* defaultBlock: The block up to which to query the blockchain state. Setting this to a historical block number
|
||||
* let's the user query the blockchain's state at an arbitrary point in time. In order for this to work, the
|
||||
* backing Ethereum node must keep the entire historical state of the chain (e.g setting `--pruning=archive`
|
||||
* flag when running Parity).
|
||||
*/
|
||||
export interface MethodOpts {
|
||||
defaultBlock?: Web3.BlockParam;
|
||||
}
|
||||
|
||||
/*
|
||||
* gasPrice: Gas price in Wei to use for a transaction
|
||||
* gasLimit: The amount of gas to send with a transaction
|
||||
*/
|
||||
export interface TransactionOpts {
|
||||
gasPrice?: BigNumber;
|
||||
gasLimit?: number;
|
||||
}
|
||||
|
||||
/*
|
||||
* shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before
|
||||
* broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default: true
|
||||
*/
|
||||
export interface OrderTransactionOpts extends TransactionOpts {
|
||||
shouldValidate?: boolean;
|
||||
}
|
||||
|
||||
export type FilterObject = Web3.FilterObject;
|
||||
|
||||
export enum TradeSide {
|
||||
Maker = 'maker',
|
||||
Taker = 'taker',
|
||||
}
|
||||
|
||||
export enum TransferType {
|
||||
Trade = 'trade',
|
||||
Fee = 'fee',
|
||||
}
|
||||
|
||||
export interface OrderRelevantState {
|
||||
makerBalance: BigNumber;
|
||||
makerProxyAllowance: BigNumber;
|
||||
makerFeeBalance: BigNumber;
|
||||
makerFeeProxyAllowance: BigNumber;
|
||||
filledTakerTokenAmount: BigNumber;
|
||||
cancelledTakerTokenAmount: BigNumber;
|
||||
remainingFillableMakerTokenAmount: BigNumber;
|
||||
remainingFillableTakerTokenAmount: BigNumber;
|
||||
}
|
||||
|
||||
export interface OrderStateValid {
|
||||
isValid: true;
|
||||
orderHash: string;
|
||||
orderRelevantState: OrderRelevantState;
|
||||
}
|
||||
|
||||
export interface OrderStateInvalid {
|
||||
isValid: false;
|
||||
orderHash: string;
|
||||
error: ExchangeContractErrs;
|
||||
}
|
||||
|
||||
export type OrderState = OrderStateValid|OrderStateInvalid;
|
||||
|
||||
export type OnOrderStateChangeCallback = (orderState: OrderState) => void;
|
||||
// tslint:disable:max-file-line-count
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
import * as SolidityCoder from 'web3/lib/solidity/coder';
|
||||
|
||||
import {AbiType, ContractEventArgs, DecodedLogArgs, LogWithDecodedArgs, RawLog, SolidityTypes} from '../types';
|
||||
|
||||
export class AbiDecoder {
|
||||
private _savedABIs: Web3.AbiDefinition[] = [];
|
||||
private _methodIds: {[signatureHash: string]: Web3.EventAbi} = {};
|
||||
private static _padZeros(address: string) {
|
||||
let formatted = address;
|
||||
if (_.startsWith(formatted, '0x')) {
|
||||
formatted = formatted.slice(2);
|
||||
}
|
||||
|
||||
formatted = _.padStart(formatted, 40, '0');
|
||||
return `0x${formatted}`;
|
||||
}
|
||||
constructor(abiArrays: Web3.AbiDefinition[][]) {
|
||||
_.map(abiArrays, this._addABI.bind(this));
|
||||
}
|
||||
// This method can only decode logs from the 0x & ERC20 smart contracts
|
||||
public tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
|
||||
log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog {
|
||||
const methodId = log.topics[0];
|
||||
const event = this._methodIds[methodId];
|
||||
if (_.isUndefined(event)) {
|
||||
return log;
|
||||
}
|
||||
const logData = log.data;
|
||||
const decodedParams: DecodedLogArgs = {};
|
||||
let dataIndex = 0;
|
||||
let topicsIndex = 1;
|
||||
|
||||
const nonIndexedInputs = _.filter(event.inputs, input => !input.indexed);
|
||||
const dataTypes = _.map(nonIndexedInputs, input => input.type);
|
||||
const decodedData = SolidityCoder.decodeParams(dataTypes, logData.slice('0x'.length));
|
||||
|
||||
_.map(event.inputs, (param: Web3.EventParameter) => {
|
||||
// Indexed parameters are stored in topics. Non-indexed ones in decodedData
|
||||
let value = param.indexed ? log.topics[topicsIndex++] : decodedData[dataIndex++];
|
||||
if (param.type === SolidityTypes.Address) {
|
||||
value = AbiDecoder._padZeros(new BigNumber(value).toString(16));
|
||||
} else if (param.type === SolidityTypes.Uint256 ||
|
||||
param.type === SolidityTypes.Uint8 ||
|
||||
param.type === SolidityTypes.Uint) {
|
||||
value = new BigNumber(value);
|
||||
}
|
||||
decodedParams[param.name] = value;
|
||||
});
|
||||
|
||||
return {
|
||||
...log,
|
||||
event: event.name,
|
||||
args: decodedParams,
|
||||
};
|
||||
}
|
||||
private _addABI(abiArray: Web3.AbiDefinition[]): void {
|
||||
_.map(abiArray, (abi: Web3.AbiDefinition) => {
|
||||
if (abi.type === AbiType.Event) {
|
||||
const signature = `${abi.name}(${_.map(abi.inputs, input => input.type).join(',')})`;
|
||||
const signatureHash = new Web3().sha3(signature);
|
||||
this._methodIds[signatureHash] = abi;
|
||||
}
|
||||
});
|
||||
this._savedABIs = this._savedABIs.concat(abiArray);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import {assert as sharedAssert} from '@0xproject/assert';
|
||||
// We need those two unused imports because they're actually used by sharedAssert which gets injected here
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import {Schema} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import * as BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ECSignature} from '../types';
|
||||
import {signatureUtils} from '../utils/signature_utils';
|
||||
|
||||
export const assert = {
|
||||
...sharedAssert,
|
||||
isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string) {
|
||||
const isValidSignature = signatureUtils.isValidSignature(orderHash, ecSignature, signerAddress);
|
||||
this.assert(isValidSignature, `Expected order with hash '${orderHash}' to have a valid signature`);
|
||||
},
|
||||
async isSenderAddressAsync(variableName: string, senderAddressHex: string,
|
||||
web3Wrapper: Web3Wrapper): Promise<void> {
|
||||
sharedAssert.isETHAddressHex(variableName, senderAddressHex);
|
||||
const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex);
|
||||
sharedAssert.assert(isSenderAddressAvailable,
|
||||
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
},
|
||||
async isUserAddressAvailableAsync(web3Wrapper: Web3Wrapper): Promise<void> {
|
||||
const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
this.assert(!_.isEmpty(availableAddresses), 'No addresses were available on the provided web3 provider');
|
||||
},
|
||||
};
|
||||
@@ -1,12 +1,6 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
|
||||
export const constants = {
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
TESTRPC_NETWORK_ID: 50,
|
||||
MAX_DIGITS_IN_UNSIGNED_256_INT: 78,
|
||||
INVALID_JUMP_PATTERN: 'invalid JUMP at',
|
||||
OUT_OF_GAS_PATTERN: 'out of gas',
|
||||
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
|
||||
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
|
||||
DEFAULT_BLOCK_POLLING_INTERVAL: 1000,
|
||||
};
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
|
||||
import {ECSignature} from '../types';
|
||||
|
||||
export const signatureUtils = {
|
||||
isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
||||
const dataBuff = ethUtil.toBuffer(data);
|
||||
const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
|
||||
try {
|
||||
const pubKey = ethUtil.ecrecover(
|
||||
msgHashBuff,
|
||||
signature.v,
|
||||
ethUtil.toBuffer(signature.r),
|
||||
ethUtil.toBuffer(signature.s));
|
||||
const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
|
||||
return retrievedAddress === signerAddress;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
parseSignatureHexAsVRS(signatureHex: string): ECSignature {
|
||||
const signatureBuffer = ethUtil.toBuffer(signatureHex);
|
||||
let v = signatureBuffer[0];
|
||||
if (v < 27) {
|
||||
v += 27;
|
||||
}
|
||||
const r = signatureBuffer.slice(1, 33);
|
||||
const s = signatureBuffer.slice(33, 65);
|
||||
const ecSignature: ECSignature = {
|
||||
v,
|
||||
r: ethUtil.bufferToHex(r),
|
||||
s: ethUtil.bufferToHex(s),
|
||||
};
|
||||
return ecSignature;
|
||||
},
|
||||
parseSignatureHexAsRSV(signatureHex: string): ECSignature {
|
||||
const {v, r, s} = ethUtil.fromRpcSig(signatureHex);
|
||||
const ecSignature: ECSignature = {
|
||||
v,
|
||||
r: ethUtil.bufferToHex(r),
|
||||
s: ethUtil.bufferToHex(s),
|
||||
};
|
||||
return ecSignature;
|
||||
},
|
||||
};
|
||||
@@ -1,59 +0,0 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import BN = require('bn.js');
|
||||
import * as ethABI from 'ethereumjs-abi';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {Order, SignedOrder, SolidityTypes} from '../types';
|
||||
|
||||
export const utils = {
|
||||
/**
|
||||
* Converts BigNumber instance to BN
|
||||
* The only reason we convert to BN is to remain compatible with `ethABI. soliditySHA3` that
|
||||
* expects values of Solidity type `uint` to be passed as type `BN`.
|
||||
* We do not use BN anywhere else in the codebase.
|
||||
*/
|
||||
bigNumberToBN(value: BigNumber) {
|
||||
return new BN(value.toString(), 10);
|
||||
},
|
||||
consoleLog(message: string): void {
|
||||
// tslint:disable-next-line: no-console
|
||||
console.log(message);
|
||||
},
|
||||
isParityNode(nodeVersion: string): boolean {
|
||||
return _.includes(nodeVersion, 'Parity');
|
||||
},
|
||||
isTestRpc(nodeVersion: string): boolean {
|
||||
return _.includes(nodeVersion, 'TestRPC');
|
||||
},
|
||||
spawnSwitchErr(name: string, value: any): Error {
|
||||
return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
|
||||
},
|
||||
getOrderHashHex(order: Order|SignedOrder): string {
|
||||
const orderParts = [
|
||||
{value: order.exchangeContractAddress, type: SolidityTypes.Address},
|
||||
{value: order.maker, type: SolidityTypes.Address},
|
||||
{value: order.taker, type: SolidityTypes.Address},
|
||||
{value: order.makerTokenAddress, type: SolidityTypes.Address},
|
||||
{value: order.takerTokenAddress, type: SolidityTypes.Address},
|
||||
{value: order.feeRecipient, type: SolidityTypes.Address},
|
||||
{value: utils.bigNumberToBN(order.makerTokenAmount), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.takerTokenAmount), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.makerFee), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.takerFee), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.expirationUnixTimestampSec), type: SolidityTypes.Uint256},
|
||||
{value: utils.bigNumberToBN(order.salt), type: SolidityTypes.Uint256},
|
||||
];
|
||||
const types = _.map(orderParts, o => o.type);
|
||||
const values = _.map(orderParts, o => o.value);
|
||||
const hashBuff = ethABI.soliditySHA3(types, values);
|
||||
const hashHex = ethUtil.bufferToHex(hashBuff);
|
||||
return hashHex;
|
||||
},
|
||||
getCurrentUnixTimestampSec(): BigNumber {
|
||||
return new BigNumber(Date.now() / 1000).round();
|
||||
},
|
||||
getCurrentUnixTimestampMs(): BigNumber {
|
||||
return new BigNumber(Date.now());
|
||||
},
|
||||
};
|
||||
@@ -1,27 +1,32 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ContractWrappers } from '@0xproject/contract-wrappers';
|
||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'make-promises-safe';
|
||||
import 'mocha';
|
||||
import * as path from 'path';
|
||||
import * as Sinon from 'sinon';
|
||||
|
||||
import {ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx} from '../src';
|
||||
import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx } from '../src';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('ZeroEx library', () => {
|
||||
const web3 = web3Factory.create();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
let zeroEx: ZeroEx;
|
||||
before(async () => {
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
zeroEx = new ZeroEx(provider, config);
|
||||
});
|
||||
describe('#setProvider', () => {
|
||||
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
|
||||
// Instantiate the contract instances with the current provider
|
||||
@@ -30,22 +35,21 @@ describe('ZeroEx library', () => {
|
||||
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
|
||||
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
|
||||
|
||||
const newProvider = web3Factory.getRpcProvider();
|
||||
// Add property to newProvider so that we can differentiate it from old provider
|
||||
(newProvider as any).zeroExTestId = 1;
|
||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||
(provider as any).zeroExTestId = 1;
|
||||
zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID);
|
||||
|
||||
// Check that contractInstances with old provider are removed after provider update
|
||||
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined();
|
||||
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
|
||||
|
||||
// Check that all nested web3 wrapper instances return the updated provider
|
||||
const nestedWeb3WrapperProvider = (zeroEx as any)._web3Wrapper.getCurrentProvider();
|
||||
expect((nestedWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
||||
const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getCurrentProvider();
|
||||
expect((exchangeWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
||||
const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getCurrentProvider();
|
||||
expect((tokenRegistryWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
||||
// Check that all nested zeroExContract/web3Wrapper instances return the updated provider
|
||||
const nestedWeb3WrapperProvider = ((zeroEx as any)._contractWrappers as ContractWrappers).getProvider();
|
||||
expect((nestedWeb3WrapperProvider as any).zeroExTestId).to.be.a('number');
|
||||
const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getProvider();
|
||||
expect(exchangeWeb3WrapperProvider.zeroExTestId).to.be.a('number');
|
||||
const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getProvider();
|
||||
expect(tokenRegistryWeb3WrapperProvider.zeroExTestId).to.be.a('number');
|
||||
});
|
||||
});
|
||||
describe('#isValidSignature', () => {
|
||||
@@ -58,67 +62,40 @@ describe('ZeroEx library', () => {
|
||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||
};
|
||||
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||
it('should return false if the data doesn\'t pertain to the signature & address', async () => {
|
||||
expect(ZeroEx.isValidSignature('0x0', signature, address)).to.be.false();
|
||||
it("should return false if the data doesn't pertain to the signature & address", async () => {
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
|
||||
).to.become(false);
|
||||
});
|
||||
it('should return false if the address doesn\'t pertain to the signature & data', async () => {
|
||||
it("should return false if the address doesn't pertain to the signature & data", async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
|
||||
expect(ZeroEx.isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature,
|
||||
validUnrelatedAddress),
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
|
||||
dataHex,
|
||||
signature,
|
||||
validUnrelatedAddress,
|
||||
),
|
||||
).to.become(false);
|
||||
});
|
||||
it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => {
|
||||
const wrongSignature = _.assign({}, signature, {v: 28});
|
||||
expect(ZeroEx.isValidSignature(dataHex, wrongSignature, address)).to.be.false();
|
||||
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
|
||||
const wrongSignature = _.assign({}, signature, { v: 28 });
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
|
||||
).to.become(false);
|
||||
});
|
||||
it('should return true if the signature does pertain to the dataHex & address', async () => {
|
||||
const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address);
|
||||
expect(isValidSignatureLocal).to.be.true();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address),
|
||||
).to.become(true);
|
||||
});
|
||||
});
|
||||
describe('#generateSalt', () => {
|
||||
it('generates different salts', () => {
|
||||
const equal = ZeroEx.generatePseudoRandomSalt().eq(ZeroEx.generatePseudoRandomSalt());
|
||||
expect(equal).to.be.false();
|
||||
});
|
||||
it('generates salt in range [0..2^256)', () => {
|
||||
const salt = ZeroEx.generatePseudoRandomSalt();
|
||||
expect(salt.greaterThanOrEqualTo(0)).to.be.true();
|
||||
const twoPow256 = new BigNumber(2).pow(256);
|
||||
expect(salt.lessThan(twoPow256)).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#isValidOrderHash', () => {
|
||||
it('returns false if the value is not a hex string', () => {
|
||||
const isValid = ZeroEx.isValidOrderHash('not a hex');
|
||||
expect(isValid).to.be.false();
|
||||
});
|
||||
it('returns false if the length is wrong', () => {
|
||||
const isValid = ZeroEx.isValidOrderHash('0xdeadbeef');
|
||||
expect(isValid).to.be.false();
|
||||
});
|
||||
it('returns true if order hash is correct', () => {
|
||||
const isValid = ZeroEx.isValidOrderHash('0x' + Array(65).join('0'));
|
||||
expect(isValid).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#toUnitAmount', () => {
|
||||
it('should throw if invalid baseUnit amount supplied as argument', () => {
|
||||
const invalidBaseUnitAmount = new BigNumber(1000000000.4);
|
||||
const decimals = 6;
|
||||
expect(() => ZeroEx.toUnitAmount(invalidBaseUnitAmount, decimals))
|
||||
.to.throw('amount should be in baseUnits (no decimals), found value: 1000000000.4');
|
||||
expect(() => ZeroEx.toUnitAmount(invalidBaseUnitAmount, decimals)).to.throw(
|
||||
'amount should be in baseUnits (no decimals), found value: 1000000000.4',
|
||||
);
|
||||
});
|
||||
it('Should return the expected unit amount for the decimals passed in', () => {
|
||||
const baseUnitAmount = new BigNumber(1000000000);
|
||||
@@ -139,98 +116,9 @@ describe('ZeroEx library', () => {
|
||||
it('should throw if unitAmount has more decimals then specified as the max decimal precision', () => {
|
||||
const unitAmount = new BigNumber(0.823091);
|
||||
const decimals = 5;
|
||||
expect(() => ZeroEx.toBaseUnitAmount(unitAmount, decimals))
|
||||
.to.throw('Invalid unit amount: 0.823091 - Too many decimal places');
|
||||
});
|
||||
});
|
||||
describe('#getOrderHashHex', () => {
|
||||
const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';
|
||||
const fakeExchangeContractAddress = '0xb69e673309512a9d726f87304c6984054f87a93b';
|
||||
const order: Order = {
|
||||
maker: constants.NULL_ADDRESS,
|
||||
taker: constants.NULL_ADDRESS,
|
||||
feeRecipient: constants.NULL_ADDRESS,
|
||||
makerTokenAddress: constants.NULL_ADDRESS,
|
||||
takerTokenAddress: constants.NULL_ADDRESS,
|
||||
exchangeContractAddress: fakeExchangeContractAddress,
|
||||
salt: new BigNumber(0),
|
||||
makerFee: new BigNumber(0),
|
||||
takerFee: new BigNumber(0),
|
||||
makerTokenAmount: new BigNumber(0),
|
||||
takerTokenAmount: new BigNumber(0),
|
||||
expirationUnixTimestampSec: new BigNumber(0),
|
||||
};
|
||||
it('calculates the order hash', async () => {
|
||||
const orderHash = ZeroEx.getOrderHashHex(order);
|
||||
expect(orderHash).to.be.equal(expectedOrderHash);
|
||||
});
|
||||
it('throws a readable error message if taker format is invalid', async () => {
|
||||
const orderWithInvalidtakerFormat = {
|
||||
...order,
|
||||
taker: null as any as string,
|
||||
};
|
||||
// tslint:disable-next-line:max-line-length
|
||||
const expectedErrorMessage = 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
expect(() => ZeroEx.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
|
||||
});
|
||||
});
|
||||
describe('#signOrderHashAsync', () => {
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
let makerAddress: string;
|
||||
before(async () => {
|
||||
const availableAddreses = await zeroEx.getAvailableAddressesAsync();
|
||||
makerAddress = availableAddreses[0];
|
||||
});
|
||||
afterEach(() => {
|
||||
// clean up any stubs after the test has completed
|
||||
_.each(stubs, s => s.restore());
|
||||
stubs = [];
|
||||
});
|
||||
it('Should return the correct ECSignature', async () => {
|
||||
const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||
};
|
||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
|
||||
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
|
||||
// tslint:disable-next-line: max-line-length
|
||||
const signature = '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3',
|
||||
s: '0x050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb02',
|
||||
};
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync')
|
||||
.returns(Promise.resolve(signature)),
|
||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
||||
];
|
||||
|
||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
});
|
||||
it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
|
||||
const orderHash = '0xc793e33ffded933b76f2f48d9aa3339fc090399d5e7f5dec8d3660f5480793f7';
|
||||
// tslint:disable-next-line: max-line-length
|
||||
const signature = '0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
|
||||
const expectedECSignature = {
|
||||
v: 27,
|
||||
r: '0xc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee0',
|
||||
s: '0x2dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960',
|
||||
};
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync')
|
||||
.returns(Promise.resolve(signature)),
|
||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
||||
];
|
||||
|
||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
|
||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||
expect(() => ZeroEx.toBaseUnitAmount(unitAmount, decimals)).to.throw(
|
||||
'Invalid unit amount: 0.823091 - Too many decimal places',
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('#awaitTransactionMinedAsync', () => {
|
||||
@@ -262,7 +150,7 @@ describe('ZeroEx library', () => {
|
||||
exchangeContractAddress: ZeroEx.NULL_ADDRESS,
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const zeroExWithWrongExchangeAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||
const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig);
|
||||
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
|
||||
});
|
||||
it('allows to specify token registry token contract address', async () => {
|
||||
@@ -270,9 +158,10 @@ describe('ZeroEx library', () => {
|
||||
tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS,
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress())
|
||||
.to.be.equal(ZeroEx.NULL_ADDRESS);
|
||||
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(provider, zeroExConfig);
|
||||
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal(
|
||||
ZeroEx.NULL_ADDRESS,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { web3Factory } from '@0xproject/dev-utils';
|
||||
import * as fs from 'fs';
|
||||
import HDWalletProvider = require('truffle-hdwallet-provider');
|
||||
import 'make-promises-safe';
|
||||
|
||||
import {ZeroEx} from '../src';
|
||||
import { ZeroEx } from '../src';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
|
||||
chaiSetup.configure();
|
||||
|
||||
@@ -14,14 +15,11 @@ const TIMEOUT = 10000;
|
||||
describe('Artifacts', () => {
|
||||
describe('contracts are deployed on kovan', () => {
|
||||
const kovanRpcUrl = constants.KOVAN_RPC_URL;
|
||||
const packageJSONContent = fs.readFileSync('package.json', 'utf-8');
|
||||
const packageJSON = JSON.parse(packageJSONContent);
|
||||
const mnemonic = packageJSON.config.mnemonic;
|
||||
const web3Provider = new HDWalletProvider(mnemonic, kovanRpcUrl);
|
||||
const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider;
|
||||
const config = {
|
||||
networkId: constants.KOVAN_NETWORK_ID,
|
||||
};
|
||||
const zeroEx = new ZeroEx(web3Provider, config);
|
||||
const zeroEx = new ZeroEx(provider, config);
|
||||
it('token registry contract is deployed', async () => {
|
||||
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
|
||||
}).timeout(TIMEOUT);
|
||||
@@ -34,14 +32,11 @@ describe('Artifacts', () => {
|
||||
});
|
||||
describe('contracts are deployed on ropsten', () => {
|
||||
const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
|
||||
const packageJSONContent = fs.readFileSync('package.json', 'utf-8');
|
||||
const packageJSON = JSON.parse(packageJSONContent);
|
||||
const mnemonic = packageJSON.config.mnemonic;
|
||||
const web3Provider = new HDWalletProvider(mnemonic, ropstenRpcUrl);
|
||||
const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider;
|
||||
const config = {
|
||||
networkId: constants.ROPSTEN_NETWORK_ID,
|
||||
};
|
||||
const zeroEx = new ZeroEx(web3Provider, config);
|
||||
const zeroEx = new ZeroEx(provider, config);
|
||||
it('token registry contract is deployed', async () => {
|
||||
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
|
||||
}).timeout(TIMEOUT);
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import {ZeroEx} from '../src';
|
||||
import {assert} from '../src/utils/assert';
|
||||
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('Assertion library', () => {
|
||||
const web3 = web3Factory.create();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
describe('#isSenderAddressHexAsync', () => {
|
||||
it('throws when address is invalid', async () => {
|
||||
const address = '0xdeadbeef';
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, address, (zeroEx as any)._web3Wrapper))
|
||||
.to.be.rejectedWith(`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`);
|
||||
});
|
||||
it('throws when address is unavailable', async () => {
|
||||
const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper))
|
||||
.to.be.rejectedWith(
|
||||
`Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
|
||||
);
|
||||
});
|
||||
it('doesn\'t throw if address is available', async () => {
|
||||
const availableAddress = (await zeroEx.getAvailableAddressesAsync())[0];
|
||||
const varName = 'address';
|
||||
return expect(assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper))
|
||||
.to.become(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,343 +0,0 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
ApprovalContractEventArgs,
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
DecodedLogEvent,
|
||||
DepositContractEventArgs,
|
||||
EtherTokenEvents,
|
||||
Token,
|
||||
TransferContractEventArgs,
|
||||
WithdrawalContractEventArgs,
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {artifacts} from '../src/artifacts';
|
||||
import {DoneCallback} from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
// Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction,
|
||||
// a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between
|
||||
// the expected balance and actual balance (given the amount of ETH deposited), only deviates by the amount
|
||||
// required to pay gas costs.
|
||||
const MAX_REASONABLE_GAS_COST_IN_WEI = 62517;
|
||||
|
||||
describe('EtherTokenWrapper', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let tokens: Token[];
|
||||
let userAddresses: string[];
|
||||
let addressWithETH: string;
|
||||
let wethContractAddress: string;
|
||||
let depositWeiAmount: BigNumber;
|
||||
let decimalPlaces: number;
|
||||
let addressWithoutFunds: string;
|
||||
const gasPrice = new BigNumber(1);
|
||||
const zeroExConfig = {
|
||||
gasPrice,
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const transferAmount = new BigNumber(42);
|
||||
const allowanceAmount = new BigNumber(42);
|
||||
const depositAmount = new BigNumber(42);
|
||||
const withdrawalAmount = new BigNumber(42);
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
addressWithETH = userAddresses[0];
|
||||
wethContractAddress = (zeroEx.etherToken as any)._getContractAddress(artifacts.EtherTokenArtifact);
|
||||
depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(new BigNumber(5));
|
||||
decimalPlaces = 7;
|
||||
addressWithoutFunds = userAddresses[1];
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#depositAsync', () => {
|
||||
it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => {
|
||||
const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
||||
expect(preETHBalance).to.be.bignumber.gt(0);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(0);
|
||||
|
||||
const txHash = await zeroEx.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const postETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
||||
|
||||
expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(depositWeiAmount);
|
||||
const remainingETHInWei = preETHBalance.minus(depositWeiAmount);
|
||||
const gasCost = remainingETHInWei.minus(postETHBalanceInWei);
|
||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||
});
|
||||
it('should throw if user has insufficient ETH balance for deposit', async () => {
|
||||
const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
|
||||
const extraETHBalance = (zeroEx as any)._web3Wrapper.toWei(5, 'ether');
|
||||
const overETHBalanceinWei = preETHBalance.add(extraETHBalance);
|
||||
|
||||
return expect(
|
||||
zeroEx.etherToken.depositAsync(wethContractAddress, overETHBalanceinWei, addressWithETH),
|
||||
).to.be.rejectedWith(ZeroExError.InsufficientEthBalanceForDeposit);
|
||||
});
|
||||
});
|
||||
describe('#withdrawAsync', () => {
|
||||
it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => {
|
||||
const ETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
|
||||
await zeroEx.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH);
|
||||
|
||||
const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount);
|
||||
const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
||||
let gasCost = expectedPreETHBalance.minus(preETHBalance);
|
||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount);
|
||||
|
||||
const txHash = await zeroEx.etherToken.withdrawAsync(wethContractAddress, depositWeiAmount, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
||||
|
||||
expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(0);
|
||||
const expectedETHBalance = preETHBalance.add(depositWeiAmount).round(decimalPlaces);
|
||||
gasCost = expectedETHBalance.minus(postETHBalance);
|
||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||
});
|
||||
it('should throw if user has insufficient WETH balance for withdrawl', async () => {
|
||||
const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(0);
|
||||
|
||||
const overWETHBalance = preWETHBalance.add(999999999);
|
||||
|
||||
return expect(
|
||||
zeroEx.etherToken.withdrawAsync(wethContractAddress, overWETHBalance, addressWithETH),
|
||||
).to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal);
|
||||
});
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
let etherTokenAddress: string;
|
||||
before(() => {
|
||||
const tokenUtils = new TokenUtils(tokens);
|
||||
const etherToken = tokenUtils.getWethTokenOrThrow();
|
||||
etherTokenAddress = etherToken.address;
|
||||
});
|
||||
afterEach(() => {
|
||||
zeroEx.etherToken.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
// we do need both. A hack is to make the top-level async fn w/ a done callback and then
|
||||
// wrap the rest of the test in an async block
|
||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
|
||||
expect(err).to.be.null();
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
expect(logEvent.log.logIndex).to.be.equal(0);
|
||||
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
||||
expect(logEvent.log.blockNumber).to.be.a('number');
|
||||
const args = logEvent.log.args;
|
||||
expect(args._from).to.be.equal(addressWithETH);
|
||||
expect(args._to).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(transferAmount);
|
||||
done();
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
expect(err).to.be.null();
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._spender).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, allowanceAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<DepositContractEventArgs>) => {
|
||||
expect(err).to.be.null();
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback);
|
||||
await zeroEx.etherToken.depositAsync(
|
||||
etherTokenAddress, depositAmount, addressWithETH,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<WithdrawalContractEventArgs>) => {
|
||||
expect(err).to.be.null();
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
done();
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(
|
||||
etherTokenAddress, depositAmount, addressWithETH,
|
||||
);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Withdrawal, indexFilterValues, callback);
|
||||
await zeroEx.etherToken.withdrawAsync(
|
||||
etherTokenAddress, withdrawalAmount, addressWithETH,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled,
|
||||
);
|
||||
const callbackToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done();
|
||||
};
|
||||
const newProvider = web3Factory.getRpcProvider();
|
||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackToBeCalled,
|
||||
);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
const subscriptionToken = zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
||||
zeroEx.etherToken.unsubscribe(subscriptionToken);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
describe('#getLogsAsync', () => {
|
||||
let etherTokenAddress: string;
|
||||
let tokenTransferProxyAddress: string;
|
||||
const blockRange: BlockRange = {
|
||||
fromBlock: 0,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
let txHash: string;
|
||||
before(() => {
|
||||
addressWithETH = userAddresses[0];
|
||||
const tokenUtils = new TokenUtils(tokens);
|
||||
const etherToken = tokenUtils.getWethTokenOrThrow();
|
||||
etherTokenAddress = etherToken.address;
|
||||
tokenTransferProxyAddress = zeroEx.proxy.getContractAddress();
|
||||
});
|
||||
it('should get logs with decoded args emitted by Approval', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = EtherTokenEvents.Approval;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._spender).to.be.equal(tokenTransferProxyAddress);
|
||||
expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
it('should get logs with decoded args emitted by Deposit', async () => {
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||
const eventName = EtherTokenEvents.Deposit;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<DepositContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const differentEventName = EtherTokenEvents.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync(
|
||||
etherTokenAddress, differentEventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithoutFunds);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = EtherTokenEvents.Approval;
|
||||
const indexFilterValues = {
|
||||
_owner: addressWithETH,
|
||||
};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,125 +0,0 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
LogEvent,
|
||||
} from '../src';
|
||||
import {EventWatcher} from '../src/order_watcher/event_watcher';
|
||||
import {DoneCallback} from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('EventWatcher', () => {
|
||||
let web3: Web3;
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
let eventWatcher: EventWatcher;
|
||||
let web3Wrapper: Web3Wrapper;
|
||||
const logA: Web3.LogEntry = {
|
||||
address: '0x71d271f8b14adef568f8f28f1587ce7271ac4ca5',
|
||||
blockHash: null,
|
||||
blockNumber: null,
|
||||
data: '',
|
||||
logIndex: null,
|
||||
topics: [],
|
||||
transactionHash: '0x004881d38cd4a8f72f1a0d68c8b9b8124504706041ff37019c1d1ed6bfda8e17',
|
||||
transactionIndex: 0,
|
||||
};
|
||||
const logB: Web3.LogEntry = {
|
||||
address: '0x8d12a197cb00d4747a1fe03395095ce2a5cc6819',
|
||||
blockHash: null,
|
||||
blockNumber: null,
|
||||
data: '',
|
||||
logIndex: null,
|
||||
topics: [ '0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567' ],
|
||||
transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
|
||||
transactionIndex: 0,
|
||||
};
|
||||
const logC: Web3.LogEntry = {
|
||||
address: '0x1d271f8b174adef58f1587ce68f8f27271ac4ca5',
|
||||
blockHash: null,
|
||||
blockNumber: null,
|
||||
data: '',
|
||||
logIndex: null,
|
||||
topics: [ '0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567' ],
|
||||
transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
|
||||
transactionIndex: 0,
|
||||
};
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
const pollingIntervalMs = 10;
|
||||
web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
||||
eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalMs);
|
||||
});
|
||||
afterEach(() => {
|
||||
// clean up any stubs after the test has completed
|
||||
_.each(stubs, s => s.restore());
|
||||
stubs = [];
|
||||
eventWatcher.unsubscribe();
|
||||
});
|
||||
it('correctly emits initial log events', (done: DoneCallback) => {
|
||||
const logs: Web3.LogEntry[] = [logA, logB];
|
||||
const expectedLogEvents = [
|
||||
{
|
||||
removed: false,
|
||||
...logA,
|
||||
},
|
||||
{
|
||||
removed: false,
|
||||
...logB,
|
||||
},
|
||||
];
|
||||
const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
|
||||
getLogsStub.onCall(0).returns(logs);
|
||||
stubs.push(getLogsStub);
|
||||
const callback = (event: LogEvent) => {
|
||||
const expectedLogEvent = expectedLogEvents.shift();
|
||||
expect(event).to.be.deep.equal(expectedLogEvent);
|
||||
if (_.isEmpty(expectedLogEvents)) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
eventWatcher.subscribe(callback);
|
||||
});
|
||||
it('correctly computes the difference and emits only changes', (done: DoneCallback) => {
|
||||
const initialLogs: Web3.LogEntry[] = [logA, logB];
|
||||
const changedLogs: Web3.LogEntry[] = [logA, logC];
|
||||
const expectedLogEvents = [
|
||||
{
|
||||
removed: false,
|
||||
...logA,
|
||||
},
|
||||
{
|
||||
removed: false,
|
||||
...logB,
|
||||
},
|
||||
{
|
||||
removed: true,
|
||||
...logB,
|
||||
},
|
||||
{
|
||||
removed: false,
|
||||
...logC,
|
||||
},
|
||||
];
|
||||
const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
|
||||
getLogsStub.onCall(0).returns(initialLogs);
|
||||
getLogsStub.onCall(1).returns(changedLogs);
|
||||
stubs.push(getLogsStub);
|
||||
const callback = (event: LogEvent) => {
|
||||
const expectedLogEvent = expectedLogEvents.shift();
|
||||
expect(event).to.be.deep.equal(expectedLogEvent);
|
||||
if (_.isEmpty(expectedLogEvents)) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
eventWatcher.subscribe(callback);
|
||||
});
|
||||
});
|
||||
@@ -1,93 +0,0 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
|
||||
import {ExchangeContractErrs, Token, ZeroEx} from '../src';
|
||||
import {BlockParamLiteral, TradeSide, TransferType} from '../src/types';
|
||||
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('ExchangeTransferSimulator', () => {
|
||||
const web3 = web3Factory.create();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
const transferAmount = new BigNumber(5);
|
||||
let userAddresses: string[];
|
||||
let tokens: Token[];
|
||||
let coinbase: string;
|
||||
let sender: string;
|
||||
let recipient: string;
|
||||
let exampleTokenAddress: string;
|
||||
let exchangeTransferSimulator: ExchangeTransferSimulator;
|
||||
let txHash: string;
|
||||
before(async () => {
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
[coinbase, sender, recipient] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
exampleTokenAddress = tokens[0].address;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#transferFromAsync', () => {
|
||||
beforeEach(() => {
|
||||
exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest);
|
||||
});
|
||||
it('throws if the user doesn\'t have enough allowance', async () => {
|
||||
return expect(exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance);
|
||||
});
|
||||
it('throws if the user doesn\'t have enough balance', async () => {
|
||||
txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
return expect(exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Maker, TransferType.Trade,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
|
||||
});
|
||||
it('updates balances and proxyAllowance after transfer', async () => {
|
||||
txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
await exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
||||
);
|
||||
const store = (exchangeTransferSimulator as any)._store;
|
||||
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
||||
const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
|
||||
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
|
||||
expect(senderBalance).to.be.bignumber.equal(0);
|
||||
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
|
||||
expect(senderProxyAllowance).to.be.bignumber.equal(0);
|
||||
});
|
||||
it('doesn\'t update proxyAllowance after transfer if unlimited', async () => {
|
||||
txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
await exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
||||
);
|
||||
const store = (exchangeTransferSimulator as any)._store;
|
||||
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
||||
const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
|
||||
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
|
||||
expect(senderBalance).to.be.bignumber.equal(0);
|
||||
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
|
||||
expect(senderProxyAllowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,831 +0,0 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
BlockRange,
|
||||
DecodedLogEvent,
|
||||
ExchangeContractErrs,
|
||||
ExchangeEvents,
|
||||
LogCancelContractEventArgs,
|
||||
LogFillContractEventArgs,
|
||||
OrderCancellationRequest,
|
||||
OrderFillRequest,
|
||||
SignedOrder,
|
||||
Token,
|
||||
ZeroEx,
|
||||
} from '../src';
|
||||
import {BlockParamLiteral, DoneCallback} from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
const NON_EXISTENT_ORDER_HASH = '0x79370342234e7acd6bbeac335bd3bb1d368383294b64b8160a00f4060e4d3777';
|
||||
|
||||
describe('ExchangeWrapper', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let tokenUtils: TokenUtils;
|
||||
let tokens: Token[];
|
||||
let userAddresses: string[];
|
||||
let zrxTokenAddress: string;
|
||||
let fillScenarios: FillScenarios;
|
||||
let exchangeContractAddress: string;
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
await fillScenarios.initTokenBalancesAsync();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('fillOrKill order(s)', () => {
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let coinbase: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let feeRecipient: string;
|
||||
const takerTokenFillAmount = new BigNumber(5);
|
||||
before(async () => {
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
describe('#batchFillOrKillAsync', () => {
|
||||
it('successfully batch fillOrKill', async () => {
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const partialFillTakerAmount = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const orderFillRequests = [
|
||||
{
|
||||
signedOrder,
|
||||
takerTokenFillAmount: partialFillTakerAmount,
|
||||
},
|
||||
{
|
||||
signedOrder: anotherSignedOrder,
|
||||
takerTokenFillAmount: partialFillTakerAmount,
|
||||
},
|
||||
];
|
||||
await zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress);
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
let signedOrder: SignedOrder;
|
||||
let orderFillRequests: OrderFillRequest[];
|
||||
const fillableAmount = new BigNumber(5);
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
orderFillRequests = [
|
||||
{
|
||||
signedOrder,
|
||||
takerTokenFillAmount: new BigNumber(0),
|
||||
},
|
||||
];
|
||||
});
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#fillOrKillOrderAsync', () => {
|
||||
let signedOrder: SignedOrder;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
});
|
||||
describe('successful fills', () => {
|
||||
it('should fill a valid order', async () => {
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
|
||||
});
|
||||
it('should partially fill a valid order', async () => {
|
||||
const partialFillAmount = new BigNumber(3);
|
||||
await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, partialFillAmount, takerAddress);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(partialFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(partialFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
});
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
const emptyFillableAmount = new BigNumber(0);
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('fill order(s)', () => {
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let coinbase: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let feeRecipient: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const takerTokenFillAmount = new BigNumber(5);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
before(async () => {
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
describe('#fillOrderAsync', () => {
|
||||
describe('successful fills', () => {
|
||||
it('should fill a valid order', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(0);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount);
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount));
|
||||
});
|
||||
it('should partially fill the valid order', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const partialFillAmount = new BigNumber(3);
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress))
|
||||
.to.be.bignumber.equal(partialFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(partialFillAmount);
|
||||
expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress))
|
||||
.to.be.bignumber.equal(fillableAmount.minus(partialFillAmount));
|
||||
});
|
||||
it('should fill the valid orders with fees', async () => {
|
||||
const makerFee = new BigNumber(1);
|
||||
const takerFee = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
|
||||
makerAddress, takerAddress, fillableAmount, feeRecipient,
|
||||
);
|
||||
const txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient))
|
||||
.to.be.bignumber.equal(makerFee.plus(takerFee));
|
||||
});
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
let signedOrder: SignedOrder;
|
||||
const emptyFillTakerAmount = new BigNumber(0);
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
});
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#batchFillOrdersAsync', () => {
|
||||
let signedOrder: SignedOrder;
|
||||
let signedOrderHashHex: string;
|
||||
let anotherSignedOrder: SignedOrder;
|
||||
let anotherOrderHashHex: string;
|
||||
let orderFillBatch: OrderFillRequest[];
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder);
|
||||
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
|
||||
});
|
||||
describe('successful batch fills', () => {
|
||||
beforeEach(() => {
|
||||
orderFillBatch = [
|
||||
{
|
||||
signedOrder,
|
||||
takerTokenFillAmount,
|
||||
},
|
||||
{
|
||||
signedOrder: anotherSignedOrder,
|
||||
takerTokenFillAmount,
|
||||
},
|
||||
];
|
||||
});
|
||||
it('should throw if a batch is empty', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
[], shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
});
|
||||
it('should successfully fill multiple orders', async () => {
|
||||
const txHash = await zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
|
||||
expect(filledAmount).to.be.bignumber.equal(takerTokenFillAmount);
|
||||
expect(anotherFilledAmount).to.be.bignumber.equal(takerTokenFillAmount);
|
||||
});
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
beforeEach(async () => {
|
||||
const emptyFillTakerAmount = new BigNumber(0);
|
||||
orderFillBatch = [
|
||||
{
|
||||
signedOrder,
|
||||
takerTokenFillAmount: emptyFillTakerAmount,
|
||||
},
|
||||
{
|
||||
signedOrder: anotherSignedOrder,
|
||||
takerTokenFillAmount: emptyFillTakerAmount,
|
||||
},
|
||||
];
|
||||
});
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchFillOrdersAsync(
|
||||
orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#fillOrdersUpTo', () => {
|
||||
let signedOrder: SignedOrder;
|
||||
let signedOrderHashHex: string;
|
||||
let anotherSignedOrder: SignedOrder;
|
||||
let anotherOrderHashHex: string;
|
||||
let signedOrders: SignedOrder[];
|
||||
const fillUpToAmount = fillableAmount.plus(fillableAmount).minus(1);
|
||||
beforeEach(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder);
|
||||
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
|
||||
signedOrders = [signedOrder, anotherSignedOrder];
|
||||
});
|
||||
describe('successful batch fills', () => {
|
||||
it('should throw if a batch is empty', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
[], fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress),
|
||||
).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
});
|
||||
it('should successfully fill up to specified amount', async () => {
|
||||
const txHash = await zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
|
||||
expect(filledAmount).to.be.bignumber.equal(fillableAmount);
|
||||
const remainingFillAmount = fillableAmount.minus(1);
|
||||
expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount);
|
||||
});
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
const emptyFillUpToAmount = new BigNumber(0);
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('cancel order(s)', () => {
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let coinbase: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
let signedOrder: SignedOrder;
|
||||
let orderHashHex: string;
|
||||
const cancelAmount = new BigNumber(3);
|
||||
beforeEach(async () => {
|
||||
[coinbase, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
orderHashHex = ZeroEx.getOrderHashHex(signedOrder);
|
||||
});
|
||||
describe('#cancelOrderAsync', () => {
|
||||
describe('successful cancels', () => {
|
||||
it('should cancel an order', async () => {
|
||||
const txHash = await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const cancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHashHex);
|
||||
expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
|
||||
});
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
const emptyCancelTakerTokenAmount = new BigNumber(0);
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#batchCancelOrdersAsync', () => {
|
||||
let anotherSignedOrder: SignedOrder;
|
||||
let anotherOrderHashHex: string;
|
||||
let cancelBatch: OrderCancellationRequest[];
|
||||
beforeEach(async () => {
|
||||
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder);
|
||||
cancelBatch = [
|
||||
{
|
||||
order: signedOrder,
|
||||
takerTokenCancelAmount: cancelAmount,
|
||||
},
|
||||
{
|
||||
order: anotherSignedOrder,
|
||||
takerTokenCancelAmount: cancelAmount,
|
||||
},
|
||||
];
|
||||
});
|
||||
describe('failed batch cancels', () => {
|
||||
it('should throw when orders have different makers', async () => {
|
||||
const signedOrderWithDifferentMaker = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, takerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync([
|
||||
cancelBatch[0],
|
||||
{
|
||||
order: signedOrderWithDifferentMaker,
|
||||
takerTokenCancelAmount: cancelAmount,
|
||||
},
|
||||
])).to.be.rejectedWith(ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
|
||||
});
|
||||
});
|
||||
describe('successful batch cancels', () => {
|
||||
it('should cancel a batch of orders', async () => {
|
||||
await zeroEx.exchange.batchCancelOrdersAsync(cancelBatch);
|
||||
const cancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHashHex);
|
||||
const anotherCancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync(
|
||||
anotherOrderHashHex,
|
||||
);
|
||||
expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
|
||||
expect(anotherCancelledAmount).to.be.bignumber.equal(cancelAmount);
|
||||
});
|
||||
});
|
||||
describe('order transaction options', () => {
|
||||
beforeEach(async () => {
|
||||
const emptyTakerTokenCancelAmount = new BigNumber(0);
|
||||
cancelBatch = [
|
||||
{
|
||||
order: signedOrder,
|
||||
takerTokenCancelAmount: emptyTakerTokenCancelAmount,
|
||||
},
|
||||
{
|
||||
order: anotherSignedOrder,
|
||||
takerTokenCancelAmount: emptyTakerTokenCancelAmount,
|
||||
},
|
||||
];
|
||||
});
|
||||
it('should validate when orderTransactionOptions are not present', async () => {
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should validate when orderTransactionOptions specify to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
|
||||
shouldValidate: true,
|
||||
})).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should not validate when orderTransactionOptions specify not to validate', async () => {
|
||||
return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, {
|
||||
shouldValidate: false,
|
||||
})).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('tests that require partially filled order', () => {
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let takerAddress: string;
|
||||
let fillableAmount: BigNumber;
|
||||
let partialFillAmount: BigNumber;
|
||||
let signedOrder: SignedOrder;
|
||||
let orderHash: string;
|
||||
before(() => {
|
||||
takerAddress = userAddresses[1];
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
fillableAmount = new BigNumber(5);
|
||||
partialFillAmount = new BigNumber(2);
|
||||
signedOrder = await fillScenarios.createPartiallyFilledSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, takerAddress, fillableAmount, partialFillAmount,
|
||||
);
|
||||
orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
});
|
||||
describe('#getUnavailableTakerAmountAsync', () => {
|
||||
it('should throw if passed an invalid orderHash', async () => {
|
||||
const invalidOrderHashHex = '0x123';
|
||||
return expect(zeroEx.exchange.getUnavailableTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
|
||||
});
|
||||
it('should return zero if passed a valid but non-existent orderHash', async () => {
|
||||
const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
|
||||
expect(unavailableValueT).to.be.bignumber.equal(0);
|
||||
});
|
||||
it('should return the unavailableValueT for a valid and partially filled orderHash', async () => {
|
||||
const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash);
|
||||
expect(unavailableValueT).to.be.bignumber.equal(partialFillAmount);
|
||||
});
|
||||
});
|
||||
describe('#getFilledTakerAmountAsync', () => {
|
||||
it('should throw if passed an invalid orderHash', async () => {
|
||||
const invalidOrderHashHex = '0x123';
|
||||
return expect(zeroEx.exchange.getFilledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
|
||||
});
|
||||
it('should return zero if passed a valid but non-existent orderHash', async () => {
|
||||
const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(NON_EXISTENT_ORDER_HASH,
|
||||
);
|
||||
expect(filledValueT).to.be.bignumber.equal(0);
|
||||
});
|
||||
it('should return the filledValueT for a valid and partially filled orderHash', async () => {
|
||||
const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(orderHash);
|
||||
expect(filledValueT).to.be.bignumber.equal(partialFillAmount);
|
||||
});
|
||||
});
|
||||
describe('#getCancelledTakerAmountAsync', () => {
|
||||
it('should throw if passed an invalid orderHash', async () => {
|
||||
const invalidOrderHashHex = '0x123';
|
||||
return expect(zeroEx.exchange.getCancelledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected();
|
||||
});
|
||||
it('should return zero if passed a valid but non-existent orderHash', async () => {
|
||||
const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(NON_EXISTENT_ORDER_HASH);
|
||||
expect(cancelledValueT).to.be.bignumber.equal(0);
|
||||
});
|
||||
it('should return the cancelledValueT for a valid and partially filled orderHash', async () => {
|
||||
const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHash);
|
||||
expect(cancelledValueT).to.be.bignumber.equal(0);
|
||||
});
|
||||
it('should return the cancelledValueT for a valid and cancelled orderHash', async () => {
|
||||
const cancelAmount = fillableAmount.minus(partialFillAmount);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
|
||||
const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHash);
|
||||
expect(cancelledValueT).to.be.bignumber.equal(cancelAmount);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let coinbase: string;
|
||||
let takerAddress: string;
|
||||
let makerAddress: string;
|
||||
let fillableAmount: BigNumber;
|
||||
let signedOrder: SignedOrder;
|
||||
const takerTokenFillAmountInBaseUnits = new BigNumber(1);
|
||||
const cancelTakerAmountInBaseUnits = new BigNumber(1);
|
||||
before(() => {
|
||||
[coinbase, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
fillableAmount = new BigNumber(5);
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
});
|
||||
afterEach(async () => {
|
||||
zeroEx.exchange.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
// we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
|
||||
// wrap the rest of the test in an async block
|
||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||
it('Should receive the LogFill event when an order is filled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
|
||||
expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogFill);
|
||||
done();
|
||||
};
|
||||
zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogFill, indexFilterValues, callback,
|
||||
);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<LogCancelContractEventArgs>) => {
|
||||
expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogCancel);
|
||||
done();
|
||||
};
|
||||
zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogCancel, indexFilterValues, callback,
|
||||
);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled,
|
||||
);
|
||||
|
||||
const newProvider = web3Factory.getRpcProvider();
|
||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
|
||||
expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogFill);
|
||||
done();
|
||||
};
|
||||
zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogFill, indexFilterValues, callback,
|
||||
);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
const subscriptionToken = zeroEx.exchange.subscribe(
|
||||
ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled,
|
||||
);
|
||||
zeroEx.exchange.unsubscribe(subscriptionToken);
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance,
|
||||
takerAddress,
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
describe('#getOrderHashHexUsingContractCallAsync', () => {
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
before(async () => {
|
||||
[, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
it('get\'s the same hash as the local function', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
const orderHashFromContract = await (zeroEx.exchange as any)
|
||||
._getOrderHashHexUsingContractCallAsync(signedOrder);
|
||||
expect(orderHash).to.equal(orderHashFromContract);
|
||||
});
|
||||
});
|
||||
describe('#getZRXTokenAddressAsync', () => {
|
||||
it('gets the same token as is in token registry', () => {
|
||||
const zrxAddress = zeroEx.exchange.getZRXTokenAddress();
|
||||
const zrxToken = tokenUtils.getProtocolTokenOrThrow();
|
||||
expect(zrxAddress).to.equal(zrxToken.address);
|
||||
});
|
||||
});
|
||||
describe('#getLogsAsync', () => {
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
const blockRange: BlockRange = {
|
||||
fromBlock: 0,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
let txHash: string;
|
||||
before(async () => {
|
||||
[, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
it('should get logs with decoded args emitted by LogFill', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = ExchangeEvents.LogFill;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.exchange.getLogsAsync(eventName, blockRange, indexFilterValues);
|
||||
expect(logs).to.have.length(1);
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const differentEventName = ExchangeEvents.LogCancel;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.exchange.getLogsAsync(differentEventName, blockRange, indexFilterValues);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const differentMakerAddress = userAddresses[2];
|
||||
const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, differentMakerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
txHash = await zeroEx.exchange.fillOrderAsync(
|
||||
anotherSignedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const eventName = ExchangeEvents.LogFill;
|
||||
const indexFilterValues = {
|
||||
maker: differentMakerAddress,
|
||||
};
|
||||
const logs = await zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
|
||||
eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(args.maker).to.be.equal(differentMakerAddress);
|
||||
});
|
||||
});
|
||||
}); // tslint:disable:max-file-line-count
|
||||
@@ -1,144 +0,0 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ZeroEx} from '../src/0x';
|
||||
import {ExpirationWatcher} from '../src/order_watcher/expiration_watcher';
|
||||
import {DoneCallback, Token} from '../src/types';
|
||||
import {constants} from '../src/utils/constants';
|
||||
import {utils} from '../src/utils/utils';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants as testConstants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(testConstants.RPC_URL);
|
||||
|
||||
describe('ExpirationWatcher', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let tokenUtils: TokenUtils;
|
||||
let tokens: Token[];
|
||||
let userAddresses: string[];
|
||||
let zrxTokenAddress: string;
|
||||
let fillScenarios: FillScenarios;
|
||||
let exchangeContractAddress: string;
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let coinbase: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let feeRecipient: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
let currentUnixTimestampSec: BigNumber;
|
||||
let timer: Sinon.SinonFakeTimers;
|
||||
let expirationWatcher: ExpirationWatcher;
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
const sinonTimerConfig = {shouldAdvanceTime: true} as any;
|
||||
// This constructor has incorrect types
|
||||
timer = Sinon.useFakeTimers(sinonTimerConfig);
|
||||
currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
|
||||
expirationWatcher = new ExpirationWatcher();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
timer.restore();
|
||||
expirationWatcher.unsubscribe();
|
||||
});
|
||||
it('correctly emits events when order expires', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const orderLifetimeSec = 60;
|
||||
const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
expirationUnixTimestampSec,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000));
|
||||
const callbackAsync = reportCallbackErrors(done)(async (hash: string) => {
|
||||
expect(hash).to.be.equal(orderHash);
|
||||
expect(utils.getCurrentUnixTimestampSec()).to.be.bignumber.gte(expirationUnixTimestampSec);
|
||||
done();
|
||||
});
|
||||
expirationWatcher.subscribe(callbackAsync);
|
||||
timer.tick(orderLifetimeSec * 1000);
|
||||
})().catch(done);
|
||||
});
|
||||
it('doesn\'t emit events before order expires', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const orderLifetimeSec = 60;
|
||||
const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
expirationUnixTimestampSec,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000));
|
||||
const callbackAsync = reportCallbackErrors(done)(async (hash: string) => {
|
||||
done(new Error('Emitted expiration went before the order actually expired'));
|
||||
});
|
||||
expirationWatcher.subscribe(callbackAsync);
|
||||
const notEnoughTime = orderLifetimeSec - 1;
|
||||
timer.tick(notEnoughTime * 1000);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
it('emits events in correct order', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const order1Lifetime = 60;
|
||||
const order2Lifetime = 120;
|
||||
const order1ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order1Lifetime);
|
||||
const order2ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order2Lifetime);
|
||||
const signedOrder1 = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
order1ExpirationUnixTimestampSec,
|
||||
);
|
||||
const signedOrder2 = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
order2ExpirationUnixTimestampSec,
|
||||
);
|
||||
const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1);
|
||||
const orderHash2 = ZeroEx.getOrderHashHex(signedOrder2);
|
||||
expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000));
|
||||
expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000));
|
||||
const expirationOrder = [orderHash1, orderHash2];
|
||||
const callbackAsync = reportCallbackErrors(done)(async (hash: string) => {
|
||||
const orderHash = expirationOrder.shift();
|
||||
expect(hash).to.be.equal(orderHash);
|
||||
if (_.isEmpty(expirationOrder)) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
expirationWatcher.subscribe(callbackAsync);
|
||||
timer.tick(order2Lifetime * 1000);
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
19
packages/0x.js/test/global_hooks.ts
Normal file
19
packages/0x.js/test/global_hooks.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { devConstants } from '@0xproject/dev-utils';
|
||||
import { runMigrationsAsync } from '@0xproject/migrations';
|
||||
import * as path from 'path';
|
||||
|
||||
import { constants } from './utils/constants';
|
||||
import { provider } from './utils/web3_wrapper';
|
||||
|
||||
before('migrate contracts', async function(): Promise<void> {
|
||||
// HACK: Since the migrations take longer then our global mocha timeout limit
|
||||
// we manually increase it for this before hook.
|
||||
const mochaTestTimeoutMs = 20000;
|
||||
this.timeout(mochaTestTimeoutMs);
|
||||
const txDefaults = {
|
||||
gas: devConstants.GAS_ESTIMATE,
|
||||
from: devConstants.TESTRPC_FIRST_ADDRESS,
|
||||
};
|
||||
const artifactsDir = `../migrations/artifacts/1.0.0`;
|
||||
await runMigrationsAsync(provider, artifactsDir, txDefaults);
|
||||
});
|
||||
@@ -1,463 +0,0 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
ExchangeContractErrs,
|
||||
OrderState,
|
||||
OrderStateInvalid,
|
||||
OrderStateValid,
|
||||
SignedOrder,
|
||||
Token,
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {DoneCallback} from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
const TIMEOUT_MS = 150;
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('OrderStateWatcher', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let tokens: Token[];
|
||||
let tokenUtils: TokenUtils;
|
||||
let fillScenarios: FillScenarios;
|
||||
let userAddresses: string[];
|
||||
let zrxTokenAddress: string;
|
||||
let exchangeContractAddress: string;
|
||||
let makerToken: Token;
|
||||
let takerToken: Token;
|
||||
let maker: string;
|
||||
let taker: string;
|
||||
let signedOrder: SignedOrder;
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const decimals = constants.ZRX_DECIMALS;
|
||||
const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
[, maker, taker] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
await fillScenarios.initTokenBalancesAsync();
|
||||
[makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#removeOrder', async () => {
|
||||
it('should successfully remove existing order', async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.include({
|
||||
[orderHash]: signedOrder,
|
||||
});
|
||||
let dependentOrderHashes = (zeroEx.orderStateWatcher as any)._dependentOrderHashes;
|
||||
expect(dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress]).to.have.keys(orderHash);
|
||||
zeroEx.orderStateWatcher.removeOrder(orderHash);
|
||||
expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.not.include({
|
||||
[orderHash]: signedOrder,
|
||||
});
|
||||
dependentOrderHashes = (zeroEx.orderStateWatcher as any)._dependentOrderHashes;
|
||||
expect(dependentOrderHashes[signedOrder.maker]).to.be.undefined();
|
||||
});
|
||||
it('should no-op when removing a non-existing order', async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
const nonExistentOrderHash = `0x${orderHash.substr(2).split('').reverse().join('')}`;
|
||||
zeroEx.orderStateWatcher.removeOrder(nonExistentOrderHash);
|
||||
});
|
||||
});
|
||||
describe('#subscribe', async () => {
|
||||
afterEach(async () => {
|
||||
zeroEx.orderStateWatcher.unsubscribe();
|
||||
});
|
||||
it('should fail when trying to subscribe twice', async () => {
|
||||
zeroEx.orderStateWatcher.subscribe(_.noop);
|
||||
expect(() => zeroEx.orderStateWatcher.subscribe(_.noop))
|
||||
.to.throw(ZeroExError.SubscriptionAlreadyPresent);
|
||||
});
|
||||
});
|
||||
describe('tests with cleanup', async () => {
|
||||
afterEach(async () => {
|
||||
zeroEx.orderStateWatcher.unsubscribe();
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.removeOrder(orderHash);
|
||||
});
|
||||
it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0));
|
||||
})().catch(done);
|
||||
});
|
||||
it('should not emit an orderState event when irrelevant Transfer event received', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
throw new Error('OrderState callback fired for irrelevant order');
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
const notTheMaker = userAddresses[0];
|
||||
const anyRecipient = taker;
|
||||
const transferAmount = new BigNumber(2);
|
||||
await zeroEx.token.transferAsync(makerToken.address, notTheMaker, anyRecipient, transferAmount);
|
||||
setTimeout(() => {
|
||||
done();
|
||||
}, TIMEOUT_MS);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateInvalid when maker moves balance backing watched order', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
const anyRecipient = taker;
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
await zeroEx.token.transferAsync(makerToken.address, maker, anyRecipient, makerBalance);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateValid when watched order partially filled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
const fillAmountInBaseUnits = new BigNumber(2);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.true();
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
const remainingMakerBalance = makerBalance.sub(fillAmountInBaseUnits);
|
||||
const remainingFillable = fillableAmount.minus(fillAmountInBaseUnits);
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingFillable);
|
||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingFillable);
|
||||
expect(orderRelevantState.makerBalance).to.be.bignumber.equal(remainingMakerBalance);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should trigger the callback when orders backing ZRX allowance changes', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
|
||||
const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), 18);
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker, taker, fillableAmount,
|
||||
taker);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0));
|
||||
})().catch(done);
|
||||
});
|
||||
describe('remainingFillable(M|T)akerTokenAmount', () => {
|
||||
it('should calculate correct remaining fillable', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const takerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(10), decimals);
|
||||
const makerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(20), decimals);
|
||||
signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, makerFillableAmount,
|
||||
takerFillableAmount,
|
||||
);
|
||||
const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.true();
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(16), decimals));
|
||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(8), decimals));
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
await zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should equal approved amount when approved amount is lowest', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
|
||||
const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
changedMakerApprovalAmount);
|
||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||
changedMakerApprovalAmount);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, changedMakerApprovalAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should equal balance amount when balance amount is lowest', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
|
||||
const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
||||
const transferAmount = makerBalance.sub(remainingAmount);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.true();
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingAmount);
|
||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingAmount);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.transferAsync(
|
||||
makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should equal remaining amount when partially cancelled and order has fees', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
|
||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||
const feeRecipient = taker;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
|
||||
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
||||
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.true();
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingTokenAmount);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, transferTokenAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should equal ratio amount when fee balance is lowered', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
|
||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||
const feeRecipient = taker;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
|
||||
const remainingFeeAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||
|
||||
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
||||
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
remainingFeeAmount);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, remainingFeeAmount);
|
||||
await zeroEx.token.transferAsync(
|
||||
makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferTokenAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should calculate full amount when all available and non-divisible', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals);
|
||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
const feeRecipient = taker;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||
fillableAmount);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.setProxyAllowanceAsync(
|
||||
makerToken.address, maker, ZeroEx.toBaseUnitAmount(new BigNumber(100), decimals));
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
it('should emit orderStateInvalid when watched order cancelled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateInvalid when within rounding error range', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const remainingFillableAmountInBaseUnits = new BigNumber(100);
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.exchange.cancelOrderAsync(
|
||||
signedOrder, fillableAmount.minus(remainingFillableAmountInBaseUnits),
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateValid when watched order partially cancelled', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
|
||||
const cancelAmountInBaseUnits = new BigNumber(2);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.true();
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
||||
const orderRelevantState = validOrderState.orderRelevantState;
|
||||
expect(orderRelevantState.cancelledTakerTokenAmount).to.be.bignumber.equal(cancelAmountInBaseUnits);
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmountInBaseUnits);
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
}); // tslint:disable:max-file-line-count
|
||||
@@ -1,328 +0,0 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError} from '../src';
|
||||
import {BlockParamLiteral, TradeSide, TransferType} from '../src/types';
|
||||
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
|
||||
import {OrderValidationUtils} from '../src/utils/order_validation_utils';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('OrderValidation', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let userAddresses: string[];
|
||||
let tokens: Token[];
|
||||
let tokenUtils: TokenUtils;
|
||||
let exchangeContractAddress: string;
|
||||
let zrxTokenAddress: string;
|
||||
let fillScenarios: FillScenarios;
|
||||
let makerTokenAddress: string;
|
||||
let takerTokenAddress: string;
|
||||
let coinbase: string;
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let feeRecipient: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const fillTakerAmount = new BigNumber(5);
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('validateOrderFillableOrThrowAsync', () => {
|
||||
it('should succeed if the order is fillable', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
||||
signedOrder,
|
||||
);
|
||||
});
|
||||
it('should succeed if the order is asymmetric and fillable', async () => {
|
||||
const makerFillableAmount = fillableAmount;
|
||||
const takerFillableAmount = fillableAmount.minus(4);
|
||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
makerFillableAmount, takerFillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
||||
signedOrder,
|
||||
);
|
||||
});
|
||||
it('should throw when the order is fully filled or cancelled', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
||||
signedOrder,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
});
|
||||
it('should throw when order is expired', async () => {
|
||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, expirationInPast,
|
||||
);
|
||||
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
||||
signedOrder,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
|
||||
});
|
||||
});
|
||||
describe('validateFillOrderAndThrowIfInvalidAsync', () => {
|
||||
it('should throw when the fill amount is zero', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const zeroFillAmount = new BigNumber(0);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, zeroFillAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||
});
|
||||
it('should throw when the signature is invalid', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
// 27 <--> 28
|
||||
signedOrder.ecSignature.v = (28 - signedOrder.ecSignature.v) + 27;
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillableAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ZeroExError.InvalidSignature);
|
||||
});
|
||||
it('should throw when the order is fully filled or cancelled', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillableAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
});
|
||||
it('should throw when sender is not a taker', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const nonTakerAddress = userAddresses[6];
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillTakerAmount, nonTakerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
|
||||
});
|
||||
it('should throw when order is expired', async () => {
|
||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, expirationInPast,
|
||||
);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillTakerAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
|
||||
});
|
||||
it('should throw when there a rounding error would have occurred', async () => {
|
||||
const makerAmount = new BigNumber(3);
|
||||
const takerAmount = new BigNumber(5);
|
||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
makerAmount, takerAmount,
|
||||
);
|
||||
const fillTakerAmountThatCausesRoundingError = new BigNumber(3);
|
||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||
signedOrder, fillTakerAmountThatCausesRoundingError, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillRoundingError);
|
||||
});
|
||||
});
|
||||
describe('#validateFillOrKillOrderAndThrowIfInvalidAsync', () => {
|
||||
it('should throw if remaining fillAmount is less then the desired fillAmount', async () => {
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
const tooLargeFillAmount = new BigNumber(7);
|
||||
const fillAmountDifference = tooLargeFillAmount.minus(fillableAmount);
|
||||
await zeroEx.token.transferAsync(takerTokenAddress, coinbase, takerAddress, fillAmountDifference);
|
||||
await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, tooLargeFillAmount);
|
||||
await zeroEx.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference);
|
||||
await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount);
|
||||
|
||||
return expect(zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
signedOrder, tooLargeFillAmount, takerAddress,
|
||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
||||
});
|
||||
});
|
||||
describe('validateCancelOrderAndThrowIfInvalidAsync', () => {
|
||||
let signedOrder: SignedOrder;
|
||||
const cancelAmount = new BigNumber(3);
|
||||
beforeEach(async () => {
|
||||
[coinbase, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
});
|
||||
it('should throw when cancel amount is zero', async () => {
|
||||
const zeroCancelAmount = new BigNumber(0);
|
||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||
});
|
||||
it('should throw when order is expired', async () => {
|
||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||
const expiredSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, expirationInPast,
|
||||
);
|
||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
|
||||
});
|
||||
it('should throw when order is already cancelled or filled', async () => {
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
|
||||
});
|
||||
});
|
||||
describe('#validateFillOrderBalancesAllowancesThrowIfInvalidAsync', () => {
|
||||
let exchangeTransferSimulator: ExchangeTransferSimulator;
|
||||
let transferFromAsync: Sinon.SinonSpy;
|
||||
const bigNumberMatch = (expected: BigNumber) => {
|
||||
return Sinon.match((value: BigNumber) => value.eq(expected));
|
||||
};
|
||||
beforeEach('create exchangeTransferSimulator', async () => {
|
||||
exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest);
|
||||
transferFromAsync = Sinon.spy();
|
||||
exchangeTransferSimulator.transferFromAsync = transferFromAsync as any;
|
||||
});
|
||||
it('should call exchangeTransferSimulator.transferFrom in a correct order', async () => {
|
||||
const makerFee = new BigNumber(2);
|
||||
const takerFee = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
|
||||
makerAddress, takerAddress, fillableAmount, feeRecipient,
|
||||
);
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
|
||||
);
|
||||
expect(transferFromAsync.callCount).to.be.equal(4);
|
||||
expect(
|
||||
transferFromAsync.getCall(0).calledWith(
|
||||
makerTokenAddress, makerAddress, takerAddress, bigNumberMatch(fillableAmount),
|
||||
TradeSide.Maker, TransferType.Trade,
|
||||
),
|
||||
).to.be.true();
|
||||
expect(
|
||||
transferFromAsync.getCall(1).calledWith(
|
||||
takerTokenAddress, takerAddress, makerAddress, bigNumberMatch(fillableAmount),
|
||||
TradeSide.Taker, TransferType.Trade,
|
||||
),
|
||||
).to.be.true();
|
||||
expect(
|
||||
transferFromAsync.getCall(2).calledWith(
|
||||
zrxTokenAddress, makerAddress, feeRecipient, bigNumberMatch(makerFee),
|
||||
TradeSide.Maker, TransferType.Fee,
|
||||
),
|
||||
).to.be.true();
|
||||
expect(
|
||||
transferFromAsync.getCall(3).calledWith(
|
||||
zrxTokenAddress, takerAddress, feeRecipient, bigNumberMatch(takerFee),
|
||||
TradeSide.Taker, TransferType.Fee,
|
||||
),
|
||||
).to.be.true();
|
||||
});
|
||||
it('should call exchangeTransferSimulator.transferFrom with correct values for an open order', async () => {
|
||||
const makerFee = new BigNumber(2);
|
||||
const takerFee = new BigNumber(2);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
|
||||
makerAddress, ZeroEx.NULL_ADDRESS, fillableAmount, feeRecipient,
|
||||
);
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
|
||||
);
|
||||
expect(transferFromAsync.callCount).to.be.equal(4);
|
||||
expect(
|
||||
transferFromAsync.getCall(0).calledWith(
|
||||
makerTokenAddress, makerAddress, takerAddress, bigNumberMatch(fillableAmount),
|
||||
TradeSide.Maker, TransferType.Trade,
|
||||
),
|
||||
).to.be.true();
|
||||
expect(
|
||||
transferFromAsync.getCall(1).calledWith(
|
||||
takerTokenAddress, takerAddress, makerAddress, bigNumberMatch(fillableAmount),
|
||||
TradeSide.Taker, TransferType.Trade,
|
||||
),
|
||||
).to.be.true();
|
||||
expect(
|
||||
transferFromAsync.getCall(2).calledWith(
|
||||
zrxTokenAddress, makerAddress, feeRecipient, bigNumberMatch(makerFee),
|
||||
TradeSide.Maker, TransferType.Fee,
|
||||
),
|
||||
).to.be.true();
|
||||
expect(
|
||||
transferFromAsync.getCall(3).calledWith(
|
||||
zrxTokenAddress, takerAddress, feeRecipient, bigNumberMatch(takerFee),
|
||||
TradeSide.Taker, TransferType.Fee,
|
||||
),
|
||||
).to.be.true();
|
||||
});
|
||||
it('should correctly round the fillMakerTokenAmount', async () => {
|
||||
const makerTokenAmount = new BigNumber(3);
|
||||
const takerTokenAmount = new BigNumber(1);
|
||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, makerTokenAmount, takerTokenAmount,
|
||||
);
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTransferSimulator, signedOrder, takerTokenAmount, takerAddress, zrxTokenAddress,
|
||||
);
|
||||
expect(transferFromAsync.callCount).to.be.equal(4);
|
||||
const makerFillAmount = transferFromAsync.getCall(0).args[3];
|
||||
expect(makerFillAmount).to.be.bignumber.equal(makerTokenAmount);
|
||||
});
|
||||
it('should correctly round the makerFeeAmount', async () => {
|
||||
const makerFee = new BigNumber(2);
|
||||
const takerFee = new BigNumber(4);
|
||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
||||
fillableAmount, ZeroEx.NULL_ADDRESS,
|
||||
);
|
||||
const fillTakerTokenAmount = fillableAmount.div(2).round(0);
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTransferSimulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress,
|
||||
);
|
||||
const makerPartialFee = makerFee.div(2);
|
||||
const takerPartialFee = takerFee.div(2);
|
||||
expect(transferFromAsync.callCount).to.be.equal(4);
|
||||
const partialMakerFee = transferFromAsync.getCall(2).args[3];
|
||||
expect(partialMakerFee).to.be.bignumber.equal(makerPartialFee);
|
||||
const partialTakerFee = transferFromAsync.getCall(3).args[3];
|
||||
expect(partialTakerFee).to.be.bignumber.equal(takerPartialFee);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,117 +0,0 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
ApprovalContractEventArgs,
|
||||
DecodedLogEvent,
|
||||
Token,
|
||||
TokenEvents,
|
||||
ZeroEx,
|
||||
} from '../src';
|
||||
import {DoneCallback} from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('SubscriptionTest', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let userAddresses: string[];
|
||||
let tokens: Token[];
|
||||
let coinbase: string;
|
||||
let addressWithoutFunds: string;
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
coinbase = userAddresses[0];
|
||||
addressWithoutFunds = userAddresses[1];
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
let tokenAddress: string;
|
||||
const allowanceAmount = new BigNumber(42);
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
before(() => {
|
||||
const token = tokens[0];
|
||||
tokenAddress = token.address;
|
||||
});
|
||||
afterEach(() => {
|
||||
zeroEx.token.unsubscribeAll();
|
||||
_.each(stubs, s => s.restore());
|
||||
stubs = [];
|
||||
});
|
||||
it('Should receive the Error when an error occurs while fetching the block', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const errMsg = 'Error fetching block';
|
||||
const callback = reportCallbackErrors(done)(
|
||||
(err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
expect(err.message).to.be.equal(errMsg);
|
||||
expect(logEvent).to.be.undefined();
|
||||
done();
|
||||
},
|
||||
);
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync')
|
||||
.throws(new Error(errMsg)),
|
||||
];
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Error when an error occurs while reconciling the new block', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const errMsg = 'Error fetching logs';
|
||||
const callback = reportCallbackErrors(done)(
|
||||
(err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
expect(err.message).to.be.equal(errMsg);
|
||||
expect(logEvent).to.be.undefined();
|
||||
done();
|
||||
},
|
||||
);
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'getLogsAsync')
|
||||
.throws(new Error(errMsg)),
|
||||
];
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => _.noop;
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
stubs = [
|
||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync')
|
||||
.throws(new Error('JSON RPC error')),
|
||||
];
|
||||
zeroEx.token.unsubscribeAll();
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,489 +0,0 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
ApprovalContractEventArgs,
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
DecodedLogEvent,
|
||||
Token,
|
||||
TokenEvents,
|
||||
TransferContractEventArgs,
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {DoneCallback} from '../src/types';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('TokenWrapper', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let userAddresses: string[];
|
||||
let tokens: Token[];
|
||||
let tokenUtils: TokenUtils;
|
||||
let coinbase: string;
|
||||
let addressWithoutFunds: string;
|
||||
let web3Wrapper: Web3Wrapper;
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
coinbase = userAddresses[0];
|
||||
addressWithoutFunds = userAddresses[1];
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
describe('#transferAsync', () => {
|
||||
let token: Token;
|
||||
let transferAmount: BigNumber;
|
||||
before(() => {
|
||||
token = tokens[0];
|
||||
transferAmount = new BigNumber(42);
|
||||
});
|
||||
it('should successfully transfer tokens', async () => {
|
||||
const fromAddress = coinbase;
|
||||
const toAddress = addressWithoutFunds;
|
||||
const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
expect(preBalance).to.be.bignumber.equal(0);
|
||||
await zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount);
|
||||
const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
||||
});
|
||||
it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => {
|
||||
const fromAddress = addressWithoutFunds;
|
||||
const toAddress = coinbase;
|
||||
return expect(zeroEx.token.transferAsync(
|
||||
token.address, fromAddress, toAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
||||
});
|
||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||
const fromAddress = coinbase;
|
||||
const toAddress = coinbase;
|
||||
return expect(zeroEx.token.transferAsync(
|
||||
nonExistentTokenAddress, fromAddress, toAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||
});
|
||||
});
|
||||
describe('#transferFromAsync', () => {
|
||||
let token: Token;
|
||||
let toAddress: string;
|
||||
let senderAddress: string;
|
||||
before(async () => {
|
||||
token = tokens[0];
|
||||
toAddress = addressWithoutFunds;
|
||||
senderAddress = userAddresses[2];
|
||||
});
|
||||
it('should fail to transfer tokens if fromAddress has insufficient allowance set', async () => {
|
||||
const fromAddress = coinbase;
|
||||
const transferAmount = new BigNumber(42);
|
||||
|
||||
const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
|
||||
expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount);
|
||||
|
||||
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress,
|
||||
toAddress);
|
||||
expect(fromAddressAllowance).to.be.bignumber.equal(0);
|
||||
|
||||
return expect(zeroEx.token.transferFromAsync(
|
||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
||||
});
|
||||
it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress',
|
||||
async () => {
|
||||
const fromAddress = coinbase;
|
||||
const transferAmount = new BigNumber(42);
|
||||
|
||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount);
|
||||
|
||||
return expect(zeroEx.token.transferFromAsync(
|
||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
||||
});
|
||||
it('should fail to transfer tokens if fromAddress has insufficient balance', async () => {
|
||||
const fromAddress = addressWithoutFunds;
|
||||
const transferAmount = new BigNumber(42);
|
||||
|
||||
const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
|
||||
expect(fromAddressBalance).to.be.bignumber.equal(0);
|
||||
|
||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
|
||||
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress,
|
||||
senderAddress);
|
||||
expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount);
|
||||
|
||||
return expect(zeroEx.token.transferFromAsync(
|
||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
||||
)).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
||||
});
|
||||
it('should successfully transfer tokens', async () => {
|
||||
const fromAddress = coinbase;
|
||||
|
||||
const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
expect(preBalance).to.be.bignumber.equal(0);
|
||||
|
||||
const transferAmount = new BigNumber(42);
|
||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
|
||||
|
||||
await zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress,
|
||||
transferAmount);
|
||||
const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
||||
});
|
||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||
const fromAddress = coinbase;
|
||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||
return expect(zeroEx.token.transferFromAsync(
|
||||
nonExistentTokenAddress, fromAddress, toAddress, senderAddress, new BigNumber(42),
|
||||
)).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||
});
|
||||
});
|
||||
describe('#getBalanceAsync', () => {
|
||||
describe('With web3 provider with accounts', () => {
|
||||
it('should return the balance for an existing ERC20 token', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const balance = await zeroEx.token.getBalanceAsync(token.address, ownerAddress);
|
||||
const expectedBalance = new BigNumber('1000000000000000000000000000');
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||
const ownerAddress = coinbase;
|
||||
return expect(zeroEx.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress))
|
||||
.to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||
});
|
||||
it('should return a balance of 0 for a non-existent owner address', async () => {
|
||||
const token = tokens[0];
|
||||
const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593';
|
||||
const balance = await zeroEx.token.getBalanceAsync(token.address, nonExistentOwner);
|
||||
const expectedBalance = new BigNumber(0);
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
});
|
||||
describe('With web3 provider without accounts', () => {
|
||||
let zeroExWithoutAccounts: ZeroEx;
|
||||
before(async () => {
|
||||
const hasAddresses = false;
|
||||
const web3WithoutAccounts = web3Factory.create(hasAddresses);
|
||||
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
||||
});
|
||||
it('should return balance even when called with Web3 provider instance without addresses', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress);
|
||||
const expectedBalance = new BigNumber('1000000000000000000000000000');
|
||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#setAllowanceAsync', () => {
|
||||
it('should set the spender\'s allowance', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
const allowanceBeforeSet = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress,
|
||||
spenderAddress);
|
||||
const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
|
||||
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
|
||||
|
||||
const allowanceAfterSet = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
|
||||
const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
|
||||
return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
|
||||
});
|
||||
});
|
||||
describe('#setUnlimitedAllowanceAsync', () => {
|
||||
it('should set the unlimited spender\'s allowance', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
await zeroEx.token.setUnlimitedAllowanceAsync(token.address, ownerAddress, spenderAddress);
|
||||
const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
|
||||
return expect(allowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => {
|
||||
const transferAmount = new BigNumber(5);
|
||||
const zrx = tokenUtils.getProtocolTokenOrThrow();
|
||||
const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses;
|
||||
await zeroEx.token.setAllowanceAsync(zrx.address, coinbase, userWithNormalAllowance, transferAmount);
|
||||
await zeroEx.token.setUnlimitedAllowanceAsync(zrx.address, coinbase, userWithUnlimitedAllowance);
|
||||
|
||||
const initBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
||||
const initBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
|
||||
userWithUnlimitedAllowance,
|
||||
);
|
||||
|
||||
await zeroEx.token.transferFromAsync(
|
||||
zrx.address, coinbase, userWithNormalAllowance, userWithNormalAllowance, transferAmount,
|
||||
);
|
||||
await zeroEx.token.transferFromAsync(
|
||||
zrx.address, coinbase, userWithUnlimitedAllowance, userWithUnlimitedAllowance, transferAmount,
|
||||
);
|
||||
|
||||
const finalBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
||||
const finalBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
|
||||
userWithUnlimitedAllowance,
|
||||
);
|
||||
|
||||
const normalGasCost = initBalanceWithNormalAllowance.minus(finalBalanceWithNormalAllowance);
|
||||
const unlimitedGasCost = initBalanceWithUnlimitedAllowance.minus(finalBalanceWithUnlimitedAllowance);
|
||||
|
||||
// In theory the gas cost with unlimited allowance should be smaller, but with testrpc it's actually bigger.
|
||||
// This needs to be investigated in ethereumjs-vm. This test is essentially a repro.
|
||||
// TODO: Make this test pass with inverted assertion.
|
||||
expect(unlimitedGasCost.toNumber()).to.be.gt(normalGasCost.toNumber());
|
||||
});
|
||||
});
|
||||
describe('#getAllowanceAsync', () => {
|
||||
describe('With web3 provider with accounts', () => {
|
||||
it('should get the proxy allowance', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
|
||||
|
||||
const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
|
||||
const expectedAllowance = amountInBaseUnits;
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
});
|
||||
it('should return 0 if no allowance set yet', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress);
|
||||
const expectedAllowance = new BigNumber(0);
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
});
|
||||
});
|
||||
describe('With web3 provider without accounts', () => {
|
||||
let zeroExWithoutAccounts: ZeroEx;
|
||||
before(async () => {
|
||||
const hasAddresses = false;
|
||||
const web3WithoutAccounts = web3Factory.create(hasAddresses);
|
||||
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
||||
});
|
||||
it('should get the proxy allowance', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
const spenderAddress = addressWithoutFunds;
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
|
||||
|
||||
const allowance = await zeroExWithoutAccounts.token.getAllowanceAsync(
|
||||
token.address, ownerAddress, spenderAddress,
|
||||
);
|
||||
const expectedAllowance = amountInBaseUnits;
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#getProxyAllowanceAsync', () => {
|
||||
it('should get the proxy allowance', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits);
|
||||
|
||||
const allowance = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
|
||||
const expectedAllowance = amountInBaseUnits;
|
||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||
});
|
||||
});
|
||||
describe('#setProxyAllowanceAsync', () => {
|
||||
it('should set the proxy allowance', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
|
||||
const allowanceBeforeSet = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
|
||||
const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
|
||||
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
|
||||
|
||||
const amountInBaseUnits = new BigNumber(50);
|
||||
await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits);
|
||||
|
||||
const allowanceAfterSet = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
|
||||
const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
|
||||
return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
|
||||
});
|
||||
});
|
||||
describe('#setUnlimitedProxyAllowanceAsync', () => {
|
||||
it('should set the unlimited proxy allowance', async () => {
|
||||
const token = tokens[0];
|
||||
const ownerAddress = coinbase;
|
||||
|
||||
await zeroEx.token.setUnlimitedProxyAllowanceAsync(token.address, ownerAddress);
|
||||
const allowance = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress);
|
||||
return expect(allowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
let tokenAddress: string;
|
||||
const transferAmount = new BigNumber(42);
|
||||
const allowanceAmount = new BigNumber(42);
|
||||
before(() => {
|
||||
const token = tokens[0];
|
||||
tokenAddress = token.address;
|
||||
});
|
||||
afterEach(() => {
|
||||
zeroEx.token.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
// we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
|
||||
// wrap the rest of the test in an async block
|
||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
expect(logEvent.log.logIndex).to.be.equal(0);
|
||||
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
||||
expect(logEvent.log.blockNumber).to.be.a('number');
|
||||
const args = logEvent.log.args;
|
||||
expect(args._from).to.be.equal(coinbase);
|
||||
expect(args._to).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(transferAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callback);
|
||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(coinbase);
|
||||
expect(args._spender).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled,
|
||||
);
|
||||
const callbackToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done();
|
||||
};
|
||||
const newProvider = web3Factory.getRpcProvider();
|
||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||
zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled,
|
||||
);
|
||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
const subscriptionToken = zeroEx.token.subscribe(
|
||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
||||
zeroEx.token.unsubscribe(subscriptionToken);
|
||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
describe('#getLogsAsync', () => {
|
||||
let tokenAddress: string;
|
||||
let tokenTransferProxyAddress: string;
|
||||
const blockRange: BlockRange = {
|
||||
fromBlock: 0,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
let txHash: string;
|
||||
before(() => {
|
||||
const token = tokens[0];
|
||||
tokenAddress = token.address;
|
||||
tokenTransferProxyAddress = zeroEx.proxy.getContractAddress();
|
||||
});
|
||||
it('should get logs with decoded args emitted by Approval', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = TokenEvents.Approval;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
||||
tokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(coinbase);
|
||||
expect(args._spender).to.be.equal(tokenTransferProxyAddress);
|
||||
expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const differentEventName = TokenEvents.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.token.getLogsAsync(
|
||||
tokenAddress, differentEventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, addressWithoutFunds);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = TokenEvents.Approval;
|
||||
const indexFilterValues = {
|
||||
_owner: coinbase,
|
||||
};
|
||||
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
||||
tokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(args._owner).to.be.equal(coinbase);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@ import ChaiBigNumber = require('chai-bignumber');
|
||||
import * as dirtyChai from 'dirty-chai';
|
||||
|
||||
export const chaiSetup = {
|
||||
configure() {
|
||||
configure(): void {
|
||||
chai.config.includeStack = true;
|
||||
chai.use(ChaiBigNumber());
|
||||
chai.use(dirtyChai);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
export const constants = {
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
RPC_URL: 'http://localhost:8545/',
|
||||
ROPSTEN_NETWORK_ID: 3,
|
||||
KOVAN_NETWORK_ID: 42,
|
||||
TESTRPC_NETWORK_ID: 50,
|
||||
KOVAN_RPC_URL: 'https://kovan.infura.io/',
|
||||
ROPSTEN_RPC_URL: 'https://ropsten.infura.io/',
|
||||
ZRX_DECIMALS: 18,
|
||||
GAS_ESTIMATE: 500000,
|
||||
};
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import {SignedOrder, Token, ZeroEx} from '../../src';
|
||||
import {artifacts} from '../../src/artifacts';
|
||||
import {DummyTokenContract} from '../../src/contract_wrappers/generated/dummy_token';
|
||||
import {orderFactory} from '../utils/order_factory';
|
||||
|
||||
import {constants} from './constants';
|
||||
|
||||
const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100);
|
||||
|
||||
export class FillScenarios {
|
||||
private _zeroEx: ZeroEx;
|
||||
private _userAddresses: string[];
|
||||
private _tokens: Token[];
|
||||
private _coinbase: string;
|
||||
private _zrxTokenAddress: string;
|
||||
private _exchangeContractAddress: string;
|
||||
constructor(zeroEx: ZeroEx, userAddresses: string[],
|
||||
tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) {
|
||||
this._zeroEx = zeroEx;
|
||||
this._userAddresses = userAddresses;
|
||||
this._tokens = tokens;
|
||||
this._coinbase = userAddresses[0];
|
||||
this._zrxTokenAddress = zrxTokenAddress;
|
||||
this._exchangeContractAddress = exchangeContractAddress;
|
||||
}
|
||||
public async initTokenBalancesAsync() {
|
||||
const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
|
||||
for (const token of this._tokens) {
|
||||
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
|
||||
const contractInstance = web3Wrapper.getContractInstance(
|
||||
artifacts.DummyTokenArtifact.abi, token.address,
|
||||
);
|
||||
const defaults = {};
|
||||
const dummyToken = new DummyTokenContract(contractInstance, defaults);
|
||||
const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
|
||||
const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
|
||||
from: this._coinbase,
|
||||
});
|
||||
await this._zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
|
||||
makerAddress: string, takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
expirationUnixTimestampSec?: BigNumber):
|
||||
Promise<SignedOrder> {
|
||||
return this.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, fillableAmount, expirationUnixTimestampSec,
|
||||
);
|
||||
}
|
||||
public async createFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress: string, takerTokenAddress: string,
|
||||
makerFee: BigNumber, takerFee: BigNumber,
|
||||
makerAddress: string, takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
feeRecepient: string, expirationUnixTimestampSec?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
||||
fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec,
|
||||
);
|
||||
}
|
||||
public async createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress: string, takerTokenAddress: string, makerAddress: string, takerAddress: string,
|
||||
makerFillableAmount: BigNumber, takerFillableAmount: BigNumber,
|
||||
expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
|
||||
const makerFee = new BigNumber(0);
|
||||
const takerFee = new BigNumber(0);
|
||||
const feeRecepient = constants.NULL_ADDRESS;
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
||||
makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec,
|
||||
);
|
||||
}
|
||||
public async createPartiallyFilledSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
|
||||
takerAddress: string, fillableAmount: BigNumber,
|
||||
partialFillAmount: BigNumber) {
|
||||
const [makerAddress] = this._userAddresses;
|
||||
const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, fillableAmount,
|
||||
);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = false;
|
||||
await this._zeroEx.exchange.fillOrderAsync(
|
||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
||||
);
|
||||
return signedOrder;
|
||||
}
|
||||
private async _createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerTokenAddress: string, takerTokenAddress: string,
|
||||
makerFee: BigNumber, takerFee: BigNumber,
|
||||
makerAddress: string, takerAddress: string,
|
||||
makerFillableAmount: BigNumber, takerFillableAmount: BigNumber,
|
||||
feeRecepient: string, expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
|
||||
|
||||
await Promise.all([
|
||||
this._increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
|
||||
this._increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
|
||||
]);
|
||||
await Promise.all([
|
||||
this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, makerAddress, makerFee),
|
||||
this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
|
||||
]);
|
||||
|
||||
const signedOrder = await orderFactory.createSignedOrderAsync(this._zeroEx,
|
||||
makerAddress, takerAddress, makerFee, takerFee,
|
||||
makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress,
|
||||
this._exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
|
||||
return signedOrder;
|
||||
}
|
||||
private async _increaseBalanceAndAllowanceAsync(
|
||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
|
||||
return; // noop
|
||||
}
|
||||
await Promise.all([
|
||||
this._increaseBalanceAsync(tokenAddress, address, amount),
|
||||
this._increaseAllowanceAsync(tokenAddress, address, amount),
|
||||
]);
|
||||
}
|
||||
private async _increaseBalanceAsync(
|
||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
await this._zeroEx.token.transferAsync(tokenAddress, this._coinbase, address, amount);
|
||||
}
|
||||
private async _increaseAllowanceAsync(
|
||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
const oldMakerAllowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, address);
|
||||
const newMakerAllowance = oldMakerAllowance.plus(amount);
|
||||
await this._zeroEx.token.setProxyAllowanceAsync(
|
||||
tokenAddress, address, newMakerAllowance,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import {DoneCallback} from '../../src/types';
|
||||
|
||||
export const reportCallbackErrors = (done: DoneCallback) => {
|
||||
return (f: (...args: any[]) => void) => {
|
||||
const wrapped = async (...args: any[]) => {
|
||||
try {
|
||||
f(...args);
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
};
|
||||
return wrapped;
|
||||
};
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
import {JSONRPCPayload} from '../../../src/types';
|
||||
|
||||
/*
|
||||
* This class implements the web3-provider-engine subprovider interface and returns
|
||||
* that the provider has no addresses when queried.
|
||||
* Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
|
||||
*/
|
||||
export class EmptyWalletSubprovider {
|
||||
// This method needs to be here to satisfy the interface but linter wants it to be static.
|
||||
// tslint:disable-next-line:prefer-function-over-method
|
||||
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error|null, result: any) => void) {
|
||||
switch (payload.method) {
|
||||
case 'eth_accounts':
|
||||
end(null, []);
|
||||
return;
|
||||
|
||||
default:
|
||||
next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Required to implement this method despite not needing it for this subprovider
|
||||
// tslint:disable-next-line:prefer-function-over-method
|
||||
public setEngine(engine: any) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import {JSONRPCPayload} from '../../../src/types';
|
||||
|
||||
/*
|
||||
* This class implements the web3-provider-engine subprovider interface and returns
|
||||
* the constant gas estimate when queried.
|
||||
* HACK: We need this so that our tests don't use testrpc gas estimation which sometimes kills the node.
|
||||
* Source: https://github.com/trufflesuite/ganache-cli/issues/417
|
||||
* Source: https://github.com/trufflesuite/ganache-cli/issues/437
|
||||
* Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
|
||||
*/
|
||||
export class FakeGasEstimateSubprovider {
|
||||
private _constantGasAmount: number;
|
||||
constructor(constantGasAmount: number) {
|
||||
this._constantGasAmount = constantGasAmount;
|
||||
}
|
||||
// This method needs to be here to satisfy the interface but linter wants it to be static.
|
||||
// tslint:disable-next-line:prefer-function-over-method
|
||||
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error|null, result: any) => void) {
|
||||
switch (payload.method) {
|
||||
case 'eth_estimateGas':
|
||||
end(null, this._constantGasAmount);
|
||||
return;
|
||||
|
||||
default:
|
||||
next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Required to implement this method despite not needing it for this subprovider
|
||||
// tslint:disable-next-line:prefer-function-over-method
|
||||
public setEngine(engine: any) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Token } from '@0xproject/types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {InternalZeroExError, Token} from '../../src/types';
|
||||
import { InternalZeroExError } from '../../src/types';
|
||||
|
||||
const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
|
||||
const WETH_TOKEN_SYMBOL = 'WETH';
|
||||
@@ -11,14 +12,14 @@ export class TokenUtils {
|
||||
this._tokens = tokens;
|
||||
}
|
||||
public getProtocolTokenOrThrow(): Token {
|
||||
const zrxToken = _.find(this._tokens, {symbol: PROTOCOL_TOKEN_SYMBOL});
|
||||
const zrxToken = _.find(this._tokens, { symbol: PROTOCOL_TOKEN_SYMBOL });
|
||||
if (_.isUndefined(zrxToken)) {
|
||||
throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
|
||||
}
|
||||
return zrxToken;
|
||||
}
|
||||
public getWethTokenOrThrow(): Token {
|
||||
const wethToken = _.find(this._tokens, {symbol: WETH_TOKEN_SYMBOL});
|
||||
const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL });
|
||||
if (_.isUndefined(wethToken)) {
|
||||
throw new Error(InternalZeroExError.WethNotInTokenRegistry);
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// HACK: web3 injects XMLHttpRequest into the global scope and ProviderEngine checks XMLHttpRequest
|
||||
// to know whether it is running in a browser or node environment. We need it to be undefined since
|
||||
// we are not running in a browser env.
|
||||
// Filed issue: https://github.com/ethereum/web3.js/issues/844
|
||||
(global as any).XMLHttpRequest = undefined;
|
||||
import ProviderEngine = require('web3-provider-engine');
|
||||
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
|
||||
|
||||
import {EmptyWalletSubprovider} from './subproviders/empty_wallet_subprovider';
|
||||
import {FakeGasEstimateSubprovider} from './subproviders/fake_gas_estimate_subprovider';
|
||||
|
||||
import {constants} from './constants';
|
||||
|
||||
// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
|
||||
// because they are using the wrong XHR package.
|
||||
// importing web3 after subproviders fixes this issue
|
||||
// Filed issue: https://github.com/ethereum/web3.js/issues/844
|
||||
// tslint:disable-next-line:ordered-imports
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export const web3Factory = {
|
||||
create(hasAddresses: boolean = true): Web3 {
|
||||
const provider = this.getRpcProvider(hasAddresses);
|
||||
const web3 = new Web3();
|
||||
web3.setProvider(provider);
|
||||
return web3;
|
||||
},
|
||||
getRpcProvider(hasAddresses: boolean = true): Web3.Provider {
|
||||
const provider = new ProviderEngine();
|
||||
if (!hasAddresses) {
|
||||
provider.addProvider(new EmptyWalletSubprovider());
|
||||
}
|
||||
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_ESTIMATE));
|
||||
provider.addProvider(new RpcSubprovider({
|
||||
rpcUrl: constants.RPC_URL,
|
||||
}));
|
||||
provider.start();
|
||||
return provider;
|
||||
},
|
||||
};
|
||||
9
packages/0x.js/test/utils/web3_wrapper.ts
Normal file
9
packages/0x.js/test/utils/web3_wrapper.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||
import { Provider } from '@0xproject/types';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
|
||||
const web3 = web3Factory.create({ shouldUseInProcessGanache: true });
|
||||
const provider: Provider = web3.currentProvider;
|
||||
const web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
||||
|
||||
export { provider, web3Wrapper };
|
||||
@@ -1,22 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"lib": [ "es2015", "dom" ],
|
||||
"outDir": "lib",
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"noImplicitAny": true,
|
||||
"experimentalDecorators": true,
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*",
|
||||
"./test/**/*",
|
||||
"../../node_modules/types-bn/index.d.ts",
|
||||
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
||||
"../../node_modules/web3-typescript-typings/index.d.ts",
|
||||
"../../node_modules/chai-typescript-typings/index.d.ts",
|
||||
"../../node_modules/chai-as-promised-typescript-typings/index.d.ts"
|
||||
]
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*"]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
{
|
||||
"extends": [
|
||||
"@0xproject/tslint-config"
|
||||
]
|
||||
"extends": ["@0xproject/tslint-config"]
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ const path = require('path');
|
||||
const production = process.env.NODE_ENV === 'production';
|
||||
|
||||
let entry = {
|
||||
'index': './src/index.ts',
|
||||
index: './src/index.ts',
|
||||
};
|
||||
if (production) {
|
||||
entry = _.assign({}, entry, {'index.min': './src/index.ts'});
|
||||
entry = _.assign({}, entry, { 'index.min': './src/index.ts' });
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
6
packages/abi-gen/.npmignore
Normal file
6
packages/abi-gen/.npmignore
Normal file
@@ -0,0 +1,6 @@
|
||||
.*
|
||||
yarn-error.log
|
||||
/src/
|
||||
/scripts/
|
||||
tsconfig.json
|
||||
/lib/monorepo_scripts/
|
||||
166
packages/abi-gen/CHANGELOG.json
Normal file
166
packages/abi-gen/CHANGELOG.json
Normal file
@@ -0,0 +1,166 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1531149657,
|
||||
"version": "0.3.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1529397769,
|
||||
"version": "0.3.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.3.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Incorrect publish that was unpublished"
|
||||
}
|
||||
],
|
||||
"timestamp": 1527810075
|
||||
},
|
||||
{
|
||||
"version": "0.3.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Properly export the executable binary",
|
||||
"pr": 588
|
||||
}
|
||||
],
|
||||
"timestamp": 1527008270
|
||||
},
|
||||
{
|
||||
"timestamp": 1525477860,
|
||||
"version": "0.2.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.2.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.2.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1523462196,
|
||||
"version": "0.2.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1522673609,
|
||||
"version": "0.2.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1522658513,
|
||||
"version": "0.2.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.2.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package",
|
||||
"pr": 452
|
||||
}
|
||||
],
|
||||
"timestamp": 1521298800
|
||||
},
|
||||
{
|
||||
"version": "0.2.4",
|
||||
"changes": [
|
||||
{
|
||||
"note":
|
||||
"Add a `backend` parameter that allows you to specify the Ethereum library you use in your templates (`web3` or `ethers`). Ethers auto-converts small ints to numbers whereas Web3 doesn't. Defaults to `web3`",
|
||||
"pr": 413
|
||||
},
|
||||
{
|
||||
"note":
|
||||
"Add support for [tuple types](https://solidity.readthedocs.io/en/develop/abi-spec.html#handling-tuple-types)",
|
||||
"pr": 413
|
||||
},
|
||||
{
|
||||
"note": "Add `hasReturnValue` to context data",
|
||||
"pr": 413
|
||||
}
|
||||
],
|
||||
"timestamp": 1520089200
|
||||
},
|
||||
{
|
||||
"version": "0.2.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fix publishing issue where .npmignore was not properly excluding undesired content",
|
||||
"pr": 389
|
||||
}
|
||||
],
|
||||
"timestamp": 1518102000
|
||||
},
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Added CLI options for explicit specifying location of partials and main template",
|
||||
"pr": 346
|
||||
},
|
||||
{
|
||||
"note":
|
||||
"Added CLI option to specify networkId, adding support for the JSON artifact format found in @0xproject/contracts",
|
||||
"pr": 388
|
||||
}
|
||||
],
|
||||
"timestamp": 1517929200
|
||||
},
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fixed array typings with union types",
|
||||
"pr": 295
|
||||
},
|
||||
{
|
||||
"note": "Add event ABIs to context data passed to templates",
|
||||
"pr": 302
|
||||
},
|
||||
{
|
||||
"note": "Add constructor ABIs to context data passed to templates",
|
||||
"pr": 304
|
||||
}
|
||||
],
|
||||
"timestamp": 1515596400
|
||||
}
|
||||
]
|
||||
@@ -1,4 +1,71 @@
|
||||
# CHANGELOG
|
||||
<!--
|
||||
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
|
||||
Edit the package's CHANGELOG.json file only.
|
||||
-->
|
||||
|
||||
vx.x.x
|
||||
------------------------
|
||||
CHANGELOG
|
||||
|
||||
## v0.3.3 - _July 9, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.3.2 - _June 19, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.3.1 - _June 1, 2018_
|
||||
|
||||
* Incorrect publish that was unpublished
|
||||
|
||||
## v0.3.0 - _May 22, 2018_
|
||||
|
||||
* Properly export the executable binary (#588)
|
||||
|
||||
## v0.2.13 - _May 5, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.12 - _May 4, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.11 - _April 18, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.10 - _April 11, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.9 - _April 2, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.8 - _April 2, 2018_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.2.5 - _March 17, 2018_
|
||||
|
||||
* Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452)
|
||||
|
||||
## v0.2.4 - _March 3, 2018_
|
||||
|
||||
* Add a `backend` parameter that allows you to specify the Ethereum library you use in your templates (`web3` or `ethers`). Ethers auto-converts small ints to numbers whereas Web3 doesn't. Defaults to `web3` (#413)
|
||||
* Add support for [tuple types](https://solidity.readthedocs.io/en/develop/abi-spec.html#handling-tuple-types) (#413)
|
||||
* Add `hasReturnValue` to context data (#413)
|
||||
|
||||
## v0.2.1 - _February 8, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
||||
## v0.2.0 - _February 6, 2018_
|
||||
|
||||
* Added CLI options for explicit specifying location of partials and main template (#346)
|
||||
* Added CLI option to specify networkId, adding support for the JSON artifact format found in @0xproject/contracts (#388)
|
||||
|
||||
## v0.1.0 - _January 10, 2018_
|
||||
|
||||
* Fixed array typings with union types (#295)
|
||||
* Add event ABIs to context data passed to templates (#302)
|
||||
* Add constructor ABIs to context data passed to templates (#304)
|
||||
|
||||
@@ -4,36 +4,102 @@ This package allows you to generate TypeScript contract wrappers from ABI files.
|
||||
It's heavily inspired by [Geth abigen](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) but takes a different approach.
|
||||
You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions.
|
||||
|
||||
For an example of the generated [wrapper files](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/src/contract_wrappers/generated) check out 0x.js.
|
||||
[Here](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files.
|
||||
For an example of the generated [wrapper files](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/src/contract_wrappers/generated) check out 0x.js.
|
||||
[Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files.
|
||||
|
||||
## Installation
|
||||
|
||||
`yarn add -g @0xproject/abi-gen`
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
abi-gen
|
||||
Options:
|
||||
--help Show help [boolean]
|
||||
--version Show version number [boolean]
|
||||
--abiGlob Glob pattern to search for ABI JSON files [string] [required]
|
||||
--templates Folder where to search for templates [string] [required]
|
||||
--output Folder where to put the output files [string] [required]
|
||||
--help Show help [boolean]
|
||||
--version Show version number [boolean]
|
||||
--abis Glob pattern to search for ABI JSON files
|
||||
[string] [required]
|
||||
--output, -o, --out Folder where to put the output files [string] [required]
|
||||
--partials Glob pattern for the partial template files [string]
|
||||
--template Path for the main template file that will be used to
|
||||
generate each contract [string] [required]
|
||||
--backend The backing Ethereum library your app uses. Either 'web3'
|
||||
or 'ethers'. Ethers auto-converts small ints to numbers
|
||||
whereas Web3 doesn't.
|
||||
[string] [choices: "web3", "ethers"] [default: "web3"]
|
||||
--network-id ID of the network where contract ABIs are nested in
|
||||
artifacts [number] [default: 50]
|
||||
```
|
||||
## ABI files
|
||||
You're required to pass a [glob](https://en.wikipedia.org/wiki/Glob_(programming)) template where your abi files are located.
|
||||
|
||||
You're required to pass a [glob](<https://en.wikipedia.org/wiki/Glob_(programming)>) template where your abi files are located.
|
||||
TL;DR - here is the example from 0x.js.
|
||||
|
||||
`--abiGlob 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry).json`
|
||||
`--abis 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry).json`
|
||||
|
||||
We could've just used `--abiGlob 'src/artifacts/*.json` but we wanted to exclude some of the abi files.
|
||||
We could've just used `--abis 'src/artifacts/*.json` but we wanted to exclude some of the abi files.
|
||||
|
||||
The abi file should be either a [Truffle](http://truffleframework.com/) contract artifact (a JSON object with an abi key) or a JSON abi array.
|
||||
|
||||
You need to also specify the location of your main template used for every contract `--template` as well as the partial templates `--partials` that can later be used from the main one.
|
||||
|
||||
## How to write custom templates?
|
||||
The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates) and start adjusting them for your needs.
|
||||
|
||||
The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) and start adjusting them for your needs.
|
||||
We use [handlebars](http://handlebarsjs.com/) template engine under the hood.
|
||||
You need to have a master template called `contract.mustache`. it will be used to generate each contract wrapper. Although - you don't need and probably shouldn't write all your logic in a single template file. You can write [partial templates](http://handlebarsjs.com/partials.html) and as long as they are within a partials folder - they will be registered and available.
|
||||
|
||||
## Which data/context do I get in my templates?
|
||||
|
||||
For now you don't get much on top of methods abi, some useful helpers and a contract name because it was enough for our use-case, but if you need something else - create a PR.
|
||||
See the [type definition](https://github.com/0xProject/0x.js/tree/development/packages/abi-gen/src/types.ts) of what we pass to the render method.
|
||||
See the [type definition](https://github.com/0xProject/0x-monorepo/tree/development/packages/abi-gen/src/types.ts) of what we pass to the render method.
|
||||
|
||||
## Output files
|
||||
|
||||
Output files will be generated within an output folder with names converted to camel case and taken from abi file names. If you already have some files in that folder they will be overwritten.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
PKG=@0xproject/abi-gen yarn build
|
||||
```
|
||||
|
||||
Or continuously rebuild on change:
|
||||
|
||||
```bash
|
||||
PKG=@0xproject/abi-gen yarn watch
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
2
packages/abi-gen/bin/abi-gen.js
Executable file
2
packages/abi-gen/bin/abi-gen.js
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env node
|
||||
require('../lib/index.js')
|
||||
@@ -1,48 +1,59 @@
|
||||
{
|
||||
"name": "@0xproject/abi-gen",
|
||||
"version": "0.0.3",
|
||||
"description": "Generate contract wrappers from ABI and handlebars templates",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"lint": "tslint --project . 'src/**/*.ts'",
|
||||
"clean": "shx rm -rf lib",
|
||||
"build": "tsc"
|
||||
},
|
||||
"bin": {
|
||||
"abi-gen": "lib/index.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x.js.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x.js/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/abi-gen/README.md",
|
||||
"dependencies": {
|
||||
"bignumber.js": "~4.1.0",
|
||||
"chalk": "^2.3.0",
|
||||
"glob": "^7.1.2",
|
||||
"handlebars": "^4.0.11",
|
||||
"lodash": "^4.17.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"to-snake-case": "^1.0.0",
|
||||
"web3": "^0.20.0",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.3.0",
|
||||
"@types/glob": "^5.0.33",
|
||||
"@types/handlebars": "^4.0.36",
|
||||
"@types/mkdirp": "^0.5.1",
|
||||
"@types/node": "^8.0.53",
|
||||
"@types/yargs": "^10.0.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "~2.6.1",
|
||||
"web3-typescript-typings": "^0.7.2"
|
||||
}
|
||||
"name": "@0xproject/abi-gen",
|
||||
"version": "0.3.3",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"description": "Generate contract wrappers from ABI and handlebars templates",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"watch": "tsc -w",
|
||||
"lint": "tslint --project .",
|
||||
"clean": "shx rm -rf lib scripts",
|
||||
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
|
||||
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
|
||||
},
|
||||
"bin": {
|
||||
"abi-gen": "bin/abi-gen.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
|
||||
"dependencies": {
|
||||
"@0xproject/types": "^0.8.2",
|
||||
"@0xproject/typescript-typings": "^0.4.2",
|
||||
"@0xproject/utils": "^0.7.2",
|
||||
"chalk": "2.3.2",
|
||||
"glob": "7.1.1",
|
||||
"handlebars": "4.0.11",
|
||||
"lodash": "4.17.10",
|
||||
"mkdirp": "0.5.1",
|
||||
"to-snake-case": "1.0.0",
|
||||
"yargs": "11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/monorepo-scripts": "^0.2.2",
|
||||
"@0xproject/tslint-config": "^0.4.21",
|
||||
"@types/glob": "5.0.35",
|
||||
"@types/handlebars": "4.0.36",
|
||||
"@types/mkdirp": "0.5.2",
|
||||
"@types/node": "9.6.0",
|
||||
"@types/yargs": "10.0.2",
|
||||
"copyfiles": "1.2.0",
|
||||
"make-promises-safe": "1.1.0",
|
||||
"npm-run-all": "4.1.2",
|
||||
"shx": "0.2.2",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "2.7.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
|
||||
const packageJSON = require('../package.json');
|
||||
|
||||
const subPackageName = packageJSON.name;
|
||||
|
||||
postpublish_utils.getLatestTagAndVersionAsync(subPackageName)
|
||||
.then(function(result) {
|
||||
const releaseName = postpublish_utils.getReleaseName(subPackageName, result.version);
|
||||
const assets = [];
|
||||
return postpublish_utils.publishReleaseNotes(result.tag, releaseName, assets);
|
||||
})
|
||||
.catch (function(err) {
|
||||
throw err;
|
||||
});
|
||||
8
packages/abi-gen/src/globals.d.ts
vendored
8
packages/abi-gen/src/globals.d.ts
vendored
@@ -1,4 +1,6 @@
|
||||
declare function toSnakeCase(str: string): string;
|
||||
declare module 'to-snake-case' {
|
||||
export = toSnakeCase;
|
||||
declare module '*.json' {
|
||||
const json: any;
|
||||
/* tslint:disable */
|
||||
export default json;
|
||||
/* tslint:enable */
|
||||
}
|
||||
|
||||
@@ -1,97 +1,155 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { AbiDefinition, ConstructorAbi, EventAbi, MethodAbi } from '@0xproject/types';
|
||||
import { abiUtils, logUtils } from '@0xproject/utils';
|
||||
import chalk from 'chalk';
|
||||
import * as fs from 'fs';
|
||||
import {sync as globSync} from 'glob';
|
||||
import { sync as globSync } from 'glob';
|
||||
import * as Handlebars from 'handlebars';
|
||||
import * as _ from 'lodash';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import * as yargs from 'yargs';
|
||||
|
||||
import toSnakeCase = require('to-snake-case');
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ContextData, ParamKind} from './types';
|
||||
import {utils} from './utils';
|
||||
import { ContextData, ContractsBackend, Method, ParamKind } from './types';
|
||||
import { utils } from './utils';
|
||||
|
||||
const ABI_TYPE_CONSTRUCTOR = 'constructor';
|
||||
const ABI_TYPE_METHOD = 'function';
|
||||
const MAIN_TEMPLATE_NAME = 'contract.mustache';
|
||||
const ABI_TYPE_EVENT = 'event';
|
||||
const DEFAULT_NETWORK_ID = 50;
|
||||
const DEFAULT_BACKEND = 'web3';
|
||||
|
||||
const args = yargs
|
||||
.option('abiGlob', {
|
||||
.option('abis', {
|
||||
describe: 'Glob pattern to search for ABI JSON files',
|
||||
type: 'string',
|
||||
demand: true,
|
||||
})
|
||||
.option('templates', {
|
||||
describe: 'Folder where to search for templates',
|
||||
type: 'string',
|
||||
demand: true,
|
||||
demandOption: true,
|
||||
})
|
||||
.option('output', {
|
||||
alias: ['o', 'out'],
|
||||
describe: 'Folder where to put the output files',
|
||||
type: 'string',
|
||||
demand: true,
|
||||
normalize: true,
|
||||
demandOption: true,
|
||||
})
|
||||
.argv;
|
||||
.option('partials', {
|
||||
describe: 'Glob pattern for the partial template files',
|
||||
type: 'string',
|
||||
implies: 'template',
|
||||
})
|
||||
.option('template', {
|
||||
describe: 'Path for the main template file that will be used to generate each contract',
|
||||
type: 'string',
|
||||
demandOption: true,
|
||||
normalize: true,
|
||||
})
|
||||
.option('backend', {
|
||||
describe: `The backing Ethereum library your app uses. Either 'web3' or 'ethers'. Ethers auto-converts small ints to numbers whereas Web3 doesn't.`,
|
||||
type: 'string',
|
||||
choices: [ContractsBackend.Web3, ContractsBackend.Ethers],
|
||||
default: DEFAULT_BACKEND,
|
||||
})
|
||||
.option('network-id', {
|
||||
describe: 'ID of the network where contract ABIs are nested in artifacts',
|
||||
type: 'number',
|
||||
default: DEFAULT_NETWORK_ID,
|
||||
})
|
||||
.example(
|
||||
"$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'",
|
||||
'Full usage example',
|
||||
).argv;
|
||||
|
||||
function registerPartials(partialsGlob: string): void {
|
||||
const partialTemplateFileNames = globSync(partialsGlob);
|
||||
logUtils.log(`Found ${chalk.green(`${partialTemplateFileNames.length}`)} ${chalk.bold('partial')} templates`);
|
||||
for (const partialTemplateFileName of partialTemplateFileNames) {
|
||||
const namedContent = utils.getNamedContent(partialTemplateFileName);
|
||||
Handlebars.registerPartial(namedContent.name, namedContent.content);
|
||||
}
|
||||
}
|
||||
|
||||
function writeOutputFile(name: string, renderedTsCode: string): void {
|
||||
const fileName = toSnakeCase(name);
|
||||
let fileName = toSnakeCase(name);
|
||||
if (fileName === 'z_r_x_token') {
|
||||
fileName = 'zrx_token';
|
||||
}
|
||||
const filePath = `${args.output}/${fileName}.ts`;
|
||||
fs.writeFileSync(filePath, renderedTsCode);
|
||||
utils.log(`Created: ${chalk.bold(filePath)}`);
|
||||
logUtils.log(`Created: ${chalk.bold(filePath)}`);
|
||||
}
|
||||
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output));
|
||||
const partialTemplateFileNames = globSync(`${args.templates}/partials/**/*.mustache`);
|
||||
for (const partialTemplateFileName of partialTemplateFileNames) {
|
||||
const namedContent = utils.getNamedContent(partialTemplateFileName);
|
||||
Handlebars.registerPartial(namedContent.name, namedContent.content);
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
|
||||
if (args.partials) {
|
||||
registerPartials(args.partials);
|
||||
}
|
||||
|
||||
const mainTemplate = utils.getNamedContent(`${args.templates}/${MAIN_TEMPLATE_NAME}`);
|
||||
const mainTemplate = utils.getNamedContent(args.template);
|
||||
const template = Handlebars.compile<ContextData>(mainTemplate.content);
|
||||
const abiFileNames = globSync(args.abiGlob);
|
||||
const abiFileNames = globSync(args.abis);
|
||||
|
||||
if (_.isEmpty(abiFileNames)) {
|
||||
utils.log(`${chalk.red(`No ABI files found.`)}`);
|
||||
utils.log(`Please make sure you've passed the correct folder name and that the files have
|
||||
logUtils.log(`${chalk.red(`No ABI files found.`)}`);
|
||||
logUtils.log(`Please make sure you've passed the correct folder name and that the files have
|
||||
${chalk.bold('*.json')} extensions`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
utils.log(`Found ${chalk.green(`${abiFileNames.length}`)} ${chalk.bold('ABI')} files`);
|
||||
logUtils.log(`Found ${chalk.green(`${abiFileNames.length}`)} ${chalk.bold('ABI')} files`);
|
||||
mkdirp.sync(args.output);
|
||||
}
|
||||
for (const abiFileName of abiFileNames) {
|
||||
const namedContent = utils.getNamedContent(abiFileName);
|
||||
utils.log(`Processing: ${chalk.bold(namedContent.name)}...`);
|
||||
logUtils.log(`Processing: ${chalk.bold(namedContent.name)}...`);
|
||||
const parsedContent = JSON.parse(namedContent.content);
|
||||
const ABI = _.isArray(parsedContent) ?
|
||||
parsedContent : // ABI file
|
||||
parsedContent.abi; // Truffle contracts file
|
||||
let ABI;
|
||||
if (_.isArray(parsedContent)) {
|
||||
ABI = parsedContent; // ABI file
|
||||
} else if (!_.isUndefined(parsedContent.abi)) {
|
||||
ABI = parsedContent.abi; // Truffle artifact
|
||||
} else if (!_.isUndefined(parsedContent.compilerOutput.abi)) {
|
||||
ABI = parsedContent.compilerOutput.abi; // 0x artifact
|
||||
}
|
||||
if (_.isUndefined(ABI)) {
|
||||
utils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`);
|
||||
utils.log(`Please make sure your ABI file is either an array with ABI entries or an object with the abi key`);
|
||||
logUtils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`);
|
||||
logUtils.log(
|
||||
`Please make sure your ABI file is either an array with ABI entries or a truffle artifact or 0x sol-compiler artifact`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
const methodAbis = ABI.filter((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_METHOD) as Web3.MethodAbi[];
|
||||
const methodsData = _.map(methodAbis, methodAbi => {
|
||||
_.map(methodAbi.inputs, input => {
|
||||
|
||||
let ctor = ABI.find((abi: AbiDefinition) => abi.type === ABI_TYPE_CONSTRUCTOR) as ConstructorAbi;
|
||||
if (_.isUndefined(ctor)) {
|
||||
ctor = utils.getEmptyConstructor(); // The constructor exists, but it's implicit in JSON's ABI definition
|
||||
}
|
||||
|
||||
const methodAbis = ABI.filter((abi: AbiDefinition) => abi.type === ABI_TYPE_METHOD) as MethodAbi[];
|
||||
const sanitizedMethodAbis = abiUtils.renameOverloadedMethods(methodAbis) as MethodAbi[];
|
||||
const methodsData = _.map(methodAbis, (methodAbi, methodAbiIndex: number) => {
|
||||
_.forEach(methodAbi.inputs, (input, inputIndex: number) => {
|
||||
if (_.isEmpty(input.name)) {
|
||||
// Auto-generated getters don't have parameter names
|
||||
input.name = 'index';
|
||||
input.name = `index_${inputIndex}`;
|
||||
}
|
||||
});
|
||||
// This will make templates simpler
|
||||
const methodData = {
|
||||
...methodAbi,
|
||||
singleReturnValue: methodAbi.outputs.length === 1,
|
||||
hasReturnValue: methodAbi.outputs.length !== 0,
|
||||
tsName: sanitizedMethodAbis[methodAbiIndex].name,
|
||||
functionSignature: abiUtils.getFunctionSignature(methodAbi),
|
||||
};
|
||||
return methodData;
|
||||
});
|
||||
|
||||
const eventAbis = ABI.filter((abi: AbiDefinition) => abi.type === ABI_TYPE_EVENT) as EventAbi[];
|
||||
|
||||
const contextData = {
|
||||
contractName: namedContent.name,
|
||||
ctor,
|
||||
methods: methodsData,
|
||||
events: eventAbis,
|
||||
};
|
||||
const renderedTsCode = template(contextData);
|
||||
writeOutputFile(namedContent.name, renderedTsCode);
|
||||
|
||||
8
packages/abi-gen/src/monorepo_scripts/postpublish.ts
Normal file
8
packages/abi-gen/src/monorepo_scripts/postpublish.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { postpublishUtils } from '@0xproject/monorepo-scripts';
|
||||
|
||||
import * as packageJSON from '../package.json';
|
||||
import * as tsConfigJSON from '../tsconfig.json';
|
||||
|
||||
const cwd = `${__dirname}/..`;
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
postpublishUtils.runAsync(packageJSON, tsConfigJSON, cwd);
|
||||
@@ -1,15 +1,24 @@
|
||||
import * as Web3 from 'web3';
|
||||
import { EventAbi, MethodAbi } from '@0xproject/types';
|
||||
|
||||
export enum ParamKind {
|
||||
Input = 'input',
|
||||
Output = 'output',
|
||||
}
|
||||
|
||||
export interface Method extends Web3.MethodAbi {
|
||||
export enum ContractsBackend {
|
||||
Web3 = 'web3',
|
||||
Ethers = 'ethers',
|
||||
}
|
||||
|
||||
export interface Method extends MethodAbi {
|
||||
singleReturnValue: boolean;
|
||||
hasReturnValue: boolean;
|
||||
tsName: string;
|
||||
functionSignature: string;
|
||||
}
|
||||
|
||||
export interface ContextData {
|
||||
contractName: string;
|
||||
methods: Method[];
|
||||
events: EventAbi[];
|
||||
}
|
||||
|
||||
@@ -1,47 +1,78 @@
|
||||
import { AbiType, ConstructorAbi, DataItem } from '@0xproject/types';
|
||||
import * as fs from 'fs';
|
||||
import * as _ from 'lodash';
|
||||
import * as path from 'path';
|
||||
|
||||
import {ParamKind} from './types';
|
||||
import { ContractsBackend, ParamKind } from './types';
|
||||
|
||||
export const utils = {
|
||||
solTypeToTsType(paramKind: ParamKind, solType: string): string {
|
||||
solTypeToTsType(paramKind: ParamKind, backend: ContractsBackend, solType: string, components?: DataItem[]): string {
|
||||
const trailingArrayRegex = /\[\d*\]$/;
|
||||
if (solType.match(trailingArrayRegex)) {
|
||||
const arrayItemSolType = solType.replace(trailingArrayRegex, '');
|
||||
const arrayItemTsType = utils.solTypeToTsType(paramKind, arrayItemSolType);
|
||||
const arrayTsType = `${arrayItemTsType}[]`;
|
||||
const arrayItemTsType = utils.solTypeToTsType(paramKind, backend, arrayItemSolType, components);
|
||||
const arrayTsType =
|
||||
utils.isUnionType(arrayItemTsType) || utils.isObjectType(arrayItemTsType)
|
||||
? `Array<${arrayItemTsType}>`
|
||||
: `${arrayItemTsType}[]`;
|
||||
return arrayTsType;
|
||||
} else {
|
||||
const solTypeRegexToTsType = [
|
||||
{regex: '^string$', tsType: 'string'},
|
||||
{regex: '^address$', tsType: 'string'},
|
||||
{regex: '^bool$', tsType: 'boolean'},
|
||||
{regex: '^u?int\\d*$', tsType: 'BigNumber'},
|
||||
{regex: '^bytes\\d*$', tsType: 'string'},
|
||||
{ regex: '^string$', tsType: 'string' },
|
||||
{ regex: '^address$', tsType: 'string' },
|
||||
{ regex: '^bool$', tsType: 'boolean' },
|
||||
{ regex: '^u?int\\d*$', tsType: 'BigNumber' },
|
||||
{ regex: '^bytes\\d*$', tsType: 'string' },
|
||||
];
|
||||
if (paramKind === ParamKind.Input) {
|
||||
// web3 allows to pass those an non-bignumbers and that's nice
|
||||
// but it always returns stuff as BigNumbers
|
||||
solTypeRegexToTsType.unshift({regex: '^u?int(8|16|32)?$', tsType: 'number|BigNumber'});
|
||||
// web3 and ethers allow to pass those as numbers instead of bignumbers
|
||||
solTypeRegexToTsType.unshift({
|
||||
regex: '^u?int(8|16|32)?$',
|
||||
tsType: 'number|BigNumber',
|
||||
});
|
||||
}
|
||||
if (backend === ContractsBackend.Ethers && paramKind === ParamKind.Output) {
|
||||
// ethers-contracts automatically converts small BigNumbers to numbers
|
||||
solTypeRegexToTsType.unshift({
|
||||
regex: '^u?int(8|16|32|48)?$',
|
||||
tsType: 'number',
|
||||
});
|
||||
}
|
||||
for (const regexAndTxType of solTypeRegexToTsType) {
|
||||
const {regex, tsType} = regexAndTxType;
|
||||
const { regex, tsType } = regexAndTxType;
|
||||
if (solType.match(regex)) {
|
||||
return tsType;
|
||||
}
|
||||
}
|
||||
const TUPLE_TYPE_REGEX = '^tuple$';
|
||||
if (solType.match(TUPLE_TYPE_REGEX)) {
|
||||
const componentsType = _.map(components, component => {
|
||||
const componentValueType = utils.solTypeToTsType(
|
||||
paramKind,
|
||||
backend,
|
||||
component.type,
|
||||
component.components,
|
||||
);
|
||||
const componentType = `${component.name}: ${componentValueType}`;
|
||||
return componentType;
|
||||
});
|
||||
const tsType = `{${componentsType}}`;
|
||||
return tsType;
|
||||
}
|
||||
throw new Error(`Unknown Solidity type found: ${solType}`);
|
||||
}
|
||||
},
|
||||
log(...args: any[]): void {
|
||||
console.log(...args); // tslint:disable-line:no-console
|
||||
isUnionType(tsType: string): boolean {
|
||||
return tsType === 'number|BigNumber';
|
||||
},
|
||||
isObjectType(tsType: string): boolean {
|
||||
return /^{.*}$/.test(tsType);
|
||||
},
|
||||
getPartialNameFromFileName(filename: string): string {
|
||||
const name = path.parse(filename).name;
|
||||
return name;
|
||||
},
|
||||
getNamedContent(filename: string): {name: string; content: string} {
|
||||
getNamedContent(filename: string): { name: string; content: string } {
|
||||
const name = utils.getPartialNameFromFileName(filename);
|
||||
try {
|
||||
const content = fs.readFileSync(filename).toString();
|
||||
@@ -53,4 +84,12 @@ export const utils = {
|
||||
throw new Error(`Failed to read ${filename}: ${err}`);
|
||||
}
|
||||
},
|
||||
getEmptyConstructor(): ConstructorAbi {
|
||||
return {
|
||||
type: AbiType.Constructor,
|
||||
stateMutability: 'nonpayable',
|
||||
payable: false,
|
||||
inputs: [],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"lib": ["es2015", "dom"],
|
||||
"outDir": "lib",
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*",
|
||||
"./test/**/*",
|
||||
"../../node_modules/web3-typescript-typings/index.d.ts"
|
||||
]
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*"]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
{
|
||||
"extends": [
|
||||
"@0xproject/tslint-config"
|
||||
]
|
||||
"extends": ["@0xproject/tslint-config"]
|
||||
}
|
||||
|
||||
7
packages/assert/.npmignore
Normal file
7
packages/assert/.npmignore
Normal file
@@ -0,0 +1,7 @@
|
||||
.*
|
||||
yarn-error.log
|
||||
/src/
|
||||
/scripts/
|
||||
test/
|
||||
tsconfig.json
|
||||
/lib/src/monorepo_scripts/
|
||||
139
packages/assert/CHANGELOG.json
Normal file
139
packages/assert/CHANGELOG.json
Normal file
@@ -0,0 +1,139 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1531149657,
|
||||
"version": "0.2.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1529397769,
|
||||
"version": "0.2.12",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.2.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Incorrect publish that was unpublished"
|
||||
}
|
||||
],
|
||||
"timestamp": 1527810075
|
||||
},
|
||||
{
|
||||
"timestamp": 1527008270,
|
||||
"version": "0.2.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1525477860,
|
||||
"version": "0.2.9",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1525428773,
|
||||
"version": "0.2.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1524044013,
|
||||
"version": "0.2.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1523462196,
|
||||
"version": "0.2.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1522673609,
|
||||
"version": "0.2.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1522658513,
|
||||
"version": "0.2.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Rename `isHttpUrl` to `isWebUri`",
|
||||
"pr": 412
|
||||
}
|
||||
],
|
||||
"timestamp": 1520434800
|
||||
},
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Remove isETHAddressHex checksum address check and assume address will be lowercased ",
|
||||
"pr": 373
|
||||
},
|
||||
{
|
||||
"note": "Add an optional parameter `subSchemas` to `doesConformToSchema` method",
|
||||
"pr": 385
|
||||
}
|
||||
],
|
||||
"timestamp": 1520089200
|
||||
},
|
||||
{
|
||||
"version": "0.0.18",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fix publishing issue where .npmignore was not properly excluding undesired content",
|
||||
"pr": 389
|
||||
}
|
||||
],
|
||||
"timestamp": 1486566000
|
||||
},
|
||||
{
|
||||
"version": "0.0.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Re-publish Assert previously published under NPM package @0xproject/0x-assert"
|
||||
},
|
||||
{
|
||||
"note":
|
||||
"Added assertion isValidBaseUnitAmount which checks both that the value is a valid bigNumber and that it does not contain decimals."
|
||||
}
|
||||
],
|
||||
"timestamp": 1510585200
|
||||
}
|
||||
]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user