Compare commits
1436 Commits
@0xproject
...
@0xproject
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8d4f6d532 | ||
|
|
631e7e9c58 | ||
|
|
c44f9e56ad | ||
|
|
2fe209d5ff | ||
|
|
7d8badc86e | ||
|
|
854d65b51b | ||
|
|
df773d07f3 | ||
|
|
efdbc1ff6c | ||
|
|
a9b5faa787 | ||
|
|
49a54c0ff6 | ||
|
|
70d403e6f8 | ||
|
|
eecf09f515 | ||
|
|
61fc3346c2 | ||
|
|
b7e98abc43 | ||
|
|
073bf738dd | ||
|
|
68e8d6f304 | ||
|
|
524e4707d2 | ||
|
|
a0fac663f7 | ||
|
|
277e58c2e5 | ||
|
|
774ab8a8ef | ||
|
|
21dc94b709 | ||
|
|
d6176872f7 | ||
|
|
c396be42b9 | ||
|
|
7f7ddee0f9 | ||
|
|
b99c797945 | ||
|
|
59edca4166 | ||
|
|
fbba5e054a | ||
|
|
ea47613d90 | ||
|
|
9d18f751c8 | ||
|
|
9745dfe2f4 | ||
|
|
29d38593d6 | ||
|
|
d76bc18bb7 | ||
|
|
cbe61ac315 | ||
|
|
250d97a7c4 | ||
|
|
249bf0163d | ||
|
|
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 |
@@ -6,23 +6,207 @@ jobs:
|
|||||||
- image: circleci/node:6.12
|
- image: circleci/node:6.12
|
||||||
environment:
|
environment:
|
||||||
CONTRACTS_COMMIT_HASH: '9ed05f5'
|
CONTRACTS_COMMIT_HASH: '9ed05f5'
|
||||||
|
working_directory: ~/repo
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
|
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
|
||||||
|
- restore_cache:
|
||||||
|
key: dependency-cache-{{ checksum "package.json" }}
|
||||||
- run:
|
- run:
|
||||||
name: yarn
|
name: yarn
|
||||||
command: yarn
|
command: yarn --frozen-lockfile
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: dependency-cache-{{ checksum "package.json" }}
|
key: dependency-cache-{{ checksum "package.json" }}
|
||||||
paths:
|
paths:
|
||||||
- ~/.cache/yarn
|
- ./node_modules
|
||||||
- run: wget https://s3.amazonaws.com/testrpc-shapshots/${CONTRACTS_COMMIT_HASH}.zip
|
- run: wget https://s3.amazonaws.com/testrpc-shapshots/${CONTRACTS_COMMIT_HASH}.zip
|
||||||
- run: unzip ${CONTRACTS_COMMIT_HASH}.zip -d testrpc_snapshot
|
- run: unzip ${CONTRACTS_COMMIT_HASH}.zip -d testrpc_snapshot
|
||||||
- run: node ./node_modules/lerna/bin/lerna.js bootstrap
|
- run: node ./node_modules/lerna/bin/lerna.js bootstrap
|
||||||
- run: yarn lerna:run build
|
- run: yarn lerna:run build
|
||||||
|
- save_cache:
|
||||||
|
key: repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
paths:
|
||||||
|
- ~/repo
|
||||||
|
test-installation:
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:6.12
|
||||||
|
working_directory: ~/repo
|
||||||
|
steps:
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
- run: yarn test:installation
|
||||||
|
test-0xjs:
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:6.12
|
||||||
|
working_directory: ~/repo
|
||||||
|
steps:
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
- run:
|
- run:
|
||||||
name: testrpc
|
name: testrpc
|
||||||
command: npm run testrpc -- --db testrpc_snapshot
|
command: npm run testrpc -- --db testrpc_snapshot
|
||||||
background: true
|
background: true
|
||||||
- run: yarn lerna:run test:circleci
|
- run: yarn lerna:run --scope 0x.js test:circleci
|
||||||
|
- save_cache:
|
||||||
|
key: coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
paths:
|
||||||
|
- ~/repo/packages/0x.js/coverage/lcov.info
|
||||||
|
test-contracts:
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:6.12
|
||||||
|
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 --scope contracts test:circleci
|
||||||
|
- save_cache:
|
||||||
|
key: coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
paths:
|
||||||
|
- ~/repo/packages/contracts/coverage/lcov.info
|
||||||
|
test-deployer:
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:6.12
|
||||||
|
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 --scope @0xproject/deployer test:circleci
|
||||||
|
- save_cache:
|
||||||
|
key: coverage-deployer-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
paths:
|
||||||
|
- ~/repo/packages/deployer/coverage/lcov.info
|
||||||
|
test-rest:
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:6.12
|
||||||
|
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 --ignore contracts --ignore 0x.js --ignore @0xproject/deployer test:circleci
|
||||||
|
- 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
|
||||||
|
lint:
|
||||||
|
working_directory: ~/repo
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:6.12
|
||||||
|
steps:
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
- run: yarn lerna:run lint
|
- run: yarn lerna:run lint
|
||||||
|
prettier:
|
||||||
|
working_directory: ~/repo
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:6.12
|
||||||
|
steps:
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
- run: yarn prettier:ci
|
||||||
|
submit-coverage:
|
||||||
|
docker:
|
||||||
|
- image: circleci/node:6.12
|
||||||
|
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-deployer-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- coverage-0xjs-{{ .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-deployer:
|
||||||
|
requires:
|
||||||
|
- build
|
||||||
|
- test-rest:
|
||||||
|
requires:
|
||||||
|
- build
|
||||||
|
- prettier:
|
||||||
|
requires:
|
||||||
|
- build
|
||||||
|
- lint:
|
||||||
|
requires:
|
||||||
|
- build
|
||||||
|
- submit-coverage:
|
||||||
|
requires:
|
||||||
|
- test-0xjs
|
||||||
|
- test-deployer
|
||||||
|
- 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
|
||||||
15
.gitignore
vendored
15
.gitignore
vendored
@@ -68,6 +68,21 @@ generated_docs/
|
|||||||
TODO.md
|
TODO.md
|
||||||
|
|
||||||
packages/website/public/bundle*
|
packages/website/public/bundle*
|
||||||
|
packages/react-docs/example/public/bundle*
|
||||||
|
|
||||||
# generated binaries
|
# generated binaries
|
||||||
bin/
|
bin/
|
||||||
|
|
||||||
|
# generated contract artifacts
|
||||||
|
packages/contracts/src/artifacts
|
||||||
|
|
||||||
|
# generated contract wrappers
|
||||||
|
packages/0x.js/src/contract_wrappers/generated/
|
||||||
|
packages/contracts/src/contract_wrappers/generated/
|
||||||
|
packages/metacoin/src/contract_wrappers
|
||||||
|
|
||||||
|
# solc-bin in deployer
|
||||||
|
packages/deployer/solc_bin/
|
||||||
|
|
||||||
|
# Monorepo scripts
|
||||||
|
packages/*/scripts/
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
.*
|
|
||||||
tsconfig.json
|
|
||||||
tslint.json
|
|
||||||
webpack.config.js
|
|
||||||
yarn.lock
|
|
||||||
docs
|
|
||||||
5
.prettierignore
Normal file
5
.prettierignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
lib
|
||||||
|
.nyc_output
|
||||||
|
/packages/contracts/src/artifacts
|
||||||
|
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
|
||||||
|
}
|
||||||
1
CODEOWNERS
Normal file
1
CODEOWNERS
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* @abandeali1 @BMillman19 @dekz @fabioberger @LogvinovLeon @Recmo
|
||||||
@@ -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!
|
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:
|
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 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
|
* 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/)
|
* Write [good commit messages](https://chris.beams.io/posts/git-commit/)
|
||||||
|
|
||||||
### Code quality
|
### Code quality
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@ If the sub-package you are modifying has a `CHANGELOG.md` file, make sure to add
|
|||||||
|
|
||||||
### Styleguide
|
### 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`
|
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:
|
If using the Atom text editor, we recommend you install the following packages:
|
||||||
|
|
||||||
* [atom-typescript](https://atom.io/packages/atom-typescript)
|
* [atom-typescript](https://atom.io/packages/atom-typescript)
|
||||||
* [linter-tslint](https://atom.io/packages/linter-tslint)
|
* [linter-tslint](https://atom.io/packages/linter-tslint)
|
||||||
* [prettier-atom](https://atom.io/packages/prettier-atom)
|
* [prettier-atom](https://atom.io/packages/prettier-atom)
|
||||||
* [language-ethereum](https://atom.io/packages/language-ethereum)
|
* [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.
|
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,42 @@
|
|||||||
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 CHANGELOGs.
|
||||||
|
* [ ] Updated the new versions of the changed packages in the relevant CHANGELOGs.
|
||||||
|
* [ ] 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.
|
||||||
|
|||||||
97
README.md
97
README.md
@@ -4,50 +4,71 @@
|
|||||||
|
|
||||||
[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].
|
[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/
|
[website-url]: https://0xproject.com/
|
||||||
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
||||||
|
|
||||||
[](https://circleci.com/gh/0xProject/0x.js)
|
[](https://circleci.com/gh/0xProject/0x-monorepo)
|
||||||
[](https://coveralls.io/github/0xProject/0x.js?branch=master)
|
[](https://coveralls.io/github/0xProject/0x-monorepo?branch=development)
|
||||||
[](https://chat.0xproject.com)
|
||||||
)](https://chat.0xproject.com)
|
|
||||||
[](https://gitter.im/0xProject/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](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://opensource.org/licenses/Apache-2.0)
|
||||||
[](https://greenkeeper.io/)
|
[](https://greenkeeper.io/)
|
||||||
|
|
||||||
### Published Packages
|
### Published Packages
|
||||||
|
|
||||||
| Package | Version | Description |
|
| Package | Version | Description |
|
||||||
|---------|---------|-------------|
|
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
||||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
| [`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/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/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/base-contract`](/packages/base-contract) | [](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
|
||||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the Standard Relayer API |
|
||||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
| [`@0xproject/deployer`](/packages/deployer) | [](https://www.npmjs.com/package/@0xproject/deployer) | Solidity project compiler and deployer framework |
|
||||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
| [`@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/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | [](https://www.npmjs.com/package/@0xproject/monorepo-scripts) | Monorepo scripts |
|
||||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
|
| [`@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 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
|
### Private Packages
|
||||||
|
|
||||||
| Package | Description |
|
| Package | Description |
|
||||||
|---------|-------------|
|
| --------------------------------------------------------------- | ---------------------------------------------------------------- |
|
||||||
| [`@0xproject/contracts`](/packages/contracts) | 0x solidity smart contracts & tests |
|
| [`@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/react-docs-example`](/packages/react-docs-example) | Example documentation site created with `@0xproject/react-docs` |
|
||||||
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | Shared monorepo scripts |
|
| [`@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 |
|
| [`@0xproject/website`](/packages/website) | 0x website & Portal DApp |
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Dedicated documentation pages:
|
Dedicated documentation pages:
|
||||||
- [0x.js Library](https://0xproject.com/docs/0xjs)
|
|
||||||
- [0x Connect](https://0xproject.com/docs/connect)
|
* [0x.js Library](https://0xproject.com/docs/0xjs)
|
||||||
- [Smart contracts](https://0xproject.com/docs/contracts)
|
* [0x Connect](https://0xproject.com/docs/connect)
|
||||||
- [Standard Relayer API](https://github.com/0xProject/standard-relayer-api/blob/master/README.md)
|
* [Smart contracts](https://0xproject.com/docs/contracts)
|
||||||
|
* [Subproviders](https://0xproject.com/docs/subproviders)
|
||||||
|
* [Deployer](https://0xproject.com/docs/deployer)
|
||||||
|
* [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)
|
||||||
|
|
||||||
|
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
|
## Contributing
|
||||||
|
|
||||||
@@ -58,26 +79,39 @@ Please read our [contribution guidelines](./CONTRIBUTING.md) before getting star
|
|||||||
### Install dependencies
|
### Install dependencies
|
||||||
|
|
||||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn config set workspaces-experimental true
|
yarn config set workspaces-experimental true
|
||||||
```
|
```
|
||||||
|
|
||||||
Then install dependencies
|
Then install dependencies
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn install
|
yarn install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
Build all packages
|
Build all packages. You need to do this before working on any given package. Although these packages
|
||||||
|
as independent, when run from within the monorepo, they are internally symlinked, to make development
|
||||||
|
easier. You can change several packages and run the changes without publishing them first to NPM. When
|
||||||
|
running `rebuild`, Lerna will figure out the dependency order of all the packages, and build them in
|
||||||
|
this order.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn lerna:run build
|
yarn lerna:rebuild
|
||||||
|
```
|
||||||
|
|
||||||
|
Or continuously rebuild on change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Lint
|
### Lint
|
||||||
|
|
||||||
Lint all packages
|
Lint all packages
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn lerna:run lint
|
yarn lerna:run lint
|
||||||
```
|
```
|
||||||
@@ -87,11 +121,13 @@ yarn lerna:run lint
|
|||||||
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.
|
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.
|
||||||
|
|
||||||
In a separate terminal, start TestRPC (a convenience command is provided as part of this repo)
|
In a separate terminal, start TestRPC (a convenience command is provided as part of this repo)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn testrpc
|
yarn testrpc
|
||||||
```
|
```
|
||||||
|
|
||||||
Then in your main terminal run
|
Then in your main terminal run
|
||||||
|
|
||||||
```
|
```
|
||||||
cd packages/contracts
|
cd packages/contracts
|
||||||
yarn migrate
|
yarn migrate
|
||||||
@@ -99,6 +135,7 @@ cd ..
|
|||||||
```
|
```
|
||||||
|
|
||||||
And finally from the root project directory run
|
And finally from the root project directory run
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn lerna:run test
|
yarn lerna:run test
|
||||||
```
|
```
|
||||||
|
|||||||
22
lerna.json
22
lerna.json
@@ -1,9 +1,17 @@
|
|||||||
{
|
{
|
||||||
"lerna": "2.5.1",
|
"lerna": "2.5.1",
|
||||||
"packages": [
|
"packages": ["packages/*"],
|
||||||
"packages/*"
|
"commands": {
|
||||||
],
|
"publish": {
|
||||||
"version": "independent",
|
"allowBranch": "development"
|
||||||
"npmClient": "yarn",
|
}
|
||||||
"useWorkspaces": true
|
},
|
||||||
|
"version": "independent",
|
||||||
|
"commands": {
|
||||||
|
"publish": {
|
||||||
|
"ignore": ["test/**/*", "*.md", "scripts", "lib", "tslint.json", "tsconfig.json"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"npmClient": "yarn",
|
||||||
|
"useWorkspaces": true
|
||||||
}
|
}
|
||||||
|
|||||||
27
package.json
27
package.json
@@ -1,24 +1,37 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "0x.js",
|
"name": "0x-monorepo",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"dev": "lerna run --parallel build:watch",
|
||||||
"testrpc": "testrpc -p 8545 --networkId 50 -m \"${npm_package_config_mnemonic}\"",
|
"testrpc": "testrpc -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",
|
||||||
|
"lerna:install": "yarn install",
|
||||||
"lerna:run": "lerna run",
|
"lerna:run": "lerna run",
|
||||||
"lerna:rebuild": "lerna run clean; lerna run build;",
|
"lerna:clean": "lerna run clean",
|
||||||
"lerna:publish": "yarn install; lerna run clean; lerna run build; lerna publish --registry=https://registry.npmjs.org/"
|
"lerna:build": "lerna run build",
|
||||||
|
"lerna:rebuild": "run-s lerna:clean lerna:build",
|
||||||
|
"lerna:publish": "run-s lerna:install lerna:rebuild script:publish",
|
||||||
|
"lerna:publish:dry": "run-s lerna:install lerna:rebuild script:publish:dry",
|
||||||
|
"lerna:stage_docs": "lerna run docs:stage",
|
||||||
|
"script:publish": "node ./packages/monorepo-scripts/lib/publish.js",
|
||||||
|
"script:publish:dry": "IS_DRY_RUN=true yarn script:publish"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
|
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0xproject/utils": "^0.1.0",
|
|
||||||
"async-child-process": "^1.1.1",
|
"async-child-process": "^1.1.1",
|
||||||
"ethereumjs-testrpc": "6.0.3",
|
"coveralls": "^3.0.0",
|
||||||
|
"ethereumjs-testrpc": "^6.0.3",
|
||||||
|
"lcov-result-merger": "^2.0.0",
|
||||||
"lerna": "^2.5.1",
|
"lerna": "^2.5.1",
|
||||||
"publish-release": "0xproject/publish-release",
|
"npm-run-all": "^4.1.2",
|
||||||
"semver-sort": "^0.0.4"
|
"prettier": "^1.11.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
packages/0x.js/.npmignore
Normal file
11
packages/0x.js/.npmignore
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
.*
|
||||||
|
tsconfig.json
|
||||||
|
webpack.config.js
|
||||||
|
yarn-error.log
|
||||||
|
test/
|
||||||
|
/src/
|
||||||
|
/_bundles/
|
||||||
|
/contract_templates/
|
||||||
|
/generated_docs/
|
||||||
|
/scripts/
|
||||||
|
/lib/src/monorepo_scripts/
|
||||||
977
packages/0x.js/CHANGELOG.json
Normal file
977
packages/0x.js/CHANGELOG.json
Normal file
@@ -0,0 +1,977 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"version": "0.36.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Moved Web3.Provider to `@0xproject/types:Provider`",
|
||||||
|
"pr": 501
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1523462196
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.35.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3_wrapper' `Web3WrapperErrors.TransactionMiningTimeout`",
|
||||||
|
"pr": 485
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1522673609
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.34.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Fix the bug causing `zeroEx.exchange.fillOrdersUpToAsync` validation to fail if there were some extra orders passed",
|
||||||
|
"pr": 470
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove automatic instantiation of `zeroEx.orderStateWatcher`",
|
||||||
|
"pr": 488
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add `zeroEx.createOrderStateWatcher` to allow creating arbitrary number of OrderStateWatchers",
|
||||||
|
"pr": 488
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Added `stateLayer` setting to `OrderStateWatcherConfig` so OrderStateWatcher can be set to monitor different blockchain state layers",
|
||||||
|
"pr": 488
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1522658513
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.33.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package",
|
||||||
|
"pr": 452
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Consolidate `Order`, `SignedOrder`, and `ECSignature` into the `@0xproject/types` package",
|
||||||
|
"pr": 456
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1521298800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.33.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add missing EthersJs typescript typings as dependency"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1520434800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.33.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Validate and lowercase all addresses in public methods",
|
||||||
|
"pr": 373
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Improve validation to force passing contract addresses on private networks",
|
||||||
|
"pr": 385
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Change `LogErrorContractEventArgs.errorId` type from `BigNumber` to `number`",
|
||||||
|
"pr": 413
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Rename all public `_unsubscribeAll` methods to `unsubscribeAll`",
|
||||||
|
"pr": 415
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Move web3 typings from devDep to dep since cannot use this package without it",
|
||||||
|
"pr": 429
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1520089200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.32.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fix publishing issue where .npmignore was not properly excluding undesired content",
|
||||||
|
"pr": 389
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1518102000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.32.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Reorganized `BlockParamLiteral` export into `@0xproject/types` package",
|
||||||
|
"pr": 355
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Now using `abi-gen` package to generate ContractEventArgs types",
|
||||||
|
"pr": 371
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1517929200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.32.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add `zeroEx.etherToken.getContractAddressIfExists`",
|
||||||
|
"pr": 350
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Fixed the bug causing order watcher to throw if there is an event with the same signature but different indexed fields",
|
||||||
|
"pr": 366
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1517756400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.31.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fix the bug causing order watcher to throw if makerToken === zrx",
|
||||||
|
"pr": 357
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1517410800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.31.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"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.",
|
||||||
|
"pr": 349
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1517238000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.30.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add Rinkeby testnet addresses to artifacts ",
|
||||||
|
"pr": 337
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Move @0xproject/types to dependencies from devDependencies fixing missing type errors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1517151600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.30.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fix a bug allowing negative fill values ",
|
||||||
|
"pr": 212
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fix a bug that made it impossible to pass a custom ZRX address ",
|
||||||
|
"pr": 341
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1516719600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.30.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add an error parameter to the order watcher callback",
|
||||||
|
"pr": 312
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fix a bug making it impossible to catch some errors from awaitTransactionMinedAsync",
|
||||||
|
"pr": 312
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"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",
|
||||||
|
"pr": 321
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1516114800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.29.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed bignumber config issue #301",
|
||||||
|
"pr": 305
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1515596400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.29.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Assert baseUnit amount supplied to `toUnitAmount` is integer amount.",
|
||||||
|
"pr": 287
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "`toBaseUnitAmount` throws if amount supplied has too many decimals",
|
||||||
|
"pr": 287
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1514386800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.28.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken`",
|
||||||
|
"pr": 267
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Removed accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry`",
|
||||||
|
"pr": 267
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Removed `etherTokenContractAddress` from `ZeroEx` constructor arg `ZeroExConfig`",
|
||||||
|
"pr": 267
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Rename `SubscriptionOpts` to `BlockRange`",
|
||||||
|
"pr": 272
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Add `zeroEx.etherToken.subscribe`, `zeroEx.etherToken.unsubscribe`, `zeroEx.etherToken.unsubscribeAll`",
|
||||||
|
"pr": 277
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add `zeroEx.etherToken.getLogsAsync`",
|
||||||
|
"pr": 277
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Add new public types `BlockParamLiteral`, `EtherTokenEvents`, `EtherTokenContractEventArgs`, `DepositContractEventArgs`, `WithdrawalContractEventArgs`",
|
||||||
|
"pr": 277
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Support `Deposit` and `Withdraw` events on etherToken",
|
||||||
|
"pr": 277
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Improve the error message when taker is not a string",
|
||||||
|
"pr": 278
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1513695600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.27.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Export `TransactionOpts` type"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1511794800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.27.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Make `ZeroExConfig` required parameter of `ZeroEx` constructor",
|
||||||
|
"pr": 233
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add a required property `networkId` to `ZeroExConfig`",
|
||||||
|
"pr": 233
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Make all `getContractAddress` functions, `zeroEx.exchange.subscribe`, `zeroEx.exchange.getZRXTokenAddress` sync",
|
||||||
|
"pr": 233
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove `ZeroExError.ContractNotFound` and replace it with contract-specific errors",
|
||||||
|
"pr": 233
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Make `DecodedLogEvent<A>` contain `LogWithDecodedArgs<A>` under log key instead of merging it in like web3 does",
|
||||||
|
"pr": 234
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Rename `removed` to `isRemoved` in `DecodedLogEvent<A>`",
|
||||||
|
"pr": 234
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add config allowing to specify gasPrice and gasLimit for every transaction sending method",
|
||||||
|
"pr": 235
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "All transaction sending methods now call `estimateGas` if no gas amount was supplied",
|
||||||
|
"pr": 235
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Modify order validation methods to validate against the `latest` block, not against the `pending` block",
|
||||||
|
"pr": 236
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1511794800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.26.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Add post-formatter for logs converting `blockNumber`, `logIndex`, `transactionIndex` from hexes to numbers",
|
||||||
|
"pr": 231
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove support for Async callback types when used in Subscribe functions",
|
||||||
|
"pr": 222
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"In OrderWatcher subscribe to ZRX Token Transfer and Approval events when maker token is different",
|
||||||
|
"pr": 225
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1511190000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.25.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Standardise on Cancelled over Canceled",
|
||||||
|
"pr": 217
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add missing `DecodedLogEvent` type to exported types",
|
||||||
|
"pr": 205
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"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.",
|
||||||
|
"pr": 200
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1510498800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.23.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed unhandled promise rejection error in subscribe methods",
|
||||||
|
"pr": 209
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Subscribe callbacks now receive an error object as their first argument"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1510412400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.22.6",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add a timeout parameter to transaction awaiting",
|
||||||
|
"pr": 206
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1510239600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.22.5",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Re-publish v0.22.4 to fix publishing issue"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1509980400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.22.4",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Upgraded bignumber.js to a new version that ships with native typings"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1508857200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.22.3",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed an issue with new version of testrpc and unlimited proxy allowance",
|
||||||
|
"pr": 199
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1508857200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.22.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed rounding of maker fill amount and incorrect validation of partial fees",
|
||||||
|
"pr": 197
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1508770800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.22.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Started using `OrderFillRequest` interface instead of `OrderFillOrKillRequest` interface for `zeroEx.exchange.batchFillOrKill`",
|
||||||
|
"pr": 187
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Removed `OrderFillOrKillRequest`",
|
||||||
|
"pr": 187
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1508079600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.21.4",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Made 0x.js more type-safe by making `getLogsAsync` and `subscribe/subscribeAsync` generics parametrized with arg type",
|
||||||
|
"pr": 194
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1507820400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.21.3",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed a bug causing order fills to throw `INSUFFICIENT_TAKER_ALLOWANCE`",
|
||||||
|
"pr": 193
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1507734000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.21.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Exported `ContractEventArg` as a public type",
|
||||||
|
"pr": 190
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1507647600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.21.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed a bug in subscriptions",
|
||||||
|
"pr": 189
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1507647600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.21.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Complete rewrite of subscription logic",
|
||||||
|
"pr": 182
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Subscriptions no longer return historical logs. If you want them - use `getLogsAsync`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Subscriptions now use [ethereumjs-blockstream](https://github.com/ethereumjs/ethereumjs-blockstream) under the hood"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Subscriptions correctly handle block re-orgs (forks)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Subscriptions correctly backfill logs (connection problems)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"They no longer setup filters on the underlying nodes, so you can use them with infura without a filter Subprovider"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Removed `ContractEventEmitter` and added `LogEvent`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Renamed `zeroEx.token.subscribeAsync` to `zeroEx.token.subscribe`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.token.unsubscribe` and `zeroEx.exchange.unsubscribe`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Renamed `zeroEx.exchange.stopWatchingAllEventsAsync` to `zeroEx.exhange.unsubscribeAll`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Renamed `zeroEx.token.stopWatchingAllEventsAsync` to `zeroEx.token.unsubscribeAll`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fixed the batch fills validation by emulating all balance & proxy allowance changes",
|
||||||
|
"pr": 185
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1507561200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.20.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add `zeroEx.token.getLogsAsync`",
|
||||||
|
"pr": 178
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add `zeroEx.exchange.getLogsAsync`",
|
||||||
|
"pr": 178
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fixed fees validation when one of the tokens transferred is ZRX",
|
||||||
|
"pr": 181
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1507129200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.19.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Made order validation optional ",
|
||||||
|
"pr": 172
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added Ropsten testnet support",
|
||||||
|
"pr": 173
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fixed a bug causing awaitTransactionMinedAsync to DDos backend nodes",
|
||||||
|
"pr": 175
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1506610800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.18.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.exchange.validateOrderFillableOrThrowAsync` to simplify orderbook pruning",
|
||||||
|
"pr": 170
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1506351600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.17.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Made `zeroEx.exchange.getZRXTokenAddressAsync` public",
|
||||||
|
"pr": 171
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1506351600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.16.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added the ability to specify custom contract addresses to be used with 0x.js",
|
||||||
|
"pr": 165
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "ZeroExConfig.exchangeContractAddress"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "ZeroExConfig.tokenRegistryContractAddress"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "ZeroExConfig.etherTokenContractAddress"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.tokenRegistry.getContractAddressAsync`",
|
||||||
|
"pr": 165
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1505833200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.15.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Added the ability to specify a historical `blockNumber` at which to query the blockchain's state when calling a token or exchange method",
|
||||||
|
"pr": 161
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1504796400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.14.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed an issue with bignumber.js types not found",
|
||||||
|
"pr": 160
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1504710000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.14.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed an issue with Artifact type not found",
|
||||||
|
"pr": 159
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1504710000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.14.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.exchange.throwLogErrorsAsErrors` method to public interface",
|
||||||
|
"pr": 157
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fixed an issue with overlapping async intervals in `zeroEx.awaitTransactionMinedAsync`",
|
||||||
|
"pr": 157
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fixed an issue with log decoder returning `BigNumber`s as `strings`",
|
||||||
|
"pr": 157
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1504623600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.13.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Made all the functions submitting transactions to the network to immediately return transaction hash",
|
||||||
|
"pr": 151
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.awaitTransactionMinedAsync`",
|
||||||
|
"pr": 151
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Added `TransactionReceiptWithDecodedLogs`, `LogWithDecodedArgs`, `DecodedLogArgs` to public types",
|
||||||
|
"pr": 151
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added signature validation to `validateFillOrderThrowIfInvalidAsync`",
|
||||||
|
"pr": 152
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1504623600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.12.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added the support for web3@1.x.x provider",
|
||||||
|
"pr": 142
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added the optional `zeroExConfig` parameter to the constructor of `ZeroEx`",
|
||||||
|
"pr": 139
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added the ability to specify `gasPrice` when instantiating `ZeroEx`",
|
||||||
|
"pr": 139
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1504278000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.11.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.token.setUnlimitedProxyAllowanceAsync`",
|
||||||
|
"pr": 137
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.token.setUnlimitedAllowanceAsync`",
|
||||||
|
"pr": 137
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS`",
|
||||||
|
"pr": 137
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1503500400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.10.4",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed a bug where checksummed addresses were being pulled from artifacts and not lower-cased.",
|
||||||
|
"pr": 135
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1503500400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.10.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.exchange.validateFillOrderThrowIfInvalidAsync`",
|
||||||
|
"pr": 128
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync`",
|
||||||
|
"pr": 128
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync`",
|
||||||
|
"pr": 128
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.exchange.isRoundingErrorAsync`",
|
||||||
|
"pr": 128
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.proxy.getContractAddressAsync`",
|
||||||
|
"pr": 130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.tokenRegistry.getTokenAddressesAsync`",
|
||||||
|
"pr": 132
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync`",
|
||||||
|
"pr": 132
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync`",
|
||||||
|
"pr": 132
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync`",
|
||||||
|
"pr": 132
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.tokenRegistry.getTokenByNameIfExistsAsync`",
|
||||||
|
"pr": 132
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added clear error message when checksummed address is passed to a public method",
|
||||||
|
"pr": 124
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fixes the description of `shouldThrowOnInsufficientBalanceOrAllowance` in docs",
|
||||||
|
"pr": 127
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1503500400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.9.3",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Update contract artifacts to include latest Kovan and Mainnet deploys",
|
||||||
|
"pr": 118
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1503327600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.9.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "*This version was unpublished because of a publishing issue.*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Update contract artifacts to include latest Kovan and Mainnet deploys",
|
||||||
|
"pr": 118
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1503241200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.9.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed the bug causing `zeroEx.token.getBalanceAsync()` to fail if no addresses available",
|
||||||
|
"pr": 120
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1502809200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.9.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Migrated to the new version of smart contracts",
|
||||||
|
"pr": 101
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Removed the ability to call methods on multiple authorized Exchange smart contracts",
|
||||||
|
"pr": 106
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Made `zeroEx.getOrderHashHex` a static method",
|
||||||
|
"pr": 107
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Cached `net_version` requests and invalidate the cache on calls to `setProvider`",
|
||||||
|
"pr": 95
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Renamed `zeroEx.exchange.batchCancelOrderAsync` to `zeroEx.exchange.batchCancelOrdersAsync`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Renamed `zeroEx.exchange.batchFillOrderAsync` to `zeroEx.exchange.batchFillOrdersAsync`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Updated to typescript v2.4",
|
||||||
|
"pr": 104
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Fixed an issue with incorrect balance/allowance validation when ZRX is one of the tokens traded",
|
||||||
|
"pr": 109
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1500994800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.8.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Added the ability to call methods on different authorized versions of the Exchange smart contract",
|
||||||
|
"pr": 82
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Updated contract artifacts to reflect latest changes to the smart contracts (0xproject/contracts#59)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.proxy.isAuthorizedAsync` and `zeroEx.proxy.getAuthorizedAddressesAsync`",
|
||||||
|
"pr": 89
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `zeroEx.token.subscribeAsync`",
|
||||||
|
"pr": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Made contract invalidation functions private",
|
||||||
|
"pr": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "`zeroEx.token.invalidateContractInstancesAsync`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "`zeroEx.exchange.invalidateContractInstancesAsync`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "`zeroEx.proxy.invalidateContractInstance`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "`zeroEx.tokenRegistry.invalidateContractInstance`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fixed the bug where `zeroEx.setProviderAsync` didn't invalidate etherToken contract's instance"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1499094000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.7.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Added the ability to convert Ether to wrapped Ether tokens and back via `zeroEx.etherToken.depostAsync` and `zeroEx.etherToken.withdrawAsync`",
|
||||||
|
"pr": 81
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1498402800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.7.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added Kovan smart contract artifacts",
|
||||||
|
"pr": 78
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Started returning fillAmount from `fillOrderAsync` and `fillUpToAsync`",
|
||||||
|
"pr": 72
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Started returning cancelledAmount from `cancelOrderAsync`",
|
||||||
|
"pr": 72
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Renamed type `LogCancelArgs` to `LogCancelContractEventArgs` and `LogFillArgs` to `LogFillContractEventArgs`"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1498057200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.6.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Reduced bundle size"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Improved documentation"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1497970800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.6.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Improved documentation"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1497798000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.6.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Made `ZeroEx` class accept `Web3Provider` instance instead of `Web3` instance"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added types for contract event arguments"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1497798000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.5.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Fixed the bug in `postpublish` script that caused that only unminified UMD bundle was uploaded to release page"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1497452400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.5.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added `postpublish` script to publish to Github Releases with assets."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1497452400
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,12 +1,91 @@
|
|||||||
# 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.36.0 - _April 11, 2018_
|
||||||
|
|
||||||
|
* Moved Web3.Provider to `@0xproject/types:Provider` (#501)
|
||||||
|
|
||||||
|
## 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)
|
* Assert baseUnit amount supplied to `toUnitAmount` is integer amount. (#287)
|
||||||
* `toBaseUnitAmount` throws if amount supplied has too many decimals (#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)
|
* 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 accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry` (#267)
|
||||||
* Removed `etherTokenContractAddress` from `ZeroEx` constructor arg `ZeroExConfig` (#267)
|
* Removed `etherTokenContractAddress` from `ZeroEx` constructor arg `ZeroExConfig` (#267)
|
||||||
@@ -17,12 +96,12 @@ v0.28.0 - _December 20, 2017_
|
|||||||
* Support `Deposit` and `Withdraw` events on etherToken (#277)
|
* Support `Deposit` and `Withdraw` events on etherToken (#277)
|
||||||
* Improve the error message when taker is not a string (#278)
|
* 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
|
* Export `TransactionOpts` type
|
||||||
|
|
||||||
v0.27.0 - _November 28, 2017_
|
## v0.27.0 - _November 27, 2017_
|
||||||
------------------------
|
|
||||||
* Make `ZeroExConfig` required parameter of `ZeroEx` constructor (#233)
|
* Make `ZeroExConfig` required parameter of `ZeroEx` constructor (#233)
|
||||||
* Add a required property `networkId` to `ZeroExConfig` (#233)
|
* Add a required property `networkId` to `ZeroExConfig` (#233)
|
||||||
* Make all `getContractAddress` functions, `zeroEx.exchange.subscribe`, `zeroEx.exchange.getZRXTokenAddress` sync (#233)
|
* Make all `getContractAddress` functions, `zeroEx.exchange.subscribe`, `zeroEx.exchange.getZRXTokenAddress` sync (#233)
|
||||||
@@ -33,150 +112,150 @@ v0.27.0 - _November 28, 2017_
|
|||||||
* All transaction sending methods now call `estimateGas` if no gas amount was supplied (#235)
|
* 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)
|
* 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)
|
* 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)
|
* 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)
|
* 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)
|
* Standardise on Cancelled over Canceled (#217)
|
||||||
* Add missing `DecodedLogEvent` type to exported types (#205)
|
* 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)
|
* 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)
|
* Fixed unhandled promise rejection error in subscribe methods (#209)
|
||||||
* Subscribe callbacks now receive an error object as their first argument
|
* 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)
|
* 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
|
* 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
|
* 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)
|
* 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)
|
* 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)
|
* Started using `OrderFillRequest` interface instead of `OrderFillOrKillRequest` interface for `zeroEx.exchange.batchFillOrKill` (#187)
|
||||||
* Removed `OrderFillOrKillRequest` (#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)
|
* 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)
|
* 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)
|
* 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)
|
* Fixed a bug in subscriptions (#189)
|
||||||
|
|
||||||
v0.21.0 - _October 10, 2017_
|
## v0.21.0 - _October 9, 2017_
|
||||||
------------------------
|
|
||||||
* Complete rewrite of subscription logic (#182)
|
* Complete rewrite of subscription logic (#182)
|
||||||
* Subscriptions no longer return historical logs. If you want them - use `getLogsAsync`
|
* 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 now use [ethereumjs-blockstream](https://github.com/ethereumjs/ethereumjs-blockstream) under the hood
|
||||||
* Subscriptions correctly handle block re-orgs (forks)
|
* Subscriptions correctly handle block re-orgs (forks)
|
||||||
* Subscriptions correctly backfill logs (connection problems)
|
* 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
|
* 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`
|
* Removed `ContractEventEmitter` and added `LogEvent`
|
||||||
* Renamed `zeroEx.token.subscribeAsync` to `zeroEx.token.subscribe`
|
* Renamed `zeroEx.token.subscribeAsync` to `zeroEx.token.subscribe`
|
||||||
* Added `zeroEx.token.unsubscribe` and `zeroEx.exchange.unsubscribe`
|
* Added `zeroEx.token.unsubscribe` and `zeroEx.exchange.unsubscribe`
|
||||||
* Renamed `zeroEx.exchange.stopWatchingAllEventsAsync` to `zeroEx.exhange.unsubscribeAll`
|
* Renamed `zeroEx.exchange.stopWatchingAllEventsAsync` to `zeroEx.exhange.unsubscribeAll`
|
||||||
* Renamed `zeroEx.token.stopWatchingAllEventsAsync` to `zeroEx.token.unsubscribeAll`
|
* Renamed `zeroEx.token.stopWatchingAllEventsAsync` to `zeroEx.token.unsubscribeAll`
|
||||||
* Fixed the batch fills validation by emulating all balance & proxy allowance changes (#185)
|
* 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.token.getLogsAsync` (#178)
|
||||||
* Add `zeroEx.exchange.getLogsAsync` (#178)
|
* Add `zeroEx.exchange.getLogsAsync` (#178)
|
||||||
* Fixed fees validation when one of the tokens transferred is ZRX (#181)
|
* 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)
|
* Made order validation optional (#172)
|
||||||
* Added Ropsten testnet support (#173)
|
* Added Ropsten testnet support (#173)
|
||||||
* Fixed a bug causing awaitTransactionMinedAsync to DDos backend nodes (#175)
|
* 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)
|
* 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)
|
* 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)
|
* Added the ability to specify custom contract addresses to be used with 0x.js (#165)
|
||||||
* ZeroExConfig.exchangeContractAddress
|
* ZeroExConfig.exchangeContractAddress
|
||||||
* ZeroExConfig.tokenRegistryContractAddress
|
* ZeroExConfig.tokenRegistryContractAddress
|
||||||
* ZeroExConfig.etherTokenContractAddress
|
* ZeroExConfig.etherTokenContractAddress
|
||||||
* Added `zeroEx.tokenRegistry.getContractAddressAsync` (#165)
|
* 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)
|
* 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)
|
* 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)
|
* 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)
|
* Added `zeroEx.exchange.throwLogErrorsAsErrors` method to public interface (#157)
|
||||||
* Fixed an issue with overlapping async intervals in `zeroEx.awaitTransactionMinedAsync` (#157)
|
* Fixed an issue with overlapping async intervals in `zeroEx.awaitTransactionMinedAsync` (#157)
|
||||||
* Fixed an issue with log decoder returning `BigNumber`s as `strings` (#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)
|
* Made all the functions submitting transactions to the network to immediately return transaction hash (#151)
|
||||||
* Added `zeroEx.awaitTransactionMinedAsync` (#151)
|
* Added `zeroEx.awaitTransactionMinedAsync` (#151)
|
||||||
* Added `TransactionReceiptWithDecodedLogs`, `LogWithDecodedArgs`, `DecodedLogArgs` to public types (#151)
|
* Added `TransactionReceiptWithDecodedLogs`, `LogWithDecodedArgs`, `DecodedLogArgs` to public types (#151)
|
||||||
* Added signature validation to `validateFillOrderThrowIfInvalidAsync` (#152)
|
* 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 support for web3@1.x.x provider (#142)
|
||||||
* Added the optional `zeroExConfig` parameter to the constructor of `ZeroEx` (#139)
|
* Added the optional `zeroExConfig` parameter to the constructor of `ZeroEx` (#139)
|
||||||
* Added the ability to specify `gasPrice` when instantiating `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.setUnlimitedProxyAllowanceAsync` (#137)
|
||||||
* Added `zeroEx.token.setUnlimitedAllowanceAsync` (#137)
|
* Added `zeroEx.token.setUnlimitedAllowanceAsync` (#137)
|
||||||
* Added `zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS` (#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)
|
* 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.validateFillOrderThrowIfInvalidAsync` (#128)
|
||||||
* Added `zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync` (#128)
|
* Added `zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync` (#128)
|
||||||
* Added `zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync` (#128)
|
* Added `zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync` (#128)
|
||||||
@@ -190,21 +269,21 @@ v0.10.1 - _Aug 24, 2017_
|
|||||||
* Added clear error message when checksummed address is passed to a public method (#124)
|
* Added clear error message when checksummed address is passed to a public method (#124)
|
||||||
* Fixes the description of `shouldThrowOnInsufficientBalanceOrAllowance` in docs (#127)
|
* 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)
|
* 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.*
|
* *This version was unpublished because of a publishing issue.*
|
||||||
* Update contract artifacts to include latest Kovan and Mainnet deploys (#118)
|
* 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)
|
* 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)
|
* Migrated to the new version of smart contracts (#101)
|
||||||
* Removed the ability to call methods on multiple authorized Exchange smart contracts (#106)
|
* Removed the ability to call methods on multiple authorized Exchange smart contracts (#106)
|
||||||
* Made `zeroEx.getOrderHashHex` a static method (#107)
|
* Made `zeroEx.getOrderHashHex` a static method (#107)
|
||||||
@@ -214,48 +293,48 @@ v0.9.0 - _Jul. 26, 2017_
|
|||||||
* Updated to typescript v2.4 (#104)
|
* Updated to typescript v2.4 (#104)
|
||||||
* Fixed an issue with incorrect balance/allowance validation when ZRX is one of the tokens traded (#109)
|
* 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)
|
* 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)
|
* 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.proxy.isAuthorizedAsync` and `zeroEx.proxy.getAuthorizedAddressesAsync` (#89)
|
||||||
* Added `zeroEx.token.subscribeAsync` (#90)
|
* Added `zeroEx.token.subscribeAsync` (#90)
|
||||||
* Made contract invalidation functions private (#90)
|
* Made contract invalidation functions private (#90)
|
||||||
* `zeroEx.token.invalidateContractInstancesAsync`
|
* `zeroEx.token.invalidateContractInstancesAsync`
|
||||||
* `zeroEx.exchange.invalidateContractInstancesAsync`
|
* `zeroEx.exchange.invalidateContractInstancesAsync`
|
||||||
* `zeroEx.proxy.invalidateContractInstance`
|
* `zeroEx.proxy.invalidateContractInstance`
|
||||||
* `zeroEx.tokenRegistry.invalidateContractInstance`
|
* `zeroEx.tokenRegistry.invalidateContractInstance`
|
||||||
* Fixed the bug where `zeroEx.setProviderAsync` didn't invalidate etherToken contract's instance
|
* 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)
|
* 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)
|
* Added Kovan smart contract artifacts (#78)
|
||||||
* Started returning fillAmount from `fillOrderAsync` and `fillUpToAsync` (#72)
|
* Started returning fillAmount from `fillOrderAsync` and `fillUpToAsync` (#72)
|
||||||
* Started returning cancelledAmount from `cancelOrderAsync` (#72)
|
* Started returning cancelledAmount from `cancelOrderAsync` (#72)
|
||||||
* Renamed type `LogCancelArgs` to `LogCancelContractEventArgs` and `LogFillArgs` to `LogFillContractEventArgs`
|
* Renamed type `LogCancelArgs` to `LogCancelContractEventArgs` and `LogFillArgs` to `LogFillContractEventArgs`
|
||||||
|
|
||||||
v0.6.2 - _Jun. 21, 2017_
|
## v0.6.2 - _June 20, 2017_
|
||||||
------------------------
|
|
||||||
* Reduced bundle size
|
* Reduced bundle size
|
||||||
* Improved documentation
|
* Improved documentation
|
||||||
|
|
||||||
v0.6.1 - _Jun. 19, 2017_
|
## v0.6.1 - _June 18, 2017_
|
||||||
------------------------
|
|
||||||
* Improved documentation
|
* Improved documentation
|
||||||
|
|
||||||
v0.6.0 - _Jun. 19, 2017_
|
## v0.6.0 - _June 18, 2017_
|
||||||
------------------------
|
|
||||||
* Made `ZeroEx` class accept `Web3Provider` instance instead of `Web3` instance
|
* Made `ZeroEx` class accept `Web3Provider` instance instead of `Web3` instance
|
||||||
* Added types for contract event arguments
|
* 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
|
* 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.
|
* 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/0xjs).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
0x.js ships as both a [UMD](https://github.com/umdjs/umd) module and a [CommonJS](https://en.wikipedia.org/wiki/CommonJS) package.
|
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**
|
**Install**
|
||||||
|
|
||||||
@@ -16,14 +19,22 @@ npm install 0x.js --save
|
|||||||
**Import**
|
**Import**
|
||||||
|
|
||||||
```javascript
|
```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:
|
#### UMD:
|
||||||
|
|
||||||
**Install**
|
**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**
|
**Import**
|
||||||
|
|
||||||
@@ -31,10 +42,66 @@ Download the UMD module from our [releases page](https://github.com/0xProject/0x
|
|||||||
<script type="text/javascript" src="0x.js"></script>
|
<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 the protocol. To report bugs within this package, please create an issue in this repository.
|
||||||
|
|
||||||
[website-url]: https://0xproject.com/
|
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||||
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
|
||||||
[docs-url]: https://0xproject.com/docs/0xjs
|
### 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
|
||||||
|
|
||||||
|
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn lerna:rebuild
|
||||||
|
```
|
||||||
|
|
||||||
|
Or continuously rebuild on change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also build this specific package by running the following from within its directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn build
|
||||||
|
```
|
||||||
|
|
||||||
|
or continuously rebuild on change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn build: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,117 @@
|
|||||||
{
|
{
|
||||||
"name": "0x.js",
|
"name": "0x.js",
|
||||||
"version": "0.28.0",
|
"version": "0.36.0",
|
||||||
"description": "A javascript library for interacting with the 0x protocol",
|
"description": "A javascript library for interacting with the 0x protocol",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"0x.js",
|
"0x.js",
|
||||||
"0xproject",
|
"0xproject",
|
||||||
"ethereum",
|
"ethereum",
|
||||||
"tokens",
|
"tokens",
|
||||||
"exchange"
|
"exchange"
|
||||||
],
|
],
|
||||||
"main": "lib/src/index.js",
|
"main": "lib/src/index.js",
|
||||||
"types": "lib/src/index.d.ts",
|
"types": "lib/src/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "run-s clean generate_contract_wrappers",
|
"build:watch": "tsc -w",
|
||||||
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
"prebuild": "run-s clean generate_contract_wrappers",
|
||||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
|
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
||||||
"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 --abis 'src/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'",
|
||||||
"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'",
|
||||||
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
"test:circleci": "run-s test:coverage",
|
||||||
"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": "run-s clean test:commonjs",
|
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||||
"test:umd": "./scripts/test_umd.sh",
|
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||||
"test:coverage": "nyc npm run test --all",
|
"update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../0x.js/src/artifacts; done;",
|
||||||
"report_test_coverage": "nyc report --reporter=text-lcov | coveralls",
|
"clean": "shx rm -rf _bundles lib test_temp scripts",
|
||||||
"update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../0x.js/src/artifacts; done;",
|
"build:umd:prod": "NODE_ENV=production webpack",
|
||||||
"clean": "shx rm -rf _bundles lib test_temp",
|
"build:commonjs": "tsc && copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
||||||
"build:umd:dev": "webpack",
|
"test:commonjs": "run-s build:commonjs run_mocha",
|
||||||
"build:umd:prod": "NODE_ENV=production webpack",
|
"run_mocha": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit",
|
||||||
"build:commonjs": "tsc && copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts;",
|
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
|
||||||
"test:commonjs": "run-s build:commonjs run_mocha",
|
"docs:stage": "yarn build && node ./scripts/stage_docs.js",
|
||||||
"pretest:umd": "run-s clean build:umd:dev build:commonjs",
|
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
|
||||||
"substitute_umd_bundle": "shx mv _bundles/* lib/src",
|
"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"
|
||||||
"run_mocha": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit"
|
},
|
||||||
},
|
"config": {
|
||||||
"config": {
|
"artifacts": "TokenTransferProxy Exchange TokenRegistry Token EtherToken",
|
||||||
"artifacts": "TokenTransferProxy Exchange TokenRegistry Token EtherToken"
|
"postpublish": {
|
||||||
},
|
"assets": [
|
||||||
"repository": {
|
"packages/0x.js/_bundles/index.js",
|
||||||
"type": "git",
|
"packages/0x.js/_bundles/index.min.js"
|
||||||
"url": "https://github.com/0xProject/0x.js"
|
],
|
||||||
},
|
"docPublishConfigs": {
|
||||||
"license": "Apache-2.0",
|
"extraFileIncludes": [
|
||||||
"engines": {
|
"../types/src/index.ts",
|
||||||
"node": ">=6.0.0"
|
"./src/contract_wrappers/generated/ether_token.ts",
|
||||||
},
|
"./src/contract_wrappers/generated/token.ts",
|
||||||
"devDependencies": {
|
"./src/contract_wrappers/generated/exchange.ts"
|
||||||
"@0xproject/abi-gen": "^0.0.3",
|
],
|
||||||
"@0xproject/dev-utils": "^0.0.2",
|
"s3BucketPath": "s3://doc-jsons/0x.js/",
|
||||||
"@0xproject/tslint-config": "^0.3.0",
|
"s3StagingBucketPath": "s3://staging-doc-jsons/0x.js/"
|
||||||
"@0xproject/types": "^0.1.1",
|
}
|
||||||
"@types/bintrees": "^1.0.2",
|
}
|
||||||
"@types/jsonschema": "^1.1.1",
|
},
|
||||||
"@types/lodash": "^4.14.86",
|
"repository": {
|
||||||
"@types/mocha": "^2.2.42",
|
"type": "git",
|
||||||
"@types/node": "^8.0.53",
|
"url": "https://github.com/0xProject/0x-monorepo"
|
||||||
"@types/sinon": "^2.2.2",
|
},
|
||||||
"@types/uuid": "^3.4.2",
|
"license": "Apache-2.0",
|
||||||
"awesome-typescript-loader": "^3.1.3",
|
"engines": {
|
||||||
"chai": "^4.0.1",
|
"node": ">=6.0.0"
|
||||||
"chai-as-promised": "^7.1.0",
|
},
|
||||||
"chai-as-promised-typescript-typings": "^0.0.3",
|
"devDependencies": {
|
||||||
"chai-bignumber": "^2.0.1",
|
"@0xproject/dev-utils": "^0.3.5",
|
||||||
"chai-typescript-typings": "^0.0.1",
|
"@0xproject/monorepo-scripts": "^0.1.17",
|
||||||
"copyfiles": "^1.2.0",
|
"@0xproject/tslint-config": "^0.4.15",
|
||||||
"coveralls": "^3.0.0",
|
"@types/bintrees": "^1.0.2",
|
||||||
"dirty-chai": "^2.0.1",
|
"@types/lodash": "4.14.104",
|
||||||
"json-loader": "^0.5.4",
|
"@types/mocha": "^2.2.42",
|
||||||
"mocha": "^4.0.1",
|
"@types/node": "^8.0.53",
|
||||||
"npm-run-all": "^4.1.2",
|
"@types/request": "2.47.0",
|
||||||
"nyc": "^11.0.1",
|
"@types/sinon": "^2.2.2",
|
||||||
"opn-cli": "^3.1.0",
|
"@types/uuid": "^3.4.2",
|
||||||
"request": "^2.81.0",
|
"awesome-typescript-loader": "^3.1.3",
|
||||||
"request-promise-native": "^1.0.4",
|
"chai": "^4.0.1",
|
||||||
"shx": "^0.2.2",
|
"chai-as-promised": "^7.1.0",
|
||||||
"sinon": "^4.0.0",
|
"chai-bignumber": "^2.0.1",
|
||||||
"source-map-support": "^0.5.0",
|
"copyfiles": "^1.2.0",
|
||||||
"truffle-hdwallet-provider": "^0.0.3",
|
"dirty-chai": "^2.0.1",
|
||||||
"tslint": "5.8.0",
|
"json-loader": "^0.5.4",
|
||||||
"typedoc": "~0.8.0",
|
"mocha": "^4.0.1",
|
||||||
"typescript": "~2.6.1",
|
"npm-run-all": "^4.1.2",
|
||||||
"web3-provider-engine": "^13.0.1",
|
"nyc": "^11.0.1",
|
||||||
"web3-typescript-typings": "^0.7.2",
|
"opn-cli": "^3.1.0",
|
||||||
"webpack": "^3.1.0"
|
"prettier": "^1.11.1",
|
||||||
},
|
"request": "^2.81.0",
|
||||||
"dependencies": {
|
"shx": "^0.2.2",
|
||||||
"@0xproject/assert": "^0.0.8",
|
"sinon": "^4.0.0",
|
||||||
"@0xproject/json-schemas": "^0.7.0",
|
"source-map-support": "^0.5.0",
|
||||||
"@0xproject/utils": "^0.1.1",
|
"truffle-hdwallet-provider": "^0.0.3",
|
||||||
"@0xproject/web3-wrapper": "^0.1.1",
|
"tslint": "5.8.0",
|
||||||
"bignumber.js": "~4.1.0",
|
"typedoc": "0xProject/typedoc",
|
||||||
"bintrees": "^1.0.2",
|
"typescript": "2.7.1",
|
||||||
"bn.js": "^4.11.8",
|
"webpack": "^3.1.0"
|
||||||
"compare-versions": "^3.0.1",
|
},
|
||||||
"ethereumjs-abi": "^0.6.4",
|
"dependencies": {
|
||||||
"ethereumjs-blockstream": "^2.0.6",
|
"@0xproject/assert": "^0.2.6",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"@0xproject/base-contract": "^0.2.0",
|
||||||
"find-versions": "^2.0.0",
|
"@0xproject/json-schemas": "^0.7.20",
|
||||||
"js-sha3": "^0.6.1",
|
"@0xproject/types": "^0.6.0",
|
||||||
"lodash": "^4.17.4",
|
"@0xproject/typescript-typings": "^0.1.0",
|
||||||
"uuid": "^3.1.0",
|
"@0xproject/utils": "^0.5.1",
|
||||||
"web3": "^0.20.0"
|
"@0xproject/web3-wrapper": "^0.6.0",
|
||||||
}
|
"bintrees": "^1.0.2",
|
||||||
|
"bn.js": "^4.11.8",
|
||||||
|
"ethereumjs-abi": "^0.6.4",
|
||||||
|
"ethereumjs-blockstream": "^2.0.6",
|
||||||
|
"ethereumjs-util": "^5.1.1",
|
||||||
|
"ethers-contracts": "^2.2.1",
|
||||||
|
"js-sha3": "^0.7.0",
|
||||||
|
"lodash": "^4.17.4",
|
||||||
|
"uuid": "^3.1.0",
|
||||||
|
"web3": "^0.20.0"
|
||||||
|
},
|
||||||
|
"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,26 @@
|
|||||||
import {schemas, SchemaValidator} from '@0xproject/json-schemas';
|
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
||||||
import {bigNumberConfigs, intervalUtils} from '@0xproject/utils';
|
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {artifacts} from './artifacts';
|
import { artifacts } from './artifacts';
|
||||||
import {EtherTokenWrapper} from './contract_wrappers/ether_token_wrapper';
|
import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
|
||||||
import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper';
|
import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
|
||||||
import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper';
|
import { TokenRegistryWrapper } from './contract_wrappers/token_registry_wrapper';
|
||||||
import {TokenTransferProxyWrapper} from './contract_wrappers/token_transfer_proxy_wrapper';
|
import { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper';
|
||||||
import {TokenWrapper} from './contract_wrappers/token_wrapper';
|
import { TokenWrapper } from './contract_wrappers/token_wrapper';
|
||||||
import {OrderStateWatcher} from './order_watcher/order_state_watcher';
|
import { OrderStateWatcher } from './order_watcher/order_state_watcher';
|
||||||
import {zeroExConfigSchema} from './schemas/zero_ex_config_schema';
|
import { zeroExConfigSchema } from './schemas/zero_ex_config_schema';
|
||||||
import {
|
import { zeroExPrivateNetworkConfigSchema } from './schemas/zero_ex_private_network_config_schema';
|
||||||
ECSignature,
|
import { zeroExPublicNetworkConfigSchema } from './schemas/zero_ex_public_network_config_schema';
|
||||||
Order,
|
import { OrderStateWatcherConfig, ZeroExConfig, ZeroExError } from './types';
|
||||||
SignedOrder,
|
import { assert } from './utils/assert';
|
||||||
TransactionReceiptWithDecodedLogs,
|
import { constants } from './utils/constants';
|
||||||
Web3Provider,
|
import { decorators } from './utils/decorators';
|
||||||
ZeroExConfig,
|
import { signatureUtils } from './utils/signature_utils';
|
||||||
ZeroExError,
|
import { utils } from './utils/utils';
|
||||||
} 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();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ZeroEx class is the single entry-point into the 0x.js library. It contains all of the library's functionality
|
* The ZeroEx class is the single entry-point into the 0x.js library. It contains all of the library's functionality
|
||||||
@@ -67,13 +57,7 @@ export class ZeroEx {
|
|||||||
* tokenTransferProxy smart contract.
|
* tokenTransferProxy smart contract.
|
||||||
*/
|
*/
|
||||||
public proxy: TokenTransferProxyWrapper;
|
public proxy: TokenTransferProxyWrapper;
|
||||||
/**
|
|
||||||
* An instance of the OrderStateWatcher class containing methods for watching a set of orders for relevant
|
|
||||||
* blockchain state changes.
|
|
||||||
*/
|
|
||||||
public orderStateWatcher: OrderStateWatcher;
|
|
||||||
private _web3Wrapper: Web3Wrapper;
|
private _web3Wrapper: Web3Wrapper;
|
||||||
private _abiDecoder: AbiDecoder;
|
|
||||||
/**
|
/**
|
||||||
* Verifies that the elliptic curve signature `signature` was generated
|
* Verifies that the elliptic curve signature `signature` was generated
|
||||||
* by signing `data` with the private key corresponding to the `signerAddress` address.
|
* by signing `data` with the private key corresponding to the `signerAddress` address.
|
||||||
@@ -86,13 +70,14 @@ export class ZeroEx {
|
|||||||
assert.isHexString('data', data);
|
assert.isHexString('data', data);
|
||||||
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
|
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
|
||||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||||
|
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||||
|
|
||||||
const isValidSignature = signatureUtils.isValidSignature(data, signature, signerAddress);
|
const isValidSignature = signatureUtils.isValidSignature(data, signature, normalizedSignerAddress);
|
||||||
return isValidSignature;
|
return isValidSignature;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Generates a pseudo-random 256-bit salt.
|
* Generates a pseudo-random 256-bit salt.
|
||||||
* The salt can be included in an 0x order, ensuring that the order generates a unique orderHash
|
* 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.
|
* 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.
|
* @return A pseudo-random 256-bit number that can be used as a salt.
|
||||||
*/
|
*/
|
||||||
@@ -130,10 +115,8 @@ export class ZeroEx {
|
|||||||
public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber {
|
public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber {
|
||||||
assert.isValidBaseUnitAmount('amount', amount);
|
assert.isValidBaseUnitAmount('amount', amount);
|
||||||
assert.isNumber('decimals', decimals);
|
assert.isNumber('decimals', decimals);
|
||||||
|
const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
|
||||||
const aUnit = new BigNumber(10).pow(decimals);
|
return unitAmount;
|
||||||
const unit = amount.div(aUnit);
|
|
||||||
return unit;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* A baseUnit is defined as the smallest denomination of a token. An amount expressed in baseUnits
|
* A baseUnit is defined as the smallest denomination of a token. An amount expressed in baseUnits
|
||||||
@@ -146,13 +129,7 @@ export class ZeroEx {
|
|||||||
public static toBaseUnitAmount(amount: BigNumber, decimals: number): BigNumber {
|
public static toBaseUnitAmount(amount: BigNumber, decimals: number): BigNumber {
|
||||||
assert.isBigNumber('amount', amount);
|
assert.isBigNumber('amount', amount);
|
||||||
assert.isNumber('decimals', decimals);
|
assert.isNumber('decimals', decimals);
|
||||||
|
const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, 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`);
|
|
||||||
}
|
|
||||||
return baseUnitAmount;
|
return baseUnitAmount;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -161,55 +138,52 @@ export class ZeroEx {
|
|||||||
* @return The resulting orderHash from hashing the supplied order.
|
* @return The resulting orderHash from hashing the supplied order.
|
||||||
*/
|
*/
|
||||||
@decorators.syncZeroExErrorHandler
|
@decorators.syncZeroExErrorHandler
|
||||||
public static getOrderHashHex(order: Order|SignedOrder): string {
|
public static getOrderHashHex(order: Order | SignedOrder): string {
|
||||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||||
const orderHashHex = utils.getOrderHashHex(order);
|
const orderHashHex = utils.getOrderHashHex(order);
|
||||||
return orderHashHex;
|
return orderHashHex;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library.
|
* 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.
|
* the Ethereum network.
|
||||||
* @param config The configuration object. Look up the type for the description.
|
* @param config The configuration object. Look up the type for the description.
|
||||||
* @return An instance of the 0x.js ZeroEx class.
|
* @return An instance of the 0x.js ZeroEx class.
|
||||||
*/
|
*/
|
||||||
constructor(provider: Web3Provider, config: ZeroExConfig) {
|
constructor(provider: Provider, config: ZeroExConfig) {
|
||||||
assert.isWeb3Provider('provider', provider);
|
assert.isWeb3Provider('provider', provider);
|
||||||
assert.doesConformToSchema('config', config, zeroExConfigSchema);
|
assert.doesConformToSchema('config', config, zeroExConfigSchema, [
|
||||||
|
zeroExPrivateNetworkConfigSchema,
|
||||||
|
zeroExPublicNetworkConfigSchema,
|
||||||
|
]);
|
||||||
const artifactJSONs = _.values(artifacts);
|
const artifactJSONs = _.values(artifacts);
|
||||||
const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
|
const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
|
||||||
this._abiDecoder = new AbiDecoder(abiArrays);
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
gasPrice: config.gasPrice,
|
gasPrice: config.gasPrice,
|
||||||
};
|
};
|
||||||
this._web3Wrapper = new Web3Wrapper(provider, defaults);
|
this._web3Wrapper = new Web3Wrapper(provider, defaults);
|
||||||
|
_.forEach(abiArrays, abi => {
|
||||||
|
this._web3Wrapper.abiDecoder.addABI(abi);
|
||||||
|
});
|
||||||
this.proxy = new TokenTransferProxyWrapper(
|
this.proxy = new TokenTransferProxyWrapper(
|
||||||
this._web3Wrapper,
|
this._web3Wrapper,
|
||||||
config.networkId,
|
config.networkId,
|
||||||
config.tokenTransferProxyContractAddress,
|
config.tokenTransferProxyContractAddress,
|
||||||
);
|
);
|
||||||
this.token = new TokenWrapper(
|
this.token = new TokenWrapper(this._web3Wrapper, config.networkId, this.proxy);
|
||||||
this._web3Wrapper,
|
|
||||||
config.networkId,
|
|
||||||
this._abiDecoder,
|
|
||||||
this.proxy,
|
|
||||||
);
|
|
||||||
this.exchange = new ExchangeWrapper(
|
this.exchange = new ExchangeWrapper(
|
||||||
this._web3Wrapper,
|
this._web3Wrapper,
|
||||||
config.networkId,
|
config.networkId,
|
||||||
this._abiDecoder,
|
|
||||||
this.token,
|
this.token,
|
||||||
config.exchangeContractAddress,
|
config.exchangeContractAddress,
|
||||||
|
config.zrxContractAddress,
|
||||||
);
|
);
|
||||||
this.tokenRegistry = new TokenRegistryWrapper(
|
this.tokenRegistry = new TokenRegistryWrapper(
|
||||||
this._web3Wrapper, config.networkId, config.tokenRegistryContractAddress,
|
this._web3Wrapper,
|
||||||
);
|
config.networkId,
|
||||||
this.etherToken = new EtherTokenWrapper(
|
config.tokenRegistryContractAddress,
|
||||||
this._web3Wrapper, config.networkId, this._abiDecoder, this.token,
|
|
||||||
);
|
|
||||||
this.orderStateWatcher = new OrderStateWatcher(
|
|
||||||
this._web3Wrapper, this._abiDecoder, this.token, this.exchange, config.orderWatcherConfig,
|
|
||||||
);
|
);
|
||||||
|
this.etherToken = new EtherTokenWrapper(this._web3Wrapper, config.networkId, this.token);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
|
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
|
||||||
@@ -217,13 +191,18 @@ export class ZeroEx {
|
|||||||
* @param provider The Web3Provider you would like the 0x.js library to use from now on.
|
* @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
|
* @param networkId The id of the network your provider is connected to
|
||||||
*/
|
*/
|
||||||
public setProvider(provider: Web3Provider, networkId: number): void {
|
public setProvider(provider: Provider, networkId: number): void {
|
||||||
this._web3Wrapper.setProvider(provider, networkId);
|
this._web3Wrapper.setProvider(provider);
|
||||||
(this.exchange as any)._invalidateContractInstances();
|
(this.exchange as any)._invalidateContractInstances();
|
||||||
|
(this.exchange as any)._setNetworkId(networkId);
|
||||||
(this.tokenRegistry as any)._invalidateContractInstance();
|
(this.tokenRegistry as any)._invalidateContractInstance();
|
||||||
|
(this.tokenRegistry as any)._setNetworkId(networkId);
|
||||||
(this.token as any)._invalidateContractInstances();
|
(this.token as any)._invalidateContractInstances();
|
||||||
|
(this.token as any)._setNetworkId(networkId);
|
||||||
(this.proxy as any)._invalidateContractInstance();
|
(this.proxy as any)._invalidateContractInstance();
|
||||||
|
(this.proxy as any)._setNetworkId(networkId);
|
||||||
(this.etherToken as any)._invalidateContractInstance();
|
(this.etherToken as any)._invalidateContractInstance();
|
||||||
|
(this.etherToken as any)._setNetworkId(networkId);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get user Ethereum addresses available through the supplied web3 provider available for sending transactions.
|
* Get user Ethereum addresses available through the supplied web3 provider available for sending transactions.
|
||||||
@@ -238,27 +217,30 @@ export class ZeroEx {
|
|||||||
* This method currently supports TestRPC, Geth and Parity above and below V1.6.6
|
* This method currently supports TestRPC, Geth and Parity above and below V1.6.6
|
||||||
* @param orderHash Hex encoded orderHash to sign.
|
* @param orderHash Hex encoded orderHash to sign.
|
||||||
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
|
* @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.
|
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
|
||||||
*/
|
*/
|
||||||
public async signOrderHashAsync(orderHash: string, signerAddress: string): Promise<ECSignature> {
|
public async signOrderHashAsync(
|
||||||
|
orderHash: string,
|
||||||
|
signerAddress: string,
|
||||||
|
shouldAddPersonalMessagePrefix: boolean,
|
||||||
|
): Promise<ECSignature> {
|
||||||
assert.isHexString('orderHash', orderHash);
|
assert.isHexString('orderHash', orderHash);
|
||||||
await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper);
|
||||||
|
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||||
|
|
||||||
let msgHashHex;
|
let msgHashHex = orderHash;
|
||||||
const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
|
if (shouldAddPersonalMessagePrefix) {
|
||||||
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 orderHashBuff = ethUtil.toBuffer(orderHash);
|
||||||
const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff);
|
const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff);
|
||||||
msgHashHex = ethUtil.bufferToHex(msgHashBuff);
|
msgHashHex = ethUtil.bufferToHex(msgHashBuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
const signature = await this._web3Wrapper.signTransactionAsync(signerAddress, msgHashHex);
|
const signature = await this._web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
|
||||||
|
|
||||||
// HACK: There is no consensus on whether the signatureHex string should be formatted as
|
// 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)
|
// v + r + s OR r + s + v, and different clients (even different versions of the same client)
|
||||||
@@ -267,7 +249,7 @@ export class ZeroEx {
|
|||||||
const validVParamValues = [27, 28];
|
const validVParamValues = [27, 28];
|
||||||
const ecSignatureVRS = signatureUtils.parseSignatureHexAsVRS(signature);
|
const ecSignatureVRS = signatureUtils.parseSignatureHexAsVRS(signature);
|
||||||
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
|
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
|
||||||
const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, signerAddress);
|
const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, normalizedSignerAddress);
|
||||||
if (isValidVRSSignature) {
|
if (isValidVRSSignature) {
|
||||||
return ecSignatureVRS;
|
return ecSignatureVRS;
|
||||||
}
|
}
|
||||||
@@ -275,7 +257,7 @@ export class ZeroEx {
|
|||||||
|
|
||||||
const ecSignatureRSV = signatureUtils.parseSignatureHexAsRSV(signature);
|
const ecSignatureRSV = signatureUtils.parseSignatureHexAsRSV(signature);
|
||||||
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
|
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
|
||||||
const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, signerAddress);
|
const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, normalizedSignerAddress);
|
||||||
if (isValidRSVSignature) {
|
if (isValidRSVSignature) {
|
||||||
return ecSignatureRSV;
|
return ecSignatureRSV;
|
||||||
}
|
}
|
||||||
@@ -291,37 +273,25 @@ export class ZeroEx {
|
|||||||
* @return Transaction receipt with decoded log args.
|
* @return Transaction receipt with decoded log args.
|
||||||
*/
|
*/
|
||||||
public async awaitTransactionMinedAsync(
|
public async awaitTransactionMinedAsync(
|
||||||
txHash: string, pollingIntervalMs = 1000, timeoutMs?: number): Promise<TransactionReceiptWithDecodedLogs> {
|
txHash: string,
|
||||||
let timeoutExceeded = false;
|
pollingIntervalMs = 1000,
|
||||||
if (timeoutMs) {
|
timeoutMs?: number,
|
||||||
setTimeout(() => timeoutExceeded = true, timeoutMs);
|
): Promise<TransactionReceiptWithDecodedLogs> {
|
||||||
}
|
const transactionReceiptWithDecodedLogs = await this._web3Wrapper.awaitTransactionMinedAsync(
|
||||||
|
txHash,
|
||||||
const txReceiptPromise = new Promise(
|
pollingIntervalMs,
|
||||||
(resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => {
|
timeoutMs,
|
||||||
const intervalId = intervalUtils.setAsyncExcludingInterval(async () => {
|
);
|
||||||
if (timeoutExceeded) {
|
return transactionReceiptWithDecodedLogs;
|
||||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
}
|
||||||
return reject(ZeroExError.TransactionMiningTimeout);
|
/**
|
||||||
}
|
* Instantiates and returns a new OrderStateWatcher instance.
|
||||||
|
* Defaults to watching the pending state.
|
||||||
const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash);
|
* @param config The configuration object. Look up the type for the description.
|
||||||
if (!_.isNull(transactionReceipt)) {
|
* @return An instance of the 0x.js OrderStateWatcher class.
|
||||||
intervalUtils.clearAsyncExcludingInterval(intervalId);
|
*/
|
||||||
const logsWithDecodedArgs = _.map(
|
public createOrderStateWatcher(config?: OrderStateWatcherConfig) {
|
||||||
transactionReceipt.logs,
|
return new OrderStateWatcher(this._web3Wrapper, this.token, this.exchange, config);
|
||||||
this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder),
|
|
||||||
);
|
|
||||||
const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = {
|
|
||||||
...transactionReceipt,
|
|
||||||
logs: logsWithDecodedArgs,
|
|
||||||
};
|
|
||||||
resolve(transactionReceiptWithDecodedLogArgs);
|
|
||||||
}
|
|
||||||
}, pollingIntervalMs);
|
|
||||||
});
|
|
||||||
|
|
||||||
return txReceiptPromise;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from
|
* HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import * as TokenArtifact from './artifacts/Token.json';
|
|||||||
import * as TokenRegistryArtifact from './artifacts/TokenRegistry.json';
|
import * as TokenRegistryArtifact from './artifacts/TokenRegistry.json';
|
||||||
import * as TokenTransferProxyArtifact from './artifacts/TokenTransferProxy.json';
|
import * as TokenTransferProxyArtifact from './artifacts/TokenTransferProxy.json';
|
||||||
import * as ZRXArtifact from './artifacts/ZRX.json';
|
import * as ZRXArtifact from './artifacts/ZRX.json';
|
||||||
import {Artifact} from './types';
|
import { Artifact } from './types';
|
||||||
|
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
ZRXArtifact: ZRXArtifact as any as Artifact,
|
ZRXArtifact: (ZRXArtifact as any) as Artifact,
|
||||||
DummyTokenArtifact: DummyTokenArtifact as any as Artifact,
|
DummyTokenArtifact: (DummyTokenArtifact as any) as Artifact,
|
||||||
TokenArtifact: TokenArtifact as any as Artifact,
|
TokenArtifact: (TokenArtifact as any) as Artifact,
|
||||||
ExchangeArtifact: ExchangeArtifact as any as Artifact,
|
ExchangeArtifact: (ExchangeArtifact as any) as Artifact,
|
||||||
EtherTokenArtifact: EtherTokenArtifact as any as Artifact,
|
EtherTokenArtifact: (EtherTokenArtifact as any) as Artifact,
|
||||||
TokenRegistryArtifact: TokenRegistryArtifact as any as Artifact,
|
TokenRegistryArtifact: (TokenRegistryArtifact as any) as Artifact,
|
||||||
TokenTransferProxyArtifact: TokenTransferProxyArtifact as any as Artifact,
|
TokenTransferProxyArtifact: (TokenTransferProxyArtifact as any) as Artifact,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"contract_name": "DummyToken",
|
"contract_name": "DummyToken",
|
||||||
"abi":
|
"abi": [
|
||||||
[
|
|
||||||
{
|
{
|
||||||
"constant": false,
|
"constant": false,
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
|||||||
@@ -1,284 +1,287 @@
|
|||||||
{
|
{
|
||||||
"contract_name": "EtherToken",
|
"contract_name": "EtherToken",
|
||||||
"abi": [
|
"abi": [
|
||||||
{
|
|
||||||
"constant": true,
|
|
||||||
"inputs": [],
|
|
||||||
"name": "name",
|
|
||||||
"outputs": [
|
|
||||||
{
|
{
|
||||||
"name": "",
|
"constant": true,
|
||||||
"type": "string"
|
"inputs": [],
|
||||||
}
|
"name": "name",
|
||||||
],
|
"outputs": [
|
||||||
"payable": false,
|
{
|
||||||
"type": "function"
|
"name": "",
|
||||||
},
|
"type": "string"
|
||||||
{
|
}
|
||||||
"constant": false,
|
],
|
||||||
"inputs": [
|
"payable": false,
|
||||||
{
|
"type": "function"
|
||||||
"name": "_spender",
|
|
||||||
"type": "address"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_value",
|
"constant": false,
|
||||||
"type": "uint256"
|
"inputs": [
|
||||||
}
|
{
|
||||||
],
|
"name": "_spender",
|
||||||
"name": "approve",
|
"type": "address"
|
||||||
"outputs": [
|
},
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "_value",
|
||||||
"type": "bool"
|
"type": "uint256"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"payable": false,
|
"name": "approve",
|
||||||
"type": "function"
|
"outputs": [
|
||||||
},
|
{
|
||||||
{
|
"name": "",
|
||||||
"constant": true,
|
"type": "bool"
|
||||||
"inputs": [],
|
}
|
||||||
"name": "totalSupply",
|
],
|
||||||
"outputs": [
|
"payable": false,
|
||||||
{
|
"type": "function"
|
||||||
"name": "",
|
|
||||||
"type": "uint256"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"payable": false,
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "_from",
|
|
||||||
"type": "address"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_to",
|
"constant": true,
|
||||||
"type": "address"
|
"inputs": [],
|
||||||
|
"name": "totalSupply",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_value",
|
"constant": false,
|
||||||
"type": "uint256"
|
"inputs": [
|
||||||
}
|
{
|
||||||
],
|
"name": "_from",
|
||||||
"name": "transferFrom",
|
"type": "address"
|
||||||
"outputs": [
|
},
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "_to",
|
||||||
"type": "bool"
|
"type": "address"
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"payable": false,
|
"name": "_value",
|
||||||
"type": "function"
|
"type": "uint256"
|
||||||
},
|
}
|
||||||
{
|
],
|
||||||
"constant": false,
|
"name": "transferFrom",
|
||||||
"inputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "amount",
|
"name": "",
|
||||||
"type": "uint256"
|
"type": "bool"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "withdraw",
|
"payable": false,
|
||||||
"outputs": [],
|
"type": "function"
|
||||||
"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",
|
"constant": false,
|
||||||
"type": "uint256"
|
"inputs": [
|
||||||
}
|
{
|
||||||
],
|
"name": "amount",
|
||||||
"name": "transfer",
|
"type": "uint256"
|
||||||
"outputs": [
|
}
|
||||||
{
|
],
|
||||||
"name": "",
|
"name": "withdraw",
|
||||||
"type": "bool"
|
"outputs": [],
|
||||||
}
|
"payable": false,
|
||||||
],
|
"type": "function"
|
||||||
"payable": false,
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"inputs": [],
|
|
||||||
"name": "deposit",
|
|
||||||
"outputs": [],
|
|
||||||
"payable": true,
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"constant": true,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"name": "_owner",
|
|
||||||
"type": "address"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_spender",
|
"constant": true,
|
||||||
"type": "address"
|
"inputs": [],
|
||||||
}
|
"name": "decimals",
|
||||||
],
|
"outputs": [
|
||||||
"name": "allowance",
|
{
|
||||||
"outputs": [
|
"name": "",
|
||||||
{
|
"type": "uint8"
|
||||||
"name": "",
|
}
|
||||||
"type": "uint256"
|
],
|
||||||
}
|
"payable": false,
|
||||||
],
|
"type": "function"
|
||||||
"payable": false,
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"payable": true,
|
|
||||||
"type": "fallback"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"anonymous": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"indexed": true,
|
|
||||||
"name": "_from",
|
|
||||||
"type": "address"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"indexed": true,
|
"constant": true,
|
||||||
"name": "_to",
|
"inputs": [
|
||||||
"type": "address"
|
{
|
||||||
|
"name": "_owner",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "balanceOf",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"indexed": false,
|
"constant": true,
|
||||||
"name": "_value",
|
"inputs": [],
|
||||||
"type": "uint256"
|
"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"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "Transfer",
|
"networks": {
|
||||||
"type": "event"
|
"1": {
|
||||||
},
|
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
|
||||||
{
|
|
||||||
"anonymous": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"indexed": true,
|
|
||||||
"name": "_owner",
|
|
||||||
"type": "address"
|
|
||||||
},
|
},
|
||||||
{
|
"3": {
|
||||||
"indexed": true,
|
"address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
|
||||||
"name": "_spender",
|
|
||||||
"type": "address"
|
|
||||||
},
|
},
|
||||||
{
|
"4": {
|
||||||
"indexed": false,
|
"address": "0xc778417e063141139fce010982780140aa0cd5ab"
|
||||||
"name": "_value",
|
},
|
||||||
"type": "uint256"
|
"42": {
|
||||||
|
"address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
|
||||||
|
},
|
||||||
|
"50": {
|
||||||
|
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,172 +1,172 @@
|
|||||||
{
|
{
|
||||||
"contract_name": "Token",
|
"contract_name": "Token",
|
||||||
"abi": [
|
"abi": [
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
{
|
||||||
"name": "_spender",
|
"constant": false,
|
||||||
"type": "address"
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_spender",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "approve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "success",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_value",
|
"constant": true,
|
||||||
"type": "uint256"
|
"inputs": [],
|
||||||
}
|
"name": "totalSupply",
|
||||||
],
|
"outputs": [
|
||||||
"name": "approve",
|
{
|
||||||
"outputs": [
|
"name": "supply",
|
||||||
{
|
"type": "uint256"
|
||||||
"name": "success",
|
}
|
||||||
"type": "bool"
|
],
|
||||||
}
|
"payable": false,
|
||||||
],
|
"type": "function"
|
||||||
"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",
|
"constant": false,
|
||||||
"type": "address"
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_from",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_to",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "transferFrom",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "success",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_value",
|
"constant": true,
|
||||||
"type": "uint256"
|
"inputs": [
|
||||||
}
|
{
|
||||||
],
|
"name": "_owner",
|
||||||
"name": "transferFrom",
|
"type": "address"
|
||||||
"outputs": [
|
}
|
||||||
{
|
],
|
||||||
"name": "success",
|
"name": "balanceOf",
|
||||||
"type": "bool"
|
"outputs": [
|
||||||
}
|
{
|
||||||
],
|
"name": "balance",
|
||||||
"payable": false,
|
"type": "uint256"
|
||||||
"type": "function"
|
}
|
||||||
},
|
],
|
||||||
{
|
"payable": false,
|
||||||
"constant": true,
|
"type": "function"
|
||||||
"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",
|
"constant": false,
|
||||||
"type": "uint256"
|
"inputs": [
|
||||||
}
|
{
|
||||||
],
|
"name": "_to",
|
||||||
"name": "transfer",
|
"type": "address"
|
||||||
"outputs": [
|
},
|
||||||
{
|
{
|
||||||
"name": "success",
|
"name": "_value",
|
||||||
"type": "bool"
|
"type": "uint256"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"payable": false,
|
"name": "transfer",
|
||||||
"type": "function"
|
"outputs": [
|
||||||
},
|
{
|
||||||
{
|
"name": "success",
|
||||||
"constant": true,
|
"type": "bool"
|
||||||
"inputs": [
|
}
|
||||||
{
|
],
|
||||||
"name": "_owner",
|
"payable": false,
|
||||||
"type": "address"
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "_spender",
|
"constant": true,
|
||||||
"type": "address"
|
"inputs": [
|
||||||
}
|
{
|
||||||
],
|
"name": "_owner",
|
||||||
"name": "allowance",
|
"type": "address"
|
||||||
"outputs": [
|
},
|
||||||
{
|
{
|
||||||
"name": "remaining",
|
"name": "_spender",
|
||||||
"type": "uint256"
|
"type": "address"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"payable": false,
|
"name": "allowance",
|
||||||
"type": "function"
|
"outputs": [
|
||||||
},
|
{
|
||||||
{
|
"name": "remaining",
|
||||||
"anonymous": false,
|
"type": "uint256"
|
||||||
"inputs": [
|
}
|
||||||
{
|
],
|
||||||
"indexed": true,
|
"payable": false,
|
||||||
"name": "_from",
|
"type": "function"
|
||||||
"type": "address"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"indexed": true,
|
"anonymous": false,
|
||||||
"name": "_to",
|
"inputs": [
|
||||||
"type": "address"
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "_from",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "_to",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "_value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Transfer",
|
||||||
|
"type": "event"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"indexed": false,
|
"anonymous": false,
|
||||||
"name": "_value",
|
"inputs": [
|
||||||
"type": "uint256"
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "_owner",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "_spender",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "_value",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Approval",
|
||||||
|
"type": "event"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,184 +1,187 @@
|
|||||||
{
|
{
|
||||||
"contract_name": "TokenTransferProxy",
|
"contract_name": "TokenTransferProxy",
|
||||||
"abi": [
|
"abi": [
|
||||||
{
|
|
||||||
"constant": false,
|
|
||||||
"inputs": [
|
|
||||||
{
|
{
|
||||||
"name": "token",
|
"constant": false,
|
||||||
"type": "address"
|
"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"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "from",
|
"constant": false,
|
||||||
"type": "address"
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "target",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "addAuthorizedAddress",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "to",
|
"constant": true,
|
||||||
"type": "address"
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "authorities",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "value",
|
"constant": false,
|
||||||
"type": "uint256"
|
"inputs": [
|
||||||
}
|
{
|
||||||
],
|
"name": "target",
|
||||||
"name": "transferFrom",
|
"type": "address"
|
||||||
"outputs": [
|
}
|
||||||
{
|
],
|
||||||
"name": "",
|
"name": "removeAuthorizedAddress",
|
||||||
"type": "bool"
|
"outputs": [],
|
||||||
}
|
"payable": false,
|
||||||
],
|
"type": "function"
|
||||||
"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,
|
"constant": true,
|
||||||
"name": "caller",
|
"inputs": [],
|
||||||
"type": "address"
|
"name": "owner",
|
||||||
}
|
"outputs": [
|
||||||
],
|
{
|
||||||
"name": "LogAuthorizedAddressAdded",
|
"name": "",
|
||||||
"type": "event"
|
"type": "address"
|
||||||
},
|
}
|
||||||
{
|
],
|
||||||
"anonymous": false,
|
"payable": false,
|
||||||
"inputs": [
|
"type": "function"
|
||||||
{
|
|
||||||
"indexed": true,
|
|
||||||
"name": "target",
|
|
||||||
"type": "address"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"indexed": true,
|
"constant": true,
|
||||||
"name": "caller",
|
"inputs": [
|
||||||
"type": "address"
|
{
|
||||||
|
"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"
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"name": "LogAuthorizedAddressRemoved",
|
|
||||||
"type": "event"
|
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"networks": {
|
|
||||||
"1": {
|
|
||||||
"address": "0x8da0d80f5007ef1e431dd2127178d224e32c2ef4"
|
|
||||||
},
|
|
||||||
"3": {
|
|
||||||
"address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
|
|
||||||
},
|
|
||||||
"42": {
|
|
||||||
"address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4"
|
|
||||||
},
|
|
||||||
"50": {
|
|
||||||
"address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
{
|
{
|
||||||
"contract_name": "ZRX",
|
"contract_name": "ZRX",
|
||||||
"networks": {
|
"networks": {
|
||||||
"1": {
|
"1": {
|
||||||
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
|
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
|
||||||
},
|
},
|
||||||
"3": {
|
"3": {
|
||||||
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
|
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
|
||||||
},
|
},
|
||||||
"42": {
|
"4": {
|
||||||
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
|
"address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8"
|
||||||
},
|
},
|
||||||
"50": {
|
"42": {
|
||||||
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
|
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
|
||||||
|
},
|
||||||
|
"50": {
|
||||||
|
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
import {intervalUtils} from '@0xproject/utils';
|
import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from '@0xproject/types';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { AbiDecoder, intervalUtils } from '@0xproject/utils';
|
||||||
import {Block, BlockAndLogStreamer} from 'ethereumjs-blockstream';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
|
import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Artifact,
|
Artifact,
|
||||||
BlockParamLiteral,
|
|
||||||
BlockRange,
|
BlockRange,
|
||||||
ContractEventArgs,
|
ContractEventArgs,
|
||||||
ContractEvents,
|
ContractEvents,
|
||||||
EventCallback,
|
EventCallback,
|
||||||
IndexedFilterValues,
|
IndexedFilterValues,
|
||||||
InternalZeroExError,
|
InternalZeroExError,
|
||||||
LogWithDecodedArgs,
|
|
||||||
RawLog,
|
|
||||||
ZeroExError,
|
ZeroExError,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {AbiDecoder} from '../utils/abi_decoder';
|
import { constants } from '../utils/constants';
|
||||||
import {constants} from '../utils/constants';
|
import { filterUtils } from '../utils/filter_utils';
|
||||||
import {filterUtils} from '../utils/filter_utils';
|
|
||||||
|
|
||||||
const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {[contractName: string]: ZeroExError} = {
|
const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {
|
||||||
|
[contractName: string]: ZeroExError;
|
||||||
|
} = {
|
||||||
ZRX: ZeroExError.ZRXContractDoesNotExist,
|
ZRX: ZeroExError.ZRXContractDoesNotExist,
|
||||||
EtherToken: ZeroExError.EtherTokenContractDoesNotExist,
|
EtherToken: ZeroExError.EtherTokenContractDoesNotExist,
|
||||||
Token: ZeroExError.TokenContractDoesNotExist,
|
Token: ZeroExError.TokenContractDoesNotExist,
|
||||||
@@ -32,25 +31,25 @@ const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {[contractName: string]: ZeroExError} =
|
|||||||
|
|
||||||
export class ContractWrapper {
|
export class ContractWrapper {
|
||||||
protected _web3Wrapper: Web3Wrapper;
|
protected _web3Wrapper: Web3Wrapper;
|
||||||
private _networkId: number;
|
protected _networkId: number;
|
||||||
private _abiDecoder?: AbiDecoder;
|
private _blockAndLogStreamerIfExists?: BlockAndLogStreamer;
|
||||||
private _blockAndLogStreamerIfExists: BlockAndLogStreamer|undefined;
|
private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer;
|
||||||
private _blockAndLogStreamInterval: NodeJS.Timer;
|
private _filters: { [filterToken: string]: FilterObject };
|
||||||
private _filters: {[filterToken: string]: Web3.FilterObject};
|
private _filterCallbacks: {
|
||||||
private _filterCallbacks: {[filterToken: string]: EventCallback<ContractEventArgs>};
|
[filterToken: string]: EventCallback<ContractEventArgs>;
|
||||||
private _onLogAddedSubscriptionToken: string|undefined;
|
};
|
||||||
private _onLogRemovedSubscriptionToken: string|undefined;
|
private _onLogAddedSubscriptionToken: string | undefined;
|
||||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder?: AbiDecoder) {
|
private _onLogRemovedSubscriptionToken: string | undefined;
|
||||||
|
constructor(web3Wrapper: Web3Wrapper, networkId: number) {
|
||||||
this._web3Wrapper = web3Wrapper;
|
this._web3Wrapper = web3Wrapper;
|
||||||
this._networkId = networkId;
|
this._networkId = networkId;
|
||||||
this._abiDecoder = abiDecoder;
|
|
||||||
this._filters = {};
|
this._filters = {};
|
||||||
this._filterCallbacks = {};
|
this._filterCallbacks = {};
|
||||||
this._blockAndLogStreamerIfExists = undefined;
|
this._blockAndLogStreamerIfExists = undefined;
|
||||||
this._onLogAddedSubscriptionToken = undefined;
|
this._onLogAddedSubscriptionToken = undefined;
|
||||||
this._onLogRemovedSubscriptionToken = undefined;
|
this._onLogRemovedSubscriptionToken = undefined;
|
||||||
}
|
}
|
||||||
protected unsubscribeAll(): void {
|
protected _unsubscribeAll(): void {
|
||||||
const filterTokens = _.keys(this._filterCallbacks);
|
const filterTokens = _.keys(this._filterCallbacks);
|
||||||
_.each(filterTokens, filterToken => {
|
_.each(filterTokens, filterToken => {
|
||||||
this._unsubscribe(filterToken);
|
this._unsubscribe(filterToken);
|
||||||
@@ -71,36 +70,46 @@ export class ContractWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected _subscribe<ArgsType extends ContractEventArgs>(
|
protected _subscribe<ArgsType extends ContractEventArgs>(
|
||||||
address: string, eventName: ContractEvents, indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi,
|
address: string,
|
||||||
callback: EventCallback<ArgsType>): string {
|
eventName: ContractEvents,
|
||||||
|
indexFilterValues: IndexedFilterValues,
|
||||||
|
abi: ContractAbi,
|
||||||
|
callback: EventCallback<ArgsType>,
|
||||||
|
): string {
|
||||||
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi);
|
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi);
|
||||||
if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
||||||
this._startBlockAndLogStream();
|
this._startBlockAndLogStream();
|
||||||
}
|
}
|
||||||
const filterToken = filterUtils.generateUUID();
|
const filterToken = filterUtils.generateUUID();
|
||||||
this._filters[filterToken] = filter;
|
this._filters[filterToken] = filter;
|
||||||
this._filterCallbacks[filterToken] = callback;
|
this._filterCallbacks[filterToken] = callback as EventCallback<ContractEventArgs>;
|
||||||
return filterToken;
|
return filterToken;
|
||||||
}
|
}
|
||||||
protected async _getLogsAsync<ArgsType extends ContractEventArgs>(
|
protected async _getLogsAsync<ArgsType extends ContractEventArgs>(
|
||||||
address: string, eventName: ContractEvents, blockRange: BlockRange,
|
address: string,
|
||||||
indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
eventName: ContractEvents,
|
||||||
|
blockRange: BlockRange,
|
||||||
|
indexFilterValues: IndexedFilterValues,
|
||||||
|
abi: ContractAbi,
|
||||||
|
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||||
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange);
|
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange);
|
||||||
const logs = await this._web3Wrapper.getLogsAsync(filter);
|
const logs = await this._web3Wrapper.getLogsAsync(filter);
|
||||||
const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
|
const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
|
||||||
return logsWithDecodedArguments;
|
return logsWithDecodedArguments;
|
||||||
}
|
}
|
||||||
protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
|
protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
|
||||||
log: Web3.LogEntry): LogWithDecodedArgs<ArgsType>|RawLog {
|
log: LogEntry,
|
||||||
if (_.isUndefined(this._abiDecoder)) {
|
): LogWithDecodedArgs<ArgsType> | RawLog {
|
||||||
|
if (_.isUndefined(this._web3Wrapper.abiDecoder)) {
|
||||||
throw new Error(InternalZeroExError.NoAbiDecoder);
|
throw new Error(InternalZeroExError.NoAbiDecoder);
|
||||||
}
|
}
|
||||||
const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
|
const logWithDecodedArgs = this._web3Wrapper.abiDecoder.tryToDecodeLogOrNoop(log);
|
||||||
return logWithDecodedArgs;
|
return logWithDecodedArgs;
|
||||||
}
|
}
|
||||||
protected async _instantiateContractIfExistsAsync(
|
protected async _getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifact: Artifact, addressIfExists?: string,
|
artifact: Artifact,
|
||||||
): Promise<Web3.ContractInstance> {
|
addressIfExists?: string,
|
||||||
|
): Promise<[ContractAbi, string]> {
|
||||||
let contractAddress: string;
|
let contractAddress: string;
|
||||||
if (_.isUndefined(addressIfExists)) {
|
if (_.isUndefined(addressIfExists)) {
|
||||||
if (_.isUndefined(artifact.networks[this._networkId])) {
|
if (_.isUndefined(artifact.networks[this._networkId])) {
|
||||||
@@ -114,10 +123,8 @@ export class ContractWrapper {
|
|||||||
if (!doesContractExist) {
|
if (!doesContractExist) {
|
||||||
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
|
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
|
||||||
}
|
}
|
||||||
const contractInstance = this._web3Wrapper.getContractInstance(
|
const abiAndAddress: [ContractAbi, string] = [artifact.abi, contractAddress];
|
||||||
artifact.abi, contractAddress,
|
return abiAndAddress;
|
||||||
);
|
|
||||||
return contractInstance;
|
|
||||||
}
|
}
|
||||||
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
|
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
|
||||||
if (_.isUndefined(addressIfExists)) {
|
if (_.isUndefined(addressIfExists)) {
|
||||||
@@ -130,8 +137,8 @@ export class ContractWrapper {
|
|||||||
return addressIfExists;
|
return addressIfExists;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, log: Web3.LogEntry): void {
|
private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, log: LogEntry): void {
|
||||||
_.forEach(this._filters, (filter: Web3.FilterObject, filterToken: string) => {
|
_.forEach(this._filters, (filter: FilterObject, filterToken: string) => {
|
||||||
if (filterUtils.matchesFilter(log, filter)) {
|
if (filterUtils.matchesFilter(log, filter)) {
|
||||||
const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>;
|
const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>;
|
||||||
const logEvent = {
|
const logEvent = {
|
||||||
@@ -152,8 +159,10 @@ export class ContractWrapper {
|
|||||||
);
|
);
|
||||||
const catchAllLogFilter = {};
|
const catchAllLogFilter = {};
|
||||||
this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
|
this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
|
||||||
this._blockAndLogStreamInterval = intervalUtils.setAsyncExcludingInterval(
|
this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval(
|
||||||
this._reconcileBlockAsync.bind(this), constants.DEFAULT_BLOCK_POLLING_INTERVAL,
|
this._reconcileBlockAsync.bind(this),
|
||||||
|
constants.DEFAULT_BLOCK_POLLING_INTERVAL,
|
||||||
|
this._onReconcileBlockError.bind(this),
|
||||||
);
|
);
|
||||||
let isRemoved = false;
|
let isRemoved = false;
|
||||||
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
|
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
|
||||||
@@ -164,28 +173,30 @@ export class ContractWrapper {
|
|||||||
this._onLogStateChanged.bind(this, isRemoved),
|
this._onLogStateChanged.bind(this, isRemoved),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
private _onReconcileBlockError(err: Error): void {
|
||||||
|
const filterTokens = _.keys(this._filterCallbacks);
|
||||||
|
_.each(filterTokens, filterToken => {
|
||||||
|
this._unsubscribe(filterToken, err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private _setNetworkId(networkId: number): void {
|
||||||
|
this._networkId = networkId;
|
||||||
|
}
|
||||||
private _stopBlockAndLogStream(): void {
|
private _stopBlockAndLogStream(): void {
|
||||||
if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
||||||
throw new Error(ZeroExError.SubscriptionNotFound);
|
throw new Error(ZeroExError.SubscriptionNotFound);
|
||||||
}
|
}
|
||||||
this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string);
|
this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string);
|
||||||
this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string);
|
this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string);
|
||||||
intervalUtils.clearAsyncExcludingInterval(this._blockAndLogStreamInterval);
|
intervalUtils.clearAsyncExcludingInterval(this._blockAndLogStreamIntervalIfExists as NodeJS.Timer);
|
||||||
delete this._blockAndLogStreamerIfExists;
|
delete this._blockAndLogStreamerIfExists;
|
||||||
}
|
}
|
||||||
private async _reconcileBlockAsync(): Promise<void> {
|
private async _reconcileBlockAsync(): Promise<void> {
|
||||||
try {
|
const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
|
||||||
const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
|
// We need to coerce to Block type cause Web3.Block includes types for mempool blocks
|
||||||
// We need to coerce to Block type cause Web3.Block includes types for mempool blocks
|
if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
||||||
if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
// If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
|
||||||
// If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
|
await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block);
|
||||||
await this._blockAndLogStreamerIfExists.reconcileNewBlock(latestBlock as any as Block);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
const filterTokens = _.keys(this._filterCallbacks);
|
|
||||||
_.each(filterTokens, filterToken => {
|
|
||||||
this._unsubscribe(filterToken, err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,28 @@
|
|||||||
import {schemas} from '@0xproject/json-schemas';
|
import { schemas } from '@0xproject/json-schemas';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { LogWithDecodedArgs } from '@0xproject/types';
|
||||||
import BigNumber from 'bignumber.js';
|
import { AbiDecoder, BigNumber } from '@0xproject/utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {artifacts} from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
import {
|
import { BlockRange, EventCallback, IndexedFilterValues, TransactionOpts, ZeroExError } from '../types';
|
||||||
BlockRange,
|
import { assert } from '../utils/assert';
|
||||||
EtherTokenContractEventArgs,
|
|
||||||
EtherTokenEvents,
|
|
||||||
EventCallback,
|
|
||||||
IndexedFilterValues,
|
|
||||||
LogWithDecodedArgs,
|
|
||||||
TransactionOpts,
|
|
||||||
ZeroExError,
|
|
||||||
} from '../types';
|
|
||||||
import {AbiDecoder} from '../utils/abi_decoder';
|
|
||||||
import {assert} from '../utils/assert';
|
|
||||||
|
|
||||||
import {ContractWrapper} from './contract_wrapper';
|
import { ContractWrapper } from './contract_wrapper';
|
||||||
import {EtherTokenContract} from './generated/ether_token';
|
import { EtherTokenContract, EtherTokenContractEventArgs, EtherTokenEvents } from './generated/ether_token';
|
||||||
import {TokenWrapper} from './token_wrapper';
|
import { TokenWrapper } from './token_wrapper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
|
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
|
||||||
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
|
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
|
||||||
*/
|
*/
|
||||||
export class EtherTokenWrapper extends ContractWrapper {
|
export class EtherTokenWrapper extends ContractWrapper {
|
||||||
private _etherTokenContractsByAddress: {[address: string]: EtherTokenContract} = {};
|
private _etherTokenContractsByAddress: {
|
||||||
|
[address: string]: EtherTokenContract;
|
||||||
|
} = {};
|
||||||
private _tokenWrapper: TokenWrapper;
|
private _tokenWrapper: TokenWrapper;
|
||||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder, tokenWrapper: TokenWrapper) {
|
constructor(web3Wrapper: Web3Wrapper, networkId: number, tokenWrapper: TokenWrapper) {
|
||||||
super(web3Wrapper, networkId, abiDecoder);
|
super(web3Wrapper, networkId);
|
||||||
this._tokenWrapper = tokenWrapper;
|
this._tokenWrapper = tokenWrapper;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -43,17 +36,23 @@ export class EtherTokenWrapper extends ContractWrapper {
|
|||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
public async depositAsync(
|
public async depositAsync(
|
||||||
etherTokenAddress: string, amountInWei: BigNumber, depositor: string, txOpts: TransactionOpts = {},
|
etherTokenAddress: string,
|
||||||
|
amountInWei: BigNumber,
|
||||||
|
depositor: string,
|
||||||
|
txOpts: TransactionOpts = {},
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
|
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||||
await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
|
await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
|
||||||
|
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||||
|
const normalizedDepositorAddress = depositor.toLowerCase();
|
||||||
|
|
||||||
const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(depositor);
|
const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(normalizedDepositorAddress);
|
||||||
assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit);
|
assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit);
|
||||||
|
|
||||||
const wethContract = await this._getEtherTokenContractAsync(etherTokenAddress);
|
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
|
||||||
const txHash = await wethContract.deposit.sendTransactionAsync({
|
const txHash = await wethContract.deposit.sendTransactionAsync({
|
||||||
from: depositor,
|
from: normalizedDepositorAddress,
|
||||||
value: amountInWei,
|
value: amountInWei,
|
||||||
gas: txOpts.gasLimit,
|
gas: txOpts.gasLimit,
|
||||||
gasPrice: txOpts.gasPrice,
|
gasPrice: txOpts.gasPrice,
|
||||||
@@ -65,22 +64,31 @@ export class EtherTokenWrapper extends ContractWrapper {
|
|||||||
* equivalent number of wrapped ETH tokens.
|
* equivalent number of wrapped ETH tokens.
|
||||||
* @param etherTokenAddress EtherToken address you wish to withdraw from.
|
* @param etherTokenAddress EtherToken address you wish to withdraw from.
|
||||||
* @param amountInWei Amount of ETH in Wei the caller wishes to withdraw.
|
* @param amountInWei Amount of ETH in Wei the caller wishes to withdraw.
|
||||||
* @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawl.
|
* @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawal.
|
||||||
* @param txOpts Transaction parameters.
|
* @param txOpts Transaction parameters.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
public async withdrawAsync(
|
public async withdrawAsync(
|
||||||
etherTokenAddress: string, amountInWei: BigNumber, withdrawer: string, txOpts: TransactionOpts = {},
|
etherTokenAddress: string,
|
||||||
|
amountInWei: BigNumber,
|
||||||
|
withdrawer: string,
|
||||||
|
txOpts: TransactionOpts = {},
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||||
|
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||||
await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
|
await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
|
||||||
|
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||||
|
const normalizedWithdrawerAddress = withdrawer.toLowerCase();
|
||||||
|
|
||||||
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(etherTokenAddress, withdrawer);
|
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(
|
||||||
|
normalizedEtherTokenAddress,
|
||||||
|
normalizedWithdrawerAddress,
|
||||||
|
);
|
||||||
assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal);
|
assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal);
|
||||||
|
|
||||||
const wethContract = await this._getEtherTokenContractAsync(etherTokenAddress);
|
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
|
||||||
const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
|
const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
|
||||||
from: withdrawer,
|
from: normalizedWithdrawerAddress,
|
||||||
gas: txOpts.gasLimit,
|
gas: txOpts.gasLimit,
|
||||||
gasPrice: txOpts.gasPrice,
|
gasPrice: txOpts.gasPrice,
|
||||||
});
|
});
|
||||||
@@ -88,7 +96,7 @@ export class EtherTokenWrapper extends ContractWrapper {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Gets historical logs without creating a subscription
|
* Gets historical logs without creating a subscription
|
||||||
* @param etherTokenAddress An address of the ether token that emmited the logs.
|
* @param etherTokenAddress An address of the ether token that emitted the logs.
|
||||||
* @param eventName The ether token contract event you would like to subscribe to.
|
* @param eventName The ether token contract event you would like to subscribe to.
|
||||||
* @param blockRange Block range to get logs from.
|
* @param blockRange Block range to get logs from.
|
||||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||||
@@ -96,14 +104,22 @@ export class EtherTokenWrapper extends ContractWrapper {
|
|||||||
* @return Array of logs that match the parameters
|
* @return Array of logs that match the parameters
|
||||||
*/
|
*/
|
||||||
public async getLogsAsync<ArgsType extends EtherTokenContractEventArgs>(
|
public async getLogsAsync<ArgsType extends EtherTokenContractEventArgs>(
|
||||||
etherTokenAddress: string, eventName: EtherTokenEvents, blockRange: BlockRange,
|
etherTokenAddress: string,
|
||||||
indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
eventName: EtherTokenEvents,
|
||||||
|
blockRange: BlockRange,
|
||||||
|
indexFilterValues: IndexedFilterValues,
|
||||||
|
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||||
|
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||||
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
||||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||||
const logs = await this._getLogsAsync<ArgsType>(
|
const logs = await this._getLogsAsync<ArgsType>(
|
||||||
etherTokenAddress, eventName, blockRange, indexFilterValues, artifacts.EtherTokenArtifact.abi,
|
normalizedEtherTokenAddress,
|
||||||
|
eventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
|
artifacts.EtherTokenArtifact.abi,
|
||||||
);
|
);
|
||||||
return logs;
|
return logs;
|
||||||
}
|
}
|
||||||
@@ -117,14 +133,22 @@ export class EtherTokenWrapper extends ContractWrapper {
|
|||||||
* @return Subscription token used later to unsubscribe
|
* @return Subscription token used later to unsubscribe
|
||||||
*/
|
*/
|
||||||
public subscribe<ArgsType extends EtherTokenContractEventArgs>(
|
public subscribe<ArgsType extends EtherTokenContractEventArgs>(
|
||||||
etherTokenAddress: string, eventName: EtherTokenEvents, indexFilterValues: IndexedFilterValues,
|
etherTokenAddress: string,
|
||||||
callback: EventCallback<ArgsType>): string {
|
eventName: EtherTokenEvents,
|
||||||
|
indexFilterValues: IndexedFilterValues,
|
||||||
|
callback: EventCallback<ArgsType>,
|
||||||
|
): string {
|
||||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||||
|
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||||
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
||||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||||
assert.isFunction('callback', callback);
|
assert.isFunction('callback', callback);
|
||||||
const subscriptionToken = this._subscribe<ArgsType>(
|
const subscriptionToken = this._subscribe<ArgsType>(
|
||||||
etherTokenAddress, eventName, indexFilterValues, artifacts.EtherTokenArtifact.abi, callback,
|
normalizedEtherTokenAddress,
|
||||||
|
eventName,
|
||||||
|
indexFilterValues,
|
||||||
|
artifacts.EtherTokenArtifact.abi,
|
||||||
|
callback,
|
||||||
);
|
);
|
||||||
return subscriptionToken;
|
return subscriptionToken;
|
||||||
}
|
}
|
||||||
@@ -139,7 +163,20 @@ export class EtherTokenWrapper extends ContractWrapper {
|
|||||||
* Cancels all existing subscriptions
|
* Cancels all existing subscriptions
|
||||||
*/
|
*/
|
||||||
public unsubscribeAll(): void {
|
public unsubscribeAll(): void {
|
||||||
super.unsubscribeAll();
|
super._unsubscribeAll();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Retrieves the Ethereum address of the EtherToken contract deployed on the network
|
||||||
|
* that the user-passed web3 provider is connected to. If it's not Kovan, Ropsten, Rinkeby, Mainnet or TestRPC
|
||||||
|
* (networkId: 50), it will return undefined (e.g a private network).
|
||||||
|
* @returns The Ethereum address of the EtherToken contract or undefined.
|
||||||
|
*/
|
||||||
|
public getContractAddressIfExists(): string | undefined {
|
||||||
|
const networkSpecificArtifact = artifacts.EtherTokenArtifact.networks[this._networkId];
|
||||||
|
const contractAddressIfExists = _.isUndefined(networkSpecificArtifact)
|
||||||
|
? undefined
|
||||||
|
: networkSpecificArtifact.address;
|
||||||
|
return contractAddressIfExists;
|
||||||
}
|
}
|
||||||
private _invalidateContractInstance(): void {
|
private _invalidateContractInstance(): void {
|
||||||
this.unsubscribeAll();
|
this.unsubscribeAll();
|
||||||
@@ -150,10 +187,16 @@ export class EtherTokenWrapper extends ContractWrapper {
|
|||||||
if (!_.isUndefined(etherTokenContract)) {
|
if (!_.isUndefined(etherTokenContract)) {
|
||||||
return etherTokenContract;
|
return etherTokenContract;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.EtherTokenArtifact, etherTokenAddress,
|
artifacts.EtherTokenArtifact,
|
||||||
|
etherTokenAddress,
|
||||||
|
);
|
||||||
|
const contractInstance = new EtherTokenContract(
|
||||||
|
abi,
|
||||||
|
address,
|
||||||
|
this._web3Wrapper.getProvider(),
|
||||||
|
this._web3Wrapper.getContractDefaults(),
|
||||||
);
|
);
|
||||||
const contractInstance = new EtherTokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
|
||||||
etherTokenContract = contractInstance;
|
etherTokenContract = contractInstance;
|
||||||
this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
|
this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
|
||||||
return etherTokenContract;
|
return etherTokenContract;
|
||||||
|
|||||||
@@ -1,43 +1,46 @@
|
|||||||
import {schemas} from '@0xproject/json-schemas';
|
import { schemas } from '@0xproject/json-schemas';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
|
||||||
import BigNumber from 'bignumber.js';
|
|
||||||
import * as _ from 'lodash';
|
|
||||||
import * as Web3 from 'web3';
|
|
||||||
|
|
||||||
import {artifacts} from '../artifacts';
|
|
||||||
import {
|
import {
|
||||||
BlockParamLiteral,
|
BlockParamLiteral,
|
||||||
BlockRange,
|
|
||||||
DecodedLogArgs,
|
DecodedLogArgs,
|
||||||
ECSignature,
|
ECSignature,
|
||||||
|
LogEntry,
|
||||||
|
LogWithDecodedArgs,
|
||||||
|
Order,
|
||||||
|
SignedOrder,
|
||||||
|
} from '@0xproject/types';
|
||||||
|
import { AbiDecoder, BigNumber } from '@0xproject/utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts } from '../artifacts';
|
||||||
|
import {
|
||||||
|
BlockRange,
|
||||||
EventCallback,
|
EventCallback,
|
||||||
ExchangeContractErrCodes,
|
ExchangeContractErrCodes,
|
||||||
ExchangeContractErrs,
|
ExchangeContractErrs,
|
||||||
ExchangeContractEventArgs,
|
|
||||||
ExchangeEvents,
|
|
||||||
IndexedFilterValues,
|
IndexedFilterValues,
|
||||||
LogErrorContractEventArgs,
|
|
||||||
LogWithDecodedArgs,
|
|
||||||
MethodOpts,
|
MethodOpts,
|
||||||
Order,
|
|
||||||
OrderAddresses,
|
OrderAddresses,
|
||||||
OrderCancellationRequest,
|
OrderCancellationRequest,
|
||||||
OrderFillRequest,
|
OrderFillRequest,
|
||||||
OrderTransactionOpts,
|
OrderTransactionOpts,
|
||||||
OrderValues,
|
OrderValues,
|
||||||
SignedOrder,
|
|
||||||
ValidateOrderFillableOpts,
|
ValidateOrderFillableOpts,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {AbiDecoder} from '../utils/abi_decoder';
|
import { assert } from '../utils/assert';
|
||||||
import {assert} from '../utils/assert';
|
import { decorators } from '../utils/decorators';
|
||||||
import {decorators} from '../utils/decorators';
|
import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator';
|
||||||
import {ExchangeTransferSimulator} from '../utils/exchange_transfer_simulator';
|
import { OrderValidationUtils } from '../utils/order_validation_utils';
|
||||||
import {OrderValidationUtils} from '../utils/order_validation_utils';
|
import { utils } from '../utils/utils';
|
||||||
import {utils} from '../utils/utils';
|
|
||||||
|
|
||||||
import {ContractWrapper} from './contract_wrapper';
|
import { ContractWrapper } from './contract_wrapper';
|
||||||
import {ExchangeContract} from './generated/exchange';
|
import {
|
||||||
import {TokenWrapper} from './token_wrapper';
|
ExchangeContract,
|
||||||
|
ExchangeContractEventArgs,
|
||||||
|
ExchangeEvents,
|
||||||
|
LogErrorContractEventArgs,
|
||||||
|
} from './generated/exchange';
|
||||||
|
import { TokenWrapper } from './token_wrapper';
|
||||||
|
|
||||||
const SHOULD_VALIDATE_BY_DEFAULT = true;
|
const SHOULD_VALIDATE_BY_DEFAULT = true;
|
||||||
|
|
||||||
@@ -81,12 +84,18 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
];
|
];
|
||||||
return [orderAddresses, orderValues];
|
return [orderAddresses, orderValues];
|
||||||
}
|
}
|
||||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder,
|
constructor(
|
||||||
tokenWrapper: TokenWrapper, contractAddressIfExists?: string) {
|
web3Wrapper: Web3Wrapper,
|
||||||
super(web3Wrapper, networkId, abiDecoder);
|
networkId: number,
|
||||||
|
tokenWrapper: TokenWrapper,
|
||||||
|
contractAddressIfExists?: string,
|
||||||
|
zrxContractAddressIfExists?: string,
|
||||||
|
) {
|
||||||
|
super(web3Wrapper, networkId);
|
||||||
this._tokenWrapper = tokenWrapper;
|
this._tokenWrapper = tokenWrapper;
|
||||||
this._orderValidationUtils = new OrderValidationUtils(this);
|
this._orderValidationUtils = new OrderValidationUtils(this);
|
||||||
this._contractAddressIfExists = contractAddressIfExists;
|
this._contractAddressIfExists = contractAddressIfExists;
|
||||||
|
this._zrxContractAddressIfExists = zrxContractAddressIfExists;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total
|
* Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total
|
||||||
@@ -97,14 +106,16 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @param methodOpts Optional arguments this method accepts.
|
* @param methodOpts Optional arguments this method accepts.
|
||||||
* @return The amount of the order (in taker tokens) that has either been filled or cancelled.
|
* @return The amount of the order (in taker tokens) that has either been filled or cancelled.
|
||||||
*/
|
*/
|
||||||
public async getUnavailableTakerAmountAsync(orderHash: string,
|
public async getUnavailableTakerAmountAsync(orderHash: string, methodOpts?: MethodOpts): Promise<BigNumber> {
|
||||||
methodOpts?: MethodOpts): Promise<BigNumber> {
|
|
||||||
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
|
||||||
|
|
||||||
const exchangeContract = await this._getExchangeContractAsync();
|
const exchangeContract = await this._getExchangeContractAsync();
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||||
|
const txData = {};
|
||||||
let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(
|
let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(
|
||||||
orderHash, defaultBlock,
|
orderHash,
|
||||||
|
txData,
|
||||||
|
defaultBlock,
|
||||||
);
|
);
|
||||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount);
|
unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount);
|
||||||
@@ -121,7 +132,8 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
|
|
||||||
const exchangeContract = await this._getExchangeContractAsync();
|
const exchangeContract = await this._getExchangeContractAsync();
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||||
let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, defaultBlock);
|
const txData = {};
|
||||||
|
let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, txData, defaultBlock);
|
||||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
|
fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
|
||||||
return fillAmountInBaseUnits;
|
return fillAmountInBaseUnits;
|
||||||
@@ -138,7 +150,8 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
|
|
||||||
const exchangeContract = await this._getExchangeContractAsync();
|
const exchangeContract = await this._getExchangeContractAsync();
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||||
let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, defaultBlock);
|
const txData = {};
|
||||||
|
let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, txData, defaultBlock);
|
||||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
|
cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
|
||||||
return cancelledAmountInBaseUnits;
|
return cancelledAmountInBaseUnits;
|
||||||
@@ -157,30 +170,39 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw
|
* @param shouldThrowOnInsufficientBalanceOrAllowance Whether or not you wish for the contract call to throw
|
||||||
* if upon execution the tokens cannot be transferred.
|
* if upon execution the tokens cannot be transferred.
|
||||||
* @param takerAddress The user Ethereum address who would like to fill this order.
|
* @param takerAddress The user Ethereum address who would like to fill this order.
|
||||||
* Must be available via the supplied Web3.Provider
|
* Must be available via the supplied Provider
|
||||||
* passed to 0x.js.
|
* passed to 0x.js.
|
||||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
@decorators.asyncZeroExErrorHandler
|
@decorators.asyncZeroExErrorHandler
|
||||||
public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber,
|
public async fillOrderAsync(
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
signedOrder: SignedOrder,
|
||||||
takerAddress: string,
|
fillTakerTokenAmount: BigNumber,
|
||||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||||
|
takerAddress: string,
|
||||||
|
orderTransactionOpts: OrderTransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||||
|
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||||
|
|
||||||
const exchangeInstance = await this._getExchangeContractAsync();
|
const exchangeInstance = await this._getExchangeContractAsync();
|
||||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||||
SHOULD_VALIDATE_BY_DEFAULT :
|
? SHOULD_VALIDATE_BY_DEFAULT
|
||||||
orderTransactionOpts.shouldValidate;
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
|
fillTakerTokenAmount,
|
||||||
|
normalizedTakerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
|
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
|
||||||
@@ -194,7 +216,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
signedOrder.ecSignature.r,
|
signedOrder.ecSignature.r,
|
||||||
signedOrder.ecSignature.s,
|
signedOrder.ecSignature.s,
|
||||||
{
|
{
|
||||||
from: takerAddress,
|
from: normalizedTakerAddress,
|
||||||
gas: orderTransactionOpts.gasLimit,
|
gas: orderTransactionOpts.gasLimit,
|
||||||
gasPrice: orderTransactionOpts.gasPrice,
|
gasPrice: orderTransactionOpts.gasPrice,
|
||||||
},
|
},
|
||||||
@@ -213,36 +235,54 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* If set to false, the call will continue to fill subsequent
|
* If set to false, the call will continue to fill subsequent
|
||||||
* signedOrders even when some cannot be filled.
|
* signedOrders even when some cannot be filled.
|
||||||
* @param takerAddress The user Ethereum address who would like to fill these
|
* @param takerAddress The user Ethereum address who would like to fill these
|
||||||
* orders. Must be available via the supplied Web3.Provider
|
* orders. Must be available via the supplied Provider
|
||||||
* passed to 0x.js.
|
* passed to 0x.js.
|
||||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
@decorators.asyncZeroExErrorHandler
|
@decorators.asyncZeroExErrorHandler
|
||||||
public async fillOrdersUpToAsync(signedOrders: SignedOrder[], fillTakerTokenAmount: BigNumber,
|
public async fillOrdersUpToAsync(
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
signedOrders: SignedOrder[],
|
||||||
takerAddress: string,
|
fillTakerTokenAmount: BigNumber,
|
||||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||||
|
takerAddress: string,
|
||||||
|
orderTransactionOpts: OrderTransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||||
const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress);
|
const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress);
|
||||||
assert.hasAtMostOneUniqueValue(takerTokenAddresses,
|
assert.hasAtMostOneUniqueValue(
|
||||||
ExchangeContractErrs.MultipleTakerTokensInFillUpToDisallowed);
|
takerTokenAddresses,
|
||||||
|
ExchangeContractErrs.MultipleTakerTokensInFillUpToDisallowed,
|
||||||
|
);
|
||||||
const exchangeContractAddresses = _.map(signedOrders, signedOrder => signedOrder.exchangeContractAddress);
|
const exchangeContractAddresses = _.map(signedOrders, signedOrder => signedOrder.exchangeContractAddress);
|
||||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
assert.hasAtMostOneUniqueValue(
|
||||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
|
exchangeContractAddresses,
|
||||||
|
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||||
|
);
|
||||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||||
|
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||||
|
|
||||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||||
SHOULD_VALIDATE_BY_DEFAULT :
|
? SHOULD_VALIDATE_BY_DEFAULT
|
||||||
orderTransactionOpts.shouldValidate;
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
|
let filledTakerTokenAmount = new BigNumber(0);
|
||||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||||
for (const signedOrder of signedOrders) {
|
for (const signedOrder of signedOrders) {
|
||||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
const singleFilledTakerTokenAmount = await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
|
fillTakerTokenAmount.minus(filledTakerTokenAmount),
|
||||||
|
normalizedTakerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
|
);
|
||||||
|
filledTakerTokenAmount = filledTakerTokenAmount.plus(singleFilledTakerTokenAmount);
|
||||||
|
if (filledTakerTokenAmount.eq(fillTakerTokenAmount)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +313,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
rArray,
|
rArray,
|
||||||
sArray,
|
sArray,
|
||||||
{
|
{
|
||||||
from: takerAddress,
|
from: normalizedTakerAddress,
|
||||||
gas: orderTransactionOpts.gasLimit,
|
gas: orderTransactionOpts.gasLimit,
|
||||||
gasPrice: orderTransactionOpts.gasPrice,
|
gasPrice: orderTransactionOpts.gasPrice,
|
||||||
},
|
},
|
||||||
@@ -295,34 +335,42 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* cannot be filled.
|
* cannot be filled.
|
||||||
* @param takerAddress The user Ethereum address who would like to fill
|
* @param takerAddress The user Ethereum address who would like to fill
|
||||||
* these orders. Must be available via the supplied
|
* these orders. Must be available via the supplied
|
||||||
* Web3.Provider passed to 0x.js.
|
* Provider passed to 0x.js.
|
||||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
@decorators.asyncZeroExErrorHandler
|
@decorators.asyncZeroExErrorHandler
|
||||||
public async batchFillOrdersAsync(orderFillRequests: OrderFillRequest[],
|
public async batchFillOrdersAsync(
|
||||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
orderFillRequests: OrderFillRequest[],
|
||||||
takerAddress: string,
|
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
takerAddress: string,
|
||||||
|
orderTransactionOpts: OrderTransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema);
|
assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema);
|
||||||
const exchangeContractAddresses = _.map(
|
const exchangeContractAddresses = _.map(
|
||||||
orderFillRequests,
|
orderFillRequests,
|
||||||
orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
|
orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
|
||||||
);
|
);
|
||||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
assert.hasAtMostOneUniqueValue(
|
||||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
|
exchangeContractAddresses,
|
||||||
|
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||||
|
);
|
||||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||||
SHOULD_VALIDATE_BY_DEFAULT :
|
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||||
orderTransactionOpts.shouldValidate;
|
? SHOULD_VALIDATE_BY_DEFAULT
|
||||||
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||||
for (const orderFillRequest of orderFillRequests) {
|
for (const orderFillRequest of orderFillRequests) {
|
||||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount,
|
exchangeTradeEmulator,
|
||||||
takerAddress, zrxTokenAddress,
|
orderFillRequest.signedOrder,
|
||||||
|
orderFillRequest.takerTokenFillAmount,
|
||||||
|
normalizedTakerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,7 +402,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
rArray,
|
rArray,
|
||||||
sArray,
|
sArray,
|
||||||
{
|
{
|
||||||
from: takerAddress,
|
from: normalizedTakerAddress,
|
||||||
gas: orderTransactionOpts.gasLimit,
|
gas: orderTransactionOpts.gasLimit,
|
||||||
gasPrice: orderTransactionOpts.gasPrice,
|
gasPrice: orderTransactionOpts.gasPrice,
|
||||||
},
|
},
|
||||||
@@ -368,28 +416,37 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* signedOrder you wish to fill.
|
* signedOrder you wish to fill.
|
||||||
* @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
|
* @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
|
||||||
* @param takerAddress The user Ethereum address who would like to fill this order.
|
* @param takerAddress The user Ethereum address who would like to fill this order.
|
||||||
* Must be available via the supplied Web3.Provider passed to 0x.js.
|
* Must be available via the supplied Provider passed to 0x.js.
|
||||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
@decorators.asyncZeroExErrorHandler
|
@decorators.asyncZeroExErrorHandler
|
||||||
public async fillOrKillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber,
|
public async fillOrKillOrderAsync(
|
||||||
takerAddress: string,
|
signedOrder: SignedOrder,
|
||||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
fillTakerTokenAmount: BigNumber,
|
||||||
|
takerAddress: string,
|
||||||
|
orderTransactionOpts: OrderTransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||||
|
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||||
|
|
||||||
const exchangeInstance = await this._getExchangeContractAsync();
|
const exchangeInstance = await this._getExchangeContractAsync();
|
||||||
|
|
||||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||||
SHOULD_VALIDATE_BY_DEFAULT :
|
? SHOULD_VALIDATE_BY_DEFAULT
|
||||||
orderTransactionOpts.shouldValidate;
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||||
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
|
fillTakerTokenAmount,
|
||||||
|
normalizedTakerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
|
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
|
||||||
@@ -401,7 +458,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
signedOrder.ecSignature.r,
|
signedOrder.ecSignature.r,
|
||||||
signedOrder.ecSignature.s,
|
signedOrder.ecSignature.s,
|
||||||
{
|
{
|
||||||
from: takerAddress,
|
from: normalizedTakerAddress,
|
||||||
gas: orderTransactionOpts.gasLimit,
|
gas: orderTransactionOpts.gasLimit,
|
||||||
gasPrice: orderTransactionOpts.gasPrice,
|
gasPrice: orderTransactionOpts.gasPrice,
|
||||||
},
|
},
|
||||||
@@ -413,38 +470,45 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* filled (each to the specified fillAmount) or aborted.
|
* filled (each to the specified fillAmount) or aborted.
|
||||||
* @param orderFillRequests An array of objects that conform to the OrderFillRequest interface.
|
* @param orderFillRequests An array of objects that conform to the OrderFillRequest interface.
|
||||||
* @param takerAddress The user Ethereum address who would like to fill there orders.
|
* @param takerAddress The user Ethereum address who would like to fill there orders.
|
||||||
* Must be available via the supplied Web3.Provider passed to 0x.js.
|
* Must be available via the supplied Provider passed to 0x.js.
|
||||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
@decorators.asyncZeroExErrorHandler
|
@decorators.asyncZeroExErrorHandler
|
||||||
public async batchFillOrKillAsync(orderFillRequests: OrderFillRequest[],
|
public async batchFillOrKillAsync(
|
||||||
takerAddress: string,
|
orderFillRequests: OrderFillRequest[],
|
||||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
takerAddress: string,
|
||||||
assert.doesConformToSchema('orderFillRequests', orderFillRequests,
|
orderTransactionOpts: OrderTransactionOpts = {},
|
||||||
schemas.orderFillRequestsSchema);
|
): Promise<string> {
|
||||||
|
assert.doesConformToSchema('orderFillRequests', orderFillRequests, schemas.orderFillRequestsSchema);
|
||||||
const exchangeContractAddresses = _.map(
|
const exchangeContractAddresses = _.map(
|
||||||
orderFillRequests,
|
orderFillRequests,
|
||||||
orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
|
orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
|
||||||
);
|
);
|
||||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
assert.hasAtMostOneUniqueValue(
|
||||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
|
exchangeContractAddresses,
|
||||||
|
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||||
|
);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||||
|
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||||
if (_.isEmpty(orderFillRequests)) {
|
if (_.isEmpty(orderFillRequests)) {
|
||||||
throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||||
}
|
}
|
||||||
const exchangeInstance = await this._getExchangeContractAsync();
|
const exchangeInstance = await this._getExchangeContractAsync();
|
||||||
|
|
||||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||||
SHOULD_VALIDATE_BY_DEFAULT :
|
? SHOULD_VALIDATE_BY_DEFAULT
|
||||||
orderTransactionOpts.shouldValidate;
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||||
for (const orderFillRequest of orderFillRequests) {
|
for (const orderFillRequest of orderFillRequests) {
|
||||||
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, orderFillRequest.signedOrder, orderFillRequest.takerTokenFillAmount,
|
exchangeTradeEmulator,
|
||||||
takerAddress, zrxTokenAddress,
|
orderFillRequest.signedOrder,
|
||||||
|
orderFillRequest.takerTokenFillAmount,
|
||||||
|
normalizedTakerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -460,8 +524,9 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
|
// We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
|
||||||
const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] =
|
const [orderAddresses, orderValues, fillTakerTokenAmounts, vParams, rParams, sParams] = _.unzip<any>(
|
||||||
_.unzip<any>(orderAddressesValuesAndTakerTokenFillAmounts);
|
orderAddressesValuesAndTakerTokenFillAmounts,
|
||||||
|
);
|
||||||
const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync(
|
const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync(
|
||||||
orderAddresses,
|
orderAddresses,
|
||||||
orderValues,
|
orderValues,
|
||||||
@@ -470,7 +535,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
rParams,
|
rParams,
|
||||||
sParams,
|
sParams,
|
||||||
{
|
{
|
||||||
from: takerAddress,
|
from: normalizedTakerAddress,
|
||||||
gas: orderTransactionOpts.gasLimit,
|
gas: orderTransactionOpts.gasLimit,
|
||||||
gasPrice: orderTransactionOpts.gasPrice,
|
gasPrice: orderTransactionOpts.gasPrice,
|
||||||
},
|
},
|
||||||
@@ -486,23 +551,29 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
@decorators.asyncZeroExErrorHandler
|
@decorators.asyncZeroExErrorHandler
|
||||||
public async cancelOrderAsync(order: Order|SignedOrder,
|
public async cancelOrderAsync(
|
||||||
cancelTakerTokenAmount: BigNumber,
|
order: Order | SignedOrder,
|
||||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
cancelTakerTokenAmount: BigNumber,
|
||||||
|
orderTransactionOpts: OrderTransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||||
assert.isValidBaseUnitAmount('takerTokenCancelAmount', cancelTakerTokenAmount);
|
assert.isValidBaseUnitAmount('takerTokenCancelAmount', cancelTakerTokenAmount);
|
||||||
await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper);
|
await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper);
|
||||||
|
const normalizedMakerAddress = order.maker.toLowerCase();
|
||||||
|
|
||||||
const exchangeInstance = await this._getExchangeContractAsync();
|
const exchangeInstance = await this._getExchangeContractAsync();
|
||||||
|
|
||||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||||
SHOULD_VALIDATE_BY_DEFAULT :
|
? SHOULD_VALIDATE_BY_DEFAULT
|
||||||
orderTransactionOpts.shouldValidate;
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
const orderHash = utils.getOrderHashHex(order);
|
const orderHash = utils.getOrderHashHex(order);
|
||||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||||
order, cancelTakerTokenAmount, unavailableTakerTokenAmount);
|
order,
|
||||||
|
cancelTakerTokenAmount,
|
||||||
|
unavailableTakerTokenAmount,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
|
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
|
||||||
@@ -511,7 +582,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
orderValues,
|
orderValues,
|
||||||
cancelTakerTokenAmount,
|
cancelTakerTokenAmount,
|
||||||
{
|
{
|
||||||
from: order.maker,
|
from: normalizedMakerAddress,
|
||||||
gas: orderTransactionOpts.gasLimit,
|
gas: orderTransactionOpts.gasLimit,
|
||||||
gasPrice: orderTransactionOpts.gasPrice,
|
gasPrice: orderTransactionOpts.gasPrice,
|
||||||
},
|
},
|
||||||
@@ -527,33 +598,42 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
@decorators.asyncZeroExErrorHandler
|
@decorators.asyncZeroExErrorHandler
|
||||||
public async batchCancelOrdersAsync(orderCancellationRequests: OrderCancellationRequest[],
|
public async batchCancelOrdersAsync(
|
||||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
orderCancellationRequests: OrderCancellationRequest[],
|
||||||
assert.doesConformToSchema('orderCancellationRequests', orderCancellationRequests,
|
orderTransactionOpts: OrderTransactionOpts = {},
|
||||||
schemas.orderCancellationRequestsSchema);
|
): Promise<string> {
|
||||||
|
assert.doesConformToSchema(
|
||||||
|
'orderCancellationRequests',
|
||||||
|
orderCancellationRequests,
|
||||||
|
schemas.orderCancellationRequestsSchema,
|
||||||
|
);
|
||||||
const exchangeContractAddresses = _.map(
|
const exchangeContractAddresses = _.map(
|
||||||
orderCancellationRequests,
|
orderCancellationRequests,
|
||||||
orderCancellationRequest => orderCancellationRequest.order.exchangeContractAddress,
|
orderCancellationRequest => orderCancellationRequest.order.exchangeContractAddress,
|
||||||
);
|
);
|
||||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
assert.hasAtMostOneUniqueValue(
|
||||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress);
|
exchangeContractAddresses,
|
||||||
|
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||||
|
);
|
||||||
const makers = _.map(orderCancellationRequests, cancellationRequest => cancellationRequest.order.maker);
|
const makers = _.map(orderCancellationRequests, cancellationRequest => cancellationRequest.order.maker);
|
||||||
assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
|
assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
|
||||||
const maker = makers[0];
|
const maker = makers[0];
|
||||||
await assert.isSenderAddressAsync('maker', maker, this._web3Wrapper);
|
await assert.isSenderAddressAsync('maker', maker, this._web3Wrapper);
|
||||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate) ?
|
const normalizedMakerAddress = maker.toLowerCase();
|
||||||
SHOULD_VALIDATE_BY_DEFAULT :
|
|
||||||
orderTransactionOpts.shouldValidate;
|
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||||
|
? SHOULD_VALIDATE_BY_DEFAULT
|
||||||
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
for (const orderCancellationRequest of orderCancellationRequests) {
|
for (const orderCancellationRequest of orderCancellationRequests) {
|
||||||
const orderHash = utils.getOrderHashHex(orderCancellationRequest.order);
|
const orderHash = utils.getOrderHashHex(orderCancellationRequest.order);
|
||||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||||
orderCancellationRequest.order, orderCancellationRequest.takerTokenCancelAmount,
|
orderCancellationRequest.order,
|
||||||
|
orderCancellationRequest.takerTokenCancelAmount,
|
||||||
unavailableTakerTokenAmount,
|
unavailableTakerTokenAmount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (_.isEmpty(orderCancellationRequests)) {
|
if (_.isEmpty(orderCancellationRequests)) {
|
||||||
throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||||
@@ -566,14 +646,15 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
];
|
];
|
||||||
});
|
});
|
||||||
// We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
|
// We use _.unzip<any> because _.unzip doesn't type check if values have different types :'(
|
||||||
const [orderAddresses, orderValues, cancelTakerTokenAmounts] =
|
const [orderAddresses, orderValues, cancelTakerTokenAmounts] = _.unzip<any>(
|
||||||
_.unzip<any>(orderAddressesValuesAndTakerTokenCancelAmounts);
|
orderAddressesValuesAndTakerTokenCancelAmounts,
|
||||||
|
);
|
||||||
const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync(
|
const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync(
|
||||||
orderAddresses,
|
orderAddresses,
|
||||||
orderValues,
|
orderValues,
|
||||||
cancelTakerTokenAmounts,
|
cancelTakerTokenAmounts,
|
||||||
{
|
{
|
||||||
from: maker,
|
from: normalizedMakerAddress,
|
||||||
gas: orderTransactionOpts.gasLimit,
|
gas: orderTransactionOpts.gasLimit,
|
||||||
gasPrice: orderTransactionOpts.gasPrice,
|
gasPrice: orderTransactionOpts.gasPrice,
|
||||||
},
|
},
|
||||||
@@ -589,14 +670,20 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @return Subscription token used later to unsubscribe
|
* @return Subscription token used later to unsubscribe
|
||||||
*/
|
*/
|
||||||
public subscribe<ArgsType extends ExchangeContractEventArgs>(
|
public subscribe<ArgsType extends ExchangeContractEventArgs>(
|
||||||
eventName: ExchangeEvents, indexFilterValues: IndexedFilterValues,
|
eventName: ExchangeEvents,
|
||||||
callback: EventCallback<ArgsType>): string {
|
indexFilterValues: IndexedFilterValues,
|
||||||
|
callback: EventCallback<ArgsType>,
|
||||||
|
): string {
|
||||||
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
|
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
|
||||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||||
assert.isFunction('callback', callback);
|
assert.isFunction('callback', callback);
|
||||||
const exchangeContractAddress = this.getContractAddress();
|
const exchangeContractAddress = this.getContractAddress();
|
||||||
const subscriptionToken = this._subscribe<ArgsType>(
|
const subscriptionToken = this._subscribe<ArgsType>(
|
||||||
exchangeContractAddress, eventName, indexFilterValues, artifacts.ExchangeArtifact.abi, callback,
|
exchangeContractAddress,
|
||||||
|
eventName,
|
||||||
|
indexFilterValues,
|
||||||
|
artifacts.ExchangeArtifact.abi,
|
||||||
|
callback,
|
||||||
);
|
);
|
||||||
return subscriptionToken;
|
return subscriptionToken;
|
||||||
}
|
}
|
||||||
@@ -611,7 +698,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* Cancels all existing subscriptions
|
* Cancels all existing subscriptions
|
||||||
*/
|
*/
|
||||||
public unsubscribeAll(): void {
|
public unsubscribeAll(): void {
|
||||||
super.unsubscribeAll();
|
super._unsubscribeAll();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Gets historical logs without creating a subscription
|
* Gets historical logs without creating a subscription
|
||||||
@@ -622,14 +709,20 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @return Array of logs that match the parameters
|
* @return Array of logs that match the parameters
|
||||||
*/
|
*/
|
||||||
public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>(
|
public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>(
|
||||||
eventName: ExchangeEvents, blockRange: BlockRange, indexFilterValues: IndexedFilterValues,
|
eventName: ExchangeEvents,
|
||||||
|
blockRange: BlockRange,
|
||||||
|
indexFilterValues: IndexedFilterValues,
|
||||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||||
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
|
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
|
||||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||||
const exchangeContractAddress = this.getContractAddress();
|
const exchangeContractAddress = this.getContractAddress();
|
||||||
const logs = await this._getLogsAsync<ArgsType>(
|
const logs = await this._getLogsAsync<ArgsType>(
|
||||||
exchangeContractAddress, eventName, blockRange, indexFilterValues, artifacts.ExchangeArtifact.abi,
|
exchangeContractAddress,
|
||||||
|
eventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
|
artifacts.ExchangeArtifact.abi,
|
||||||
);
|
);
|
||||||
return logs;
|
return logs;
|
||||||
}
|
}
|
||||||
@@ -652,14 +745,18 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* to validate for.
|
* to validate for.
|
||||||
*/
|
*/
|
||||||
public async validateOrderFillableOrThrowAsync(
|
public async validateOrderFillableOrThrowAsync(
|
||||||
signedOrder: SignedOrder, opts?: ValidateOrderFillableOpts,
|
signedOrder: SignedOrder,
|
||||||
|
opts?: ValidateOrderFillableOpts,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||||
const expectedFillTakerTokenAmount = !_.isUndefined(opts) ? opts.expectedFillTakerTokenAmount : undefined;
|
const expectedFillTakerTokenAmount = !_.isUndefined(opts) ? opts.expectedFillTakerTokenAmount : undefined;
|
||||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||||
await this._orderValidationUtils.validateOrderFillableOrThrowAsync(
|
await this._orderValidationUtils.validateOrderFillableOrThrowAsync(
|
||||||
exchangeTradeEmulator, signedOrder, zrxTokenAddress, expectedFillTakerTokenAmount,
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
|
zrxTokenAddress,
|
||||||
|
expectedFillTakerTokenAmount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -668,18 +765,26 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* signedOrder you wish to fill.
|
* signedOrder you wish to fill.
|
||||||
* @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
|
* @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
|
||||||
* @param takerAddress The user Ethereum address who would like to fill this order.
|
* @param takerAddress The user Ethereum address who would like to fill this order.
|
||||||
* Must be available via the supplied Web3.Provider passed to 0x.js.
|
* Must be available via the supplied Provider passed to 0x.js.
|
||||||
*/
|
*/
|
||||||
public async validateFillOrderThrowIfInvalidAsync(signedOrder: SignedOrder,
|
public async validateFillOrderThrowIfInvalidAsync(
|
||||||
fillTakerTokenAmount: BigNumber,
|
signedOrder: SignedOrder,
|
||||||
takerAddress: string): Promise<void> {
|
fillTakerTokenAmount: BigNumber,
|
||||||
|
takerAddress: string,
|
||||||
|
): Promise<void> {
|
||||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||||
|
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
|
fillTakerTokenAmount,
|
||||||
|
normalizedTakerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Checks if cancelling a given order will succeed and throws an informative error if it won't.
|
* Checks if cancelling a given order will succeed and throws an informative error if it won't.
|
||||||
@@ -688,13 +793,18 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel.
|
* @param cancelTakerTokenAmount The amount (specified in taker tokens) that you would like to cancel.
|
||||||
*/
|
*/
|
||||||
public async validateCancelOrderThrowIfInvalidAsync(
|
public async validateCancelOrderThrowIfInvalidAsync(
|
||||||
order: Order, cancelTakerTokenAmount: BigNumber): Promise<void> {
|
order: Order,
|
||||||
|
cancelTakerTokenAmount: BigNumber,
|
||||||
|
): Promise<void> {
|
||||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||||
assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount);
|
assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount);
|
||||||
const orderHash = utils.getOrderHashHex(order);
|
const orderHash = utils.getOrderHashHex(order);
|
||||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||||
order, cancelTakerTokenAmount, unavailableTakerTokenAmount);
|
order,
|
||||||
|
cancelTakerTokenAmount,
|
||||||
|
unavailableTakerTokenAmount,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Checks if calling fillOrKill on a given order will succeed and throws an informative error if it won't.
|
* Checks if calling fillOrKill on a given order will succeed and throws an informative error if it won't.
|
||||||
@@ -702,18 +812,26 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* signedOrder you wish to fill.
|
* signedOrder you wish to fill.
|
||||||
* @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
|
* @param fillTakerTokenAmount The total amount of the takerTokens you would like to fill.
|
||||||
* @param takerAddress The user Ethereum address who would like to fill this order.
|
* @param takerAddress The user Ethereum address who would like to fill this order.
|
||||||
* Must be available via the supplied Web3.Provider passed to 0x.js.
|
* Must be available via the supplied Provider passed to 0x.js.
|
||||||
*/
|
*/
|
||||||
public async validateFillOrKillOrderThrowIfInvalidAsync(signedOrder: SignedOrder,
|
public async validateFillOrKillOrderThrowIfInvalidAsync(
|
||||||
fillTakerTokenAmount: BigNumber,
|
signedOrder: SignedOrder,
|
||||||
takerAddress: string): Promise<void> {
|
fillTakerTokenAmount: BigNumber,
|
||||||
|
takerAddress: string,
|
||||||
|
): Promise<void> {
|
||||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||||
|
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||||
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress);
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
|
fillTakerTokenAmount,
|
||||||
|
normalizedTakerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Checks if rounding error will be > 0.1% when computing makerTokenAmount by doing:
|
* Checks if rounding error will be > 0.1% when computing makerTokenAmount by doing:
|
||||||
@@ -724,29 +842,33 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @param takerTokenAmount The order size on the taker side
|
* @param takerTokenAmount The order size on the taker side
|
||||||
* @param makerTokenAmount The order size on the maker side
|
* @param makerTokenAmount The order size on the maker side
|
||||||
*/
|
*/
|
||||||
public async isRoundingErrorAsync(fillTakerTokenAmount: BigNumber,
|
public async isRoundingErrorAsync(
|
||||||
takerTokenAmount: BigNumber,
|
fillTakerTokenAmount: BigNumber,
|
||||||
makerTokenAmount: BigNumber): Promise<boolean> {
|
takerTokenAmount: BigNumber,
|
||||||
|
makerTokenAmount: BigNumber,
|
||||||
|
): Promise<boolean> {
|
||||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||||
assert.isValidBaseUnitAmount('takerTokenAmount', takerTokenAmount);
|
assert.isValidBaseUnitAmount('takerTokenAmount', takerTokenAmount);
|
||||||
assert.isValidBaseUnitAmount('makerTokenAmount', makerTokenAmount);
|
assert.isValidBaseUnitAmount('makerTokenAmount', makerTokenAmount);
|
||||||
const exchangeInstance = await this._getExchangeContractAsync();
|
const exchangeInstance = await this._getExchangeContractAsync();
|
||||||
const isRoundingError = await exchangeInstance.isRoundingError.callAsync(
|
const isRoundingError = await exchangeInstance.isRoundingError.callAsync(
|
||||||
fillTakerTokenAmount, takerTokenAmount, makerTokenAmount,
|
fillTakerTokenAmount,
|
||||||
|
takerTokenAmount,
|
||||||
|
makerTokenAmount,
|
||||||
);
|
);
|
||||||
return isRoundingError;
|
return isRoundingError;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Checks if logs contain LogError, which is emmited by Exchange contract on transaction failure.
|
* Checks if logs contain LogError, which is emitted by Exchange contract on transaction failure.
|
||||||
* @param logs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync`
|
* @param logs Transaction logs as returned by `zeroEx.awaitTransactionMinedAsync`
|
||||||
*/
|
*/
|
||||||
public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs>|Web3.LogEntry>): void {
|
public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs> | LogEntry>): void {
|
||||||
const errLog = _.find(logs, {
|
const errLog = _.find(logs, {
|
||||||
event: ExchangeEvents.LogError,
|
event: ExchangeEvents.LogError,
|
||||||
}) as LogWithDecodedArgs<LogErrorContractEventArgs>|undefined;
|
});
|
||||||
if (!_.isUndefined(errLog)) {
|
if (!_.isUndefined(errLog)) {
|
||||||
const logArgs = errLog.args;
|
const logArgs = (errLog as LogWithDecodedArgs<LogErrorContractEventArgs>).args;
|
||||||
const errCode = logArgs.errorId.toNumber();
|
const errCode = logArgs.errorId;
|
||||||
const errMessage = this._exchangeContractErrCodesToMsg[errCode];
|
const errMessage = this._exchangeContractErrCodesToMsg[errCode];
|
||||||
throw new Error(errMessage);
|
throw new Error(errMessage);
|
||||||
}
|
}
|
||||||
@@ -756,25 +878,27 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
* @return Address of ZRX token
|
* @return Address of ZRX token
|
||||||
*/
|
*/
|
||||||
public getZRXTokenAddress(): string {
|
public getZRXTokenAddress(): string {
|
||||||
const contractAddress = this._getContractAddress(
|
const contractAddress = this._getContractAddress(artifacts.ZRXArtifact, this._zrxContractAddressIfExists);
|
||||||
artifacts.ZRXArtifact, this._zrxContractAddressIfExists,
|
|
||||||
);
|
|
||||||
return contractAddress;
|
return contractAddress;
|
||||||
}
|
}
|
||||||
private _invalidateContractInstances(): void {
|
private _invalidateContractInstances(): void {
|
||||||
this.unsubscribeAll();
|
this.unsubscribeAll();
|
||||||
delete this._exchangeContractIfExists;
|
delete this._exchangeContractIfExists;
|
||||||
}
|
}
|
||||||
private async _isValidSignatureUsingContractCallAsync(dataHex: string, ecSignature: ECSignature,
|
private async _isValidSignatureUsingContractCallAsync(
|
||||||
signerAddressHex: string): Promise<boolean> {
|
dataHex: string,
|
||||||
|
ecSignature: ECSignature,
|
||||||
|
signerAddressHex: string,
|
||||||
|
): Promise<boolean> {
|
||||||
assert.isHexString('dataHex', dataHex);
|
assert.isHexString('dataHex', dataHex);
|
||||||
assert.doesConformToSchema('ecSignature', ecSignature, schemas.ecSignatureSchema);
|
assert.doesConformToSchema('ecSignature', ecSignature, schemas.ecSignatureSchema);
|
||||||
assert.isETHAddressHex('signerAddressHex', signerAddressHex);
|
assert.isETHAddressHex('signerAddressHex', signerAddressHex);
|
||||||
|
const normalizedSignerAddress = signerAddressHex.toLowerCase();
|
||||||
|
|
||||||
const exchangeInstance = await this._getExchangeContractAsync();
|
const exchangeInstance = await this._getExchangeContractAsync();
|
||||||
|
|
||||||
const isValidSignature = await exchangeInstance.isValidSignature.callAsync(
|
const isValidSignature = await exchangeInstance.isValidSignature.callAsync(
|
||||||
signerAddressHex,
|
normalizedSignerAddress,
|
||||||
dataHex,
|
dataHex,
|
||||||
ecSignature.v,
|
ecSignature.v,
|
||||||
ecSignature.r,
|
ecSignature.r,
|
||||||
@@ -782,7 +906,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
);
|
);
|
||||||
return isValidSignature;
|
return isValidSignature;
|
||||||
}
|
}
|
||||||
private async _getOrderHashHexUsingContractCallAsync(order: Order|SignedOrder): Promise<string> {
|
private async _getOrderHashHexUsingContractCallAsync(order: Order | SignedOrder): Promise<string> {
|
||||||
const exchangeInstance = await this._getExchangeContractAsync();
|
const exchangeInstance = await this._getExchangeContractAsync();
|
||||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
|
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
|
||||||
const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues);
|
const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues);
|
||||||
@@ -792,10 +916,16 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
if (!_.isUndefined(this._exchangeContractIfExists)) {
|
if (!_.isUndefined(this._exchangeContractIfExists)) {
|
||||||
return this._exchangeContractIfExists;
|
return this._exchangeContractIfExists;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.ExchangeArtifact, this._contractAddressIfExists,
|
artifacts.ExchangeArtifact,
|
||||||
|
this._contractAddressIfExists,
|
||||||
|
);
|
||||||
|
const contractInstance = new ExchangeContract(
|
||||||
|
abi,
|
||||||
|
address,
|
||||||
|
this._web3Wrapper.getProvider(),
|
||||||
|
this._web3Wrapper.getContractDefaults(),
|
||||||
);
|
);
|
||||||
const contractInstance = new ExchangeContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
|
||||||
this._exchangeContractIfExists = contractInstance;
|
this._exchangeContractIfExists = contractInstance;
|
||||||
return this._exchangeContractIfExists;
|
return this._exchangeContractIfExists;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {artifacts} from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
import {Token, TokenMetadata} from '../types';
|
import { Token, TokenMetadata } from '../types';
|
||||||
import {assert} from '../utils/assert';
|
import { assert } from '../utils/assert';
|
||||||
import {constants} from '../utils/constants';
|
import { constants } from '../utils/constants';
|
||||||
|
|
||||||
import {ContractWrapper} from './contract_wrapper';
|
import { ContractWrapper } from './contract_wrapper';
|
||||||
import {TokenRegistryContract} from './generated/token_registry';
|
import { TokenRegistryContract } from './generated/token_registry';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class includes all the functionality related to interacting with the 0x Token Registry smart contract.
|
* This class includes all the functionality related to interacting with the 0x Token Registry smart contract.
|
||||||
@@ -15,7 +15,7 @@ import {TokenRegistryContract} from './generated/token_registry';
|
|||||||
export class TokenRegistryWrapper extends ContractWrapper {
|
export class TokenRegistryWrapper extends ContractWrapper {
|
||||||
private _tokenRegistryContractIfExists?: TokenRegistryContract;
|
private _tokenRegistryContractIfExists?: TokenRegistryContract;
|
||||||
private _contractAddressIfExists?: string;
|
private _contractAddressIfExists?: string;
|
||||||
private static _createTokenFromMetadata(metadata: TokenMetadata): Token|undefined {
|
private static _createTokenFromMetadata(metadata: TokenMetadata): Token | undefined {
|
||||||
if (metadata[0] === constants.NULL_ADDRESS) {
|
if (metadata[0] === constants.NULL_ADDRESS) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
|||||||
address: metadata[0],
|
address: metadata[0],
|
||||||
name: metadata[1],
|
name: metadata[1],
|
||||||
symbol: metadata[2],
|
symbol: metadata[2],
|
||||||
decimals: metadata[3].toNumber(),
|
decimals: metadata[3],
|
||||||
};
|
};
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
@@ -37,9 +37,8 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
|||||||
*/
|
*/
|
||||||
public async getTokensAsync(): Promise<Token[]> {
|
public async getTokensAsync(): Promise<Token[]> {
|
||||||
const addresses = await this.getTokenAddressesAsync();
|
const addresses = await this.getTokenAddressesAsync();
|
||||||
const tokenPromises: Array<Promise<Token|undefined>> = _.map(
|
const tokenPromises: Array<Promise<Token | undefined>> = _.map(addresses, async (address: string) =>
|
||||||
addresses,
|
this.getTokenIfExistsAsync(address),
|
||||||
async (address: string) => this.getTokenIfExistsAsync(address),
|
|
||||||
);
|
);
|
||||||
const tokens = await Promise.all(tokenPromises);
|
const tokens = await Promise.all(tokenPromises);
|
||||||
return tokens as Token[];
|
return tokens as Token[];
|
||||||
@@ -51,21 +50,23 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
|||||||
public async getTokenAddressesAsync(): Promise<string[]> {
|
public async getTokenAddressesAsync(): Promise<string[]> {
|
||||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||||
const addresses = await tokenRegistryContract.getTokenAddresses.callAsync();
|
const addresses = await tokenRegistryContract.getTokenAddresses.callAsync();
|
||||||
return addresses;
|
const lowerCaseAddresses = _.map(addresses, address => address.toLowerCase());
|
||||||
|
return lowerCaseAddresses;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Retrieves a token by address currently listed in the Token Registry smart contract
|
* Retrieves a token by address currently listed in the Token Registry smart contract
|
||||||
* @return An object that conforms to the Token interface or undefined if token not found.
|
* @return An object that conforms to the Token interface or undefined if token not found.
|
||||||
*/
|
*/
|
||||||
public async getTokenIfExistsAsync(address: string): Promise<Token|undefined> {
|
public async getTokenIfExistsAsync(address: string): Promise<Token | undefined> {
|
||||||
assert.isETHAddressHex('address', address);
|
assert.isETHAddressHex('address', address);
|
||||||
|
const normalizedAddress = address.toLowerCase();
|
||||||
|
|
||||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||||
const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(address);
|
const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(normalizedAddress);
|
||||||
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
|
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string|undefined> {
|
public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string | undefined> {
|
||||||
assert.isString('symbol', symbol);
|
assert.isString('symbol', symbol);
|
||||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||||
const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.callAsync(symbol);
|
const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.callAsync(symbol);
|
||||||
@@ -74,7 +75,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
|||||||
}
|
}
|
||||||
return addressIfExists;
|
return addressIfExists;
|
||||||
}
|
}
|
||||||
public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string|undefined> {
|
public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string | undefined> {
|
||||||
assert.isString('name', name);
|
assert.isString('name', name);
|
||||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||||
const addressIfExists = await tokenRegistryContract.getTokenAddressByName.callAsync(name);
|
const addressIfExists = await tokenRegistryContract.getTokenAddressByName.callAsync(name);
|
||||||
@@ -83,14 +84,14 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
|||||||
}
|
}
|
||||||
return addressIfExists;
|
return addressIfExists;
|
||||||
}
|
}
|
||||||
public async getTokenBySymbolIfExistsAsync(symbol: string): Promise<Token|undefined> {
|
public async getTokenBySymbolIfExistsAsync(symbol: string): Promise<Token | undefined> {
|
||||||
assert.isString('symbol', symbol);
|
assert.isString('symbol', symbol);
|
||||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||||
const metadata = await tokenRegistryContract.getTokenBySymbol.callAsync(symbol);
|
const metadata = await tokenRegistryContract.getTokenBySymbol.callAsync(symbol);
|
||||||
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
|
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
public async getTokenByNameIfExistsAsync(name: string): Promise<Token|undefined> {
|
public async getTokenByNameIfExistsAsync(name: string): Promise<Token | undefined> {
|
||||||
assert.isString('name', name);
|
assert.isString('name', name);
|
||||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||||
const metadata = await tokenRegistryContract.getTokenByName.callAsync(name);
|
const metadata = await tokenRegistryContract.getTokenByName.callAsync(name);
|
||||||
@@ -104,7 +105,8 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
|||||||
*/
|
*/
|
||||||
public getContractAddress(): string {
|
public getContractAddress(): string {
|
||||||
const contractAddress = this._getContractAddress(
|
const contractAddress = this._getContractAddress(
|
||||||
artifacts.TokenRegistryArtifact, this._contractAddressIfExists,
|
artifacts.TokenRegistryArtifact,
|
||||||
|
this._contractAddressIfExists,
|
||||||
);
|
);
|
||||||
return contractAddress;
|
return contractAddress;
|
||||||
}
|
}
|
||||||
@@ -115,11 +117,15 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
|||||||
if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
|
if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
|
||||||
return this._tokenRegistryContractIfExists;
|
return this._tokenRegistryContractIfExists;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.TokenRegistryArtifact, this._contractAddressIfExists,
|
artifacts.TokenRegistryArtifact,
|
||||||
|
this._contractAddressIfExists,
|
||||||
);
|
);
|
||||||
const contractInstance = new TokenRegistryContract(
|
const contractInstance = new TokenRegistryContract(
|
||||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
abi,
|
||||||
|
address,
|
||||||
|
this._web3Wrapper.getProvider(),
|
||||||
|
this._web3Wrapper.getContractDefaults(),
|
||||||
);
|
);
|
||||||
this._tokenRegistryContractIfExists = contractInstance;
|
this._tokenRegistryContractIfExists = contractInstance;
|
||||||
return this._tokenRegistryContractIfExists;
|
return this._tokenRegistryContractIfExists;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {artifacts} from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
|
import { assert } from '../utils/assert';
|
||||||
|
|
||||||
import {ContractWrapper} from './contract_wrapper';
|
import { ContractWrapper } from './contract_wrapper';
|
||||||
import {TokenTransferProxyContract} from './generated/token_transfer_proxy';
|
import { TokenTransferProxyContract } from './generated/token_transfer_proxy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class includes the functionality related to interacting with the TokenTransferProxy contract.
|
* This class includes the functionality related to interacting with the TokenTransferProxy contract.
|
||||||
@@ -22,8 +23,12 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
|||||||
* @return Whether the exchangeContractAddress is authorized.
|
* @return Whether the exchangeContractAddress is authorized.
|
||||||
*/
|
*/
|
||||||
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
|
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
|
||||||
|
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
|
||||||
|
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
|
||||||
const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
|
const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
|
||||||
const isAuthorized = await tokenTransferProxyContractInstance.authorized.callAsync(exchangeContractAddress);
|
const isAuthorized = await tokenTransferProxyContractInstance.authorized.callAsync(
|
||||||
|
normalizedExchangeContractAddress,
|
||||||
|
);
|
||||||
return isAuthorized;
|
return isAuthorized;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +47,8 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
|||||||
*/
|
*/
|
||||||
public getContractAddress(): string {
|
public getContractAddress(): string {
|
||||||
const contractAddress = this._getContractAddress(
|
const contractAddress = this._getContractAddress(
|
||||||
artifacts.TokenTransferProxyArtifact, this._contractAddressIfExists,
|
artifacts.TokenTransferProxyArtifact,
|
||||||
|
this._contractAddressIfExists,
|
||||||
);
|
);
|
||||||
return contractAddress;
|
return contractAddress;
|
||||||
}
|
}
|
||||||
@@ -53,11 +59,15 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
|||||||
if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
|
if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
|
||||||
return this._tokenTransferProxyContractIfExists;
|
return this._tokenTransferProxyContractIfExists;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.TokenTransferProxyArtifact, this._contractAddressIfExists,
|
artifacts.TokenTransferProxyArtifact,
|
||||||
|
this._contractAddressIfExists,
|
||||||
);
|
);
|
||||||
const contractInstance = new TokenTransferProxyContract(
|
const contractInstance = new TokenTransferProxyContract(
|
||||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
abi,
|
||||||
|
address,
|
||||||
|
this._web3Wrapper.getProvider(),
|
||||||
|
this._web3Wrapper.getContractDefaults(),
|
||||||
);
|
);
|
||||||
this._tokenTransferProxyContractIfExists = contractInstance;
|
this._tokenTransferProxyContractIfExists = contractInstance;
|
||||||
return this._tokenTransferProxyContractIfExists;
|
return this._tokenTransferProxyContractIfExists;
|
||||||
|
|||||||
@@ -1,27 +1,17 @@
|
|||||||
import {schemas} from '@0xproject/json-schemas';
|
import { schemas } from '@0xproject/json-schemas';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { LogWithDecodedArgs } from '@0xproject/types';
|
||||||
import BigNumber from 'bignumber.js';
|
import { AbiDecoder, BigNumber } from '@0xproject/utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {artifacts} from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
import {
|
import { BlockRange, EventCallback, IndexedFilterValues, MethodOpts, TransactionOpts, ZeroExError } from '../types';
|
||||||
BlockRange,
|
import { assert } from '../utils/assert';
|
||||||
EventCallback,
|
import { constants } from '../utils/constants';
|
||||||
IndexedFilterValues,
|
|
||||||
LogWithDecodedArgs,
|
|
||||||
MethodOpts,
|
|
||||||
TokenContractEventArgs,
|
|
||||||
TokenEvents,
|
|
||||||
TransactionOpts,
|
|
||||||
ZeroExError,
|
|
||||||
} from '../types';
|
|
||||||
import {AbiDecoder} from '../utils/abi_decoder';
|
|
||||||
import {assert} from '../utils/assert';
|
|
||||||
import {constants} from '../utils/constants';
|
|
||||||
|
|
||||||
import {ContractWrapper} from './contract_wrapper';
|
import { ContractWrapper } from './contract_wrapper';
|
||||||
import {TokenContract} from './generated/token';
|
import { TokenContract, TokenContractEventArgs, TokenEvents } from './generated/token';
|
||||||
import {TokenTransferProxyWrapper} from './token_transfer_proxy_wrapper';
|
import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class includes all the functionality related to interacting with ERC20 token contracts.
|
* This class includes all the functionality related to interacting with ERC20 token contracts.
|
||||||
@@ -30,11 +20,10 @@ import {TokenTransferProxyWrapper} from './token_transfer_proxy_wrapper';
|
|||||||
*/
|
*/
|
||||||
export class TokenWrapper extends ContractWrapper {
|
export class TokenWrapper extends ContractWrapper {
|
||||||
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
||||||
private _tokenContractsByAddress: {[address: string]: TokenContract};
|
private _tokenContractsByAddress: { [address: string]: TokenContract };
|
||||||
private _tokenTransferProxyWrapper: TokenTransferProxyWrapper;
|
private _tokenTransferProxyWrapper: TokenTransferProxyWrapper;
|
||||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder,
|
constructor(web3Wrapper: Web3Wrapper, networkId: number, tokenTransferProxyWrapper: TokenTransferProxyWrapper) {
|
||||||
tokenTransferProxyWrapper: TokenTransferProxyWrapper) {
|
super(web3Wrapper, networkId);
|
||||||
super(web3Wrapper, networkId, abiDecoder);
|
|
||||||
this._tokenContractsByAddress = {};
|
this._tokenContractsByAddress = {};
|
||||||
this._tokenTransferProxyWrapper = tokenTransferProxyWrapper;
|
this._tokenTransferProxyWrapper = tokenTransferProxyWrapper;
|
||||||
}
|
}
|
||||||
@@ -45,14 +34,20 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @param methodOpts Optional arguments this method accepts.
|
* @param methodOpts Optional arguments this method accepts.
|
||||||
* @return The owner's ERC20 token balance in base units.
|
* @return The owner's ERC20 token balance in base units.
|
||||||
*/
|
*/
|
||||||
public async getBalanceAsync(tokenAddress: string, ownerAddress: string,
|
public async getBalanceAsync(
|
||||||
methodOpts?: MethodOpts): Promise<BigNumber> {
|
tokenAddress: string,
|
||||||
|
ownerAddress: string,
|
||||||
|
methodOpts?: MethodOpts,
|
||||||
|
): Promise<BigNumber> {
|
||||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||||
|
|
||||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||||
let balance = await tokenContract.balanceOf.callAsync(ownerAddress, defaultBlock);
|
const txData = {};
|
||||||
|
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, defaultBlock);
|
||||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
balance = new BigNumber(balance);
|
balance = new BigNumber(balance);
|
||||||
return balance;
|
return balance;
|
||||||
@@ -68,16 +63,24 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @param txOpts Transaction parameters.
|
* @param txOpts Transaction parameters.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
public async setAllowanceAsync(tokenAddress: string, ownerAddress: string, spenderAddress: string,
|
public async setAllowanceAsync(
|
||||||
amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}): Promise<string> {
|
tokenAddress: string,
|
||||||
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
|
ownerAddress: string,
|
||||||
|
spenderAddress: string,
|
||||||
|
amountInBaseUnits: BigNumber,
|
||||||
|
txOpts: TransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedSpenderAddress = spenderAddress.toLowerCase();
|
||||||
|
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||||
|
|
||||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||||
const txHash = await tokenContract.approve.sendTransactionAsync(spenderAddress, amountInBaseUnits, {
|
const txHash = await tokenContract.approve.sendTransactionAsync(normalizedSpenderAddress, amountInBaseUnits, {
|
||||||
from: ownerAddress,
|
from: normalizedOwnerAddress,
|
||||||
gas: txOpts.gasLimit,
|
gas: txOpts.gasLimit,
|
||||||
gasPrice: txOpts.gasPrice,
|
gasPrice: txOpts.gasPrice,
|
||||||
});
|
});
|
||||||
@@ -95,10 +98,24 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @param txOpts Transaction parameters.
|
* @param txOpts Transaction parameters.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
public async setUnlimitedAllowanceAsync(tokenAddress: string, ownerAddress: string,
|
public async setUnlimitedAllowanceAsync(
|
||||||
spenderAddress: string, txOpts: TransactionOpts = {}): Promise<string> {
|
tokenAddress: string,
|
||||||
|
ownerAddress: string,
|
||||||
|
spenderAddress: string,
|
||||||
|
txOpts: TransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
|
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||||
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||||
|
const normalizedSpenderAddress = spenderAddress.toLowerCase();
|
||||||
const txHash = await this.setAllowanceAsync(
|
const txHash = await this.setAllowanceAsync(
|
||||||
tokenAddress, ownerAddress, spenderAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, txOpts,
|
normalizedTokenAddress,
|
||||||
|
normalizedOwnerAddress,
|
||||||
|
normalizedSpenderAddress,
|
||||||
|
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||||
|
txOpts,
|
||||||
);
|
);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@@ -110,14 +127,28 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching.
|
* @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching.
|
||||||
* @param methodOpts Optional arguments this method accepts.
|
* @param methodOpts Optional arguments this method accepts.
|
||||||
*/
|
*/
|
||||||
public async getAllowanceAsync(tokenAddress: string, ownerAddress: string,
|
public async getAllowanceAsync(
|
||||||
spenderAddress: string, methodOpts?: MethodOpts): Promise<BigNumber> {
|
tokenAddress: string,
|
||||||
|
ownerAddress: string,
|
||||||
|
spenderAddress: string,
|
||||||
|
methodOpts?: MethodOpts,
|
||||||
|
): Promise<BigNumber> {
|
||||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||||
|
const normalizedSpenderAddress = spenderAddress.toLowerCase();
|
||||||
|
|
||||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||||
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(ownerAddress, spenderAddress, defaultBlock);
|
const txData = {};
|
||||||
|
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
|
||||||
|
normalizedOwnerAddress,
|
||||||
|
normalizedSpenderAddress,
|
||||||
|
txData,
|
||||||
|
defaultBlock,
|
||||||
|
);
|
||||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||||
allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
|
allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
|
||||||
return allowanceInBaseUnits;
|
return allowanceInBaseUnits;
|
||||||
@@ -128,13 +159,23 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @param ownerAddress The hex encoded user Ethereum address whose proxy contract allowance we are retrieving.
|
* @param ownerAddress The hex encoded user Ethereum address whose proxy contract allowance we are retrieving.
|
||||||
* @param methodOpts Optional arguments this method accepts.
|
* @param methodOpts Optional arguments this method accepts.
|
||||||
*/
|
*/
|
||||||
public async getProxyAllowanceAsync(tokenAddress: string, ownerAddress: string,
|
public async getProxyAllowanceAsync(
|
||||||
methodOpts?: MethodOpts): Promise<BigNumber> {
|
tokenAddress: string,
|
||||||
|
ownerAddress: string,
|
||||||
|
methodOpts?: MethodOpts,
|
||||||
|
): Promise<BigNumber> {
|
||||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||||
|
|
||||||
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
|
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
|
||||||
const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts);
|
const allowanceInBaseUnits = await this.getAllowanceAsync(
|
||||||
|
normalizedTokenAddress,
|
||||||
|
normalizedOwnerAddress,
|
||||||
|
proxyAddress,
|
||||||
|
methodOpts,
|
||||||
|
);
|
||||||
return allowanceInBaseUnits;
|
return allowanceInBaseUnits;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -147,15 +188,25 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @param txOpts Transaction parameters.
|
* @param txOpts Transaction parameters.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
public async setProxyAllowanceAsync(tokenAddress: string, ownerAddress: string,
|
public async setProxyAllowanceAsync(
|
||||||
amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}): Promise<string> {
|
tokenAddress: string,
|
||||||
|
ownerAddress: string,
|
||||||
|
amountInBaseUnits: BigNumber,
|
||||||
|
txOpts: TransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||||
|
|
||||||
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
|
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
|
||||||
const txHash = await this.setAllowanceAsync(
|
const txHash = await this.setAllowanceAsync(
|
||||||
tokenAddress, ownerAddress, proxyAddress, amountInBaseUnits, txOpts,
|
normalizedTokenAddress,
|
||||||
|
normalizedOwnerAddress,
|
||||||
|
proxyAddress,
|
||||||
|
amountInBaseUnits,
|
||||||
|
txOpts,
|
||||||
);
|
);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@@ -171,10 +222,19 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
public async setUnlimitedProxyAllowanceAsync(
|
public async setUnlimitedProxyAllowanceAsync(
|
||||||
tokenAddress: string, ownerAddress: string, txOpts: TransactionOpts = {},
|
tokenAddress: string,
|
||||||
|
ownerAddress: string,
|
||||||
|
txOpts: TransactionOpts = {},
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
|
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||||
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||||
const txHash = await this.setProxyAllowanceAsync(
|
const txHash = await this.setProxyAllowanceAsync(
|
||||||
tokenAddress, ownerAddress, this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, txOpts,
|
normalizedTokenAddress,
|
||||||
|
normalizedOwnerAddress,
|
||||||
|
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||||
|
txOpts,
|
||||||
);
|
);
|
||||||
return txHash;
|
return txHash;
|
||||||
}
|
}
|
||||||
@@ -187,22 +247,30 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @param txOpts Transaction parameters.
|
* @param txOpts Transaction parameters.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
public async transferAsync(tokenAddress: string, fromAddress: string, toAddress: string,
|
public async transferAsync(
|
||||||
amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}): Promise<string> {
|
tokenAddress: string,
|
||||||
|
fromAddress: string,
|
||||||
|
toAddress: string,
|
||||||
|
amountInBaseUnits: BigNumber,
|
||||||
|
txOpts: TransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
|
|
||||||
assert.isETHAddressHex('toAddress', toAddress);
|
assert.isETHAddressHex('toAddress', toAddress);
|
||||||
|
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedFromAddress = fromAddress.toLowerCase();
|
||||||
|
const normalizedToAddress = toAddress.toLowerCase();
|
||||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||||
|
|
||||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||||
|
|
||||||
const fromAddressBalance = await this.getBalanceAsync(tokenAddress, fromAddress);
|
const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress);
|
||||||
if (fromAddressBalance.lessThan(amountInBaseUnits)) {
|
if (fromAddressBalance.lessThan(amountInBaseUnits)) {
|
||||||
throw new Error(ZeroExError.InsufficientBalanceForTransfer);
|
throw new Error(ZeroExError.InsufficientBalanceForTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const txHash = await tokenContract.transfer.sendTransactionAsync(toAddress, amountInBaseUnits, {
|
const txHash = await tokenContract.transfer.sendTransactionAsync(normalizedToAddress, amountInBaseUnits, {
|
||||||
from: fromAddress,
|
from: normalizedFromAddress,
|
||||||
gas: txOpts.gasLimit,
|
gas: txOpts.gasLimit,
|
||||||
gasPrice: txOpts.gasPrice,
|
gasPrice: txOpts.gasPrice,
|
||||||
});
|
});
|
||||||
@@ -222,31 +290,46 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @param txOpts Transaction parameters.
|
* @param txOpts Transaction parameters.
|
||||||
* @return Transaction hash.
|
* @return Transaction hash.
|
||||||
*/
|
*/
|
||||||
public async transferFromAsync(tokenAddress: string, fromAddress: string, toAddress: string,
|
public async transferFromAsync(
|
||||||
senderAddress: string, amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}):
|
tokenAddress: string,
|
||||||
Promise<string> {
|
fromAddress: string,
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
toAddress: string,
|
||||||
assert.isETHAddressHex('fromAddress', fromAddress);
|
senderAddress: string,
|
||||||
|
amountInBaseUnits: BigNumber,
|
||||||
|
txOpts: TransactionOpts = {},
|
||||||
|
): Promise<string> {
|
||||||
assert.isETHAddressHex('toAddress', toAddress);
|
assert.isETHAddressHex('toAddress', toAddress);
|
||||||
|
assert.isETHAddressHex('fromAddress', fromAddress);
|
||||||
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
|
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
|
||||||
|
const normalizedToAddress = toAddress.toLowerCase();
|
||||||
|
const normalizedFromAddress = fromAddress.toLowerCase();
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
const normalizedSenderAddress = senderAddress.toLowerCase();
|
||||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||||
|
|
||||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||||
|
|
||||||
const fromAddressAllowance = await this.getAllowanceAsync(tokenAddress, fromAddress, senderAddress);
|
const fromAddressAllowance = await this.getAllowanceAsync(
|
||||||
|
normalizedTokenAddress,
|
||||||
|
normalizedFromAddress,
|
||||||
|
normalizedSenderAddress,
|
||||||
|
);
|
||||||
if (fromAddressAllowance.lessThan(amountInBaseUnits)) {
|
if (fromAddressAllowance.lessThan(amountInBaseUnits)) {
|
||||||
throw new Error(ZeroExError.InsufficientAllowanceForTransfer);
|
throw new Error(ZeroExError.InsufficientAllowanceForTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fromAddressBalance = await this.getBalanceAsync(tokenAddress, fromAddress);
|
const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress);
|
||||||
if (fromAddressBalance.lessThan(amountInBaseUnits)) {
|
if (fromAddressBalance.lessThan(amountInBaseUnits)) {
|
||||||
throw new Error(ZeroExError.InsufficientBalanceForTransfer);
|
throw new Error(ZeroExError.InsufficientBalanceForTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
|
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
|
||||||
fromAddress, toAddress, amountInBaseUnits,
|
normalizedFromAddress,
|
||||||
|
normalizedToAddress,
|
||||||
|
amountInBaseUnits,
|
||||||
{
|
{
|
||||||
from: senderAddress,
|
from: normalizedSenderAddress,
|
||||||
gas: txOpts.gasLimit,
|
gas: txOpts.gasLimit,
|
||||||
gasPrice: txOpts.gasPrice,
|
gasPrice: txOpts.gasPrice,
|
||||||
},
|
},
|
||||||
@@ -263,14 +346,22 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @return Subscription token used later to unsubscribe
|
* @return Subscription token used later to unsubscribe
|
||||||
*/
|
*/
|
||||||
public subscribe<ArgsType extends TokenContractEventArgs>(
|
public subscribe<ArgsType extends TokenContractEventArgs>(
|
||||||
tokenAddress: string, eventName: TokenEvents, indexFilterValues: IndexedFilterValues,
|
tokenAddress: string,
|
||||||
callback: EventCallback<ArgsType>): string {
|
eventName: TokenEvents,
|
||||||
|
indexFilterValues: IndexedFilterValues,
|
||||||
|
callback: EventCallback<ArgsType>,
|
||||||
|
): string {
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
|
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
|
||||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||||
assert.isFunction('callback', callback);
|
assert.isFunction('callback', callback);
|
||||||
const subscriptionToken = this._subscribe<ArgsType>(
|
const subscriptionToken = this._subscribe<ArgsType>(
|
||||||
tokenAddress, eventName, indexFilterValues, artifacts.TokenArtifact.abi, callback,
|
normalizedTokenAddress,
|
||||||
|
eventName,
|
||||||
|
indexFilterValues,
|
||||||
|
artifacts.TokenArtifact.abi,
|
||||||
|
callback,
|
||||||
);
|
);
|
||||||
return subscriptionToken;
|
return subscriptionToken;
|
||||||
}
|
}
|
||||||
@@ -285,11 +376,11 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* Cancels all existing subscriptions
|
* Cancels all existing subscriptions
|
||||||
*/
|
*/
|
||||||
public unsubscribeAll(): void {
|
public unsubscribeAll(): void {
|
||||||
super.unsubscribeAll();
|
super._unsubscribeAll();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Gets historical logs without creating a subscription
|
* Gets historical logs without creating a subscription
|
||||||
* @param tokenAddress An address of the token that emmited the logs.
|
* @param tokenAddress An address of the token that emitted the logs.
|
||||||
* @param eventName The token contract event you would like to subscribe to.
|
* @param eventName The token contract event you would like to subscribe to.
|
||||||
* @param blockRange Block range to get logs from.
|
* @param blockRange Block range to get logs from.
|
||||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||||
@@ -297,14 +388,22 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
* @return Array of logs that match the parameters
|
* @return Array of logs that match the parameters
|
||||||
*/
|
*/
|
||||||
public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
|
public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
|
||||||
tokenAddress: string, eventName: TokenEvents, blockRange: BlockRange,
|
tokenAddress: string,
|
||||||
indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
eventName: TokenEvents,
|
||||||
|
blockRange: BlockRange,
|
||||||
|
indexFilterValues: IndexedFilterValues,
|
||||||
|
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||||
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
|
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
|
||||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||||
const logs = await this._getLogsAsync<ArgsType>(
|
const logs = await this._getLogsAsync<ArgsType>(
|
||||||
tokenAddress, eventName, blockRange, indexFilterValues, artifacts.TokenArtifact.abi,
|
normalizedTokenAddress,
|
||||||
|
eventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
|
artifacts.TokenArtifact.abi,
|
||||||
);
|
);
|
||||||
return logs;
|
return logs;
|
||||||
}
|
}
|
||||||
@@ -313,18 +412,23 @@ export class TokenWrapper extends ContractWrapper {
|
|||||||
this._tokenContractsByAddress = {};
|
this._tokenContractsByAddress = {};
|
||||||
}
|
}
|
||||||
private async _getTokenContractAsync(tokenAddress: string): Promise<TokenContract> {
|
private async _getTokenContractAsync(tokenAddress: string): Promise<TokenContract> {
|
||||||
let tokenContract = this._tokenContractsByAddress[tokenAddress];
|
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||||
|
let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress];
|
||||||
if (!_.isUndefined(tokenContract)) {
|
if (!_.isUndefined(tokenContract)) {
|
||||||
return tokenContract;
|
return tokenContract;
|
||||||
}
|
}
|
||||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||||
artifacts.TokenArtifact, tokenAddress,
|
artifacts.TokenArtifact,
|
||||||
|
normalizedTokenAddress,
|
||||||
);
|
);
|
||||||
const contractInstance = new TokenContract(
|
const contractInstance = new TokenContract(
|
||||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
abi,
|
||||||
|
address,
|
||||||
|
this._web3Wrapper.getProvider(),
|
||||||
|
this._web3Wrapper.getContractDefaults(),
|
||||||
);
|
);
|
||||||
tokenContract = contractInstance;
|
tokenContract = contractInstance;
|
||||||
this._tokenContractsByAddress[tokenAddress] = tokenContract;
|
this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
|
||||||
return tokenContract;
|
return tokenContract;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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' {
|
declare module '*.json' {
|
||||||
const json: any;
|
const json: any;
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
export default json;
|
export default json;
|
||||||
/* tslint:enable */
|
/* 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,43 +1,20 @@
|
|||||||
export {ZeroEx} from './0x';
|
export { ZeroEx } from './0x';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Order,
|
|
||||||
BlockParamLiteral,
|
|
||||||
SignedOrder,
|
|
||||||
ECSignature,
|
|
||||||
ZeroExError,
|
ZeroExError,
|
||||||
EventCallback,
|
EventCallback,
|
||||||
ExchangeContractErrs,
|
ExchangeContractErrs,
|
||||||
ContractEvent,
|
ContractEvent,
|
||||||
Token,
|
Token,
|
||||||
ExchangeEvents,
|
|
||||||
TokenEvents,
|
|
||||||
IndexedFilterValues,
|
IndexedFilterValues,
|
||||||
BlockRange,
|
BlockRange,
|
||||||
BlockParam,
|
|
||||||
OrderCancellationRequest,
|
OrderCancellationRequest,
|
||||||
OrderFillRequest,
|
OrderFillRequest,
|
||||||
LogErrorContractEventArgs,
|
|
||||||
LogCancelContractEventArgs,
|
|
||||||
LogFillContractEventArgs,
|
|
||||||
ExchangeContractEventArgs,
|
|
||||||
TransferContractEventArgs,
|
|
||||||
ApprovalContractEventArgs,
|
|
||||||
TokenContractEventArgs,
|
|
||||||
EtherTokenContractEventArgs,
|
|
||||||
WithdrawalContractEventArgs,
|
|
||||||
DepositContractEventArgs,
|
|
||||||
ContractEventArgs,
|
ContractEventArgs,
|
||||||
ContractEventArg,
|
|
||||||
Web3Provider,
|
|
||||||
ZeroExConfig,
|
ZeroExConfig,
|
||||||
EtherTokenEvents,
|
|
||||||
TransactionReceiptWithDecodedLogs,
|
|
||||||
LogWithDecodedArgs,
|
|
||||||
MethodOpts,
|
MethodOpts,
|
||||||
OrderTransactionOpts,
|
OrderTransactionOpts,
|
||||||
TransactionOpts,
|
TransactionOpts,
|
||||||
FilterObject,
|
|
||||||
LogEvent,
|
LogEvent,
|
||||||
DecodedLogEvent,
|
DecodedLogEvent,
|
||||||
EventWatcherCallback,
|
EventWatcherCallback,
|
||||||
@@ -48,5 +25,37 @@ export {
|
|||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
BlockParamLiteral,
|
||||||
|
FilterObject,
|
||||||
|
BlockParam,
|
||||||
|
ContractEventArg,
|
||||||
|
LogWithDecodedArgs,
|
||||||
|
Order,
|
||||||
|
Provider,
|
||||||
|
SignedOrder,
|
||||||
|
ECSignature,
|
||||||
TransactionReceipt,
|
TransactionReceipt,
|
||||||
|
TransactionReceiptWithDecodedLogs,
|
||||||
} from '@0xproject/types';
|
} from '@0xproject/types';
|
||||||
|
|
||||||
|
export {
|
||||||
|
EtherTokenContractEventArgs,
|
||||||
|
WithdrawalContractEventArgs,
|
||||||
|
DepositContractEventArgs,
|
||||||
|
EtherTokenEvents,
|
||||||
|
} from './contract_wrappers/generated/ether_token';
|
||||||
|
|
||||||
|
export {
|
||||||
|
TransferContractEventArgs,
|
||||||
|
ApprovalContractEventArgs,
|
||||||
|
TokenContractEventArgs,
|
||||||
|
TokenEvents,
|
||||||
|
} from './contract_wrappers/generated/token';
|
||||||
|
|
||||||
|
export {
|
||||||
|
LogErrorContractEventArgs,
|
||||||
|
LogCancelContractEventArgs,
|
||||||
|
LogFillContractEventArgs,
|
||||||
|
ExchangeContractEventArgs,
|
||||||
|
ExchangeEvents,
|
||||||
|
} from './contract_wrappers/generated/exchange';
|
||||||
|
|||||||
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,14 +1,10 @@
|
|||||||
import {intervalUtils} from '@0xproject/utils';
|
import { BlockParamLiteral, LogEntry } from '@0xproject/types';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { intervalUtils } from '@0xproject/utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as Web3 from 'web3';
|
|
||||||
|
|
||||||
import {
|
import { EventWatcherCallback, ZeroExError } from '../types';
|
||||||
BlockParamLiteral,
|
import { assert } from '../utils/assert';
|
||||||
EventWatcherCallback,
|
|
||||||
ZeroExError,
|
|
||||||
} from '../types';
|
|
||||||
import {assert} from '../utils/assert';
|
|
||||||
|
|
||||||
const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200;
|
const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200;
|
||||||
|
|
||||||
@@ -25,12 +21,18 @@ export class EventWatcher {
|
|||||||
private _web3Wrapper: Web3Wrapper;
|
private _web3Wrapper: Web3Wrapper;
|
||||||
private _pollingIntervalMs: number;
|
private _pollingIntervalMs: number;
|
||||||
private _intervalIdIfExists?: NodeJS.Timer;
|
private _intervalIdIfExists?: NodeJS.Timer;
|
||||||
private _lastEvents: Web3.LogEntry[] = [];
|
private _lastEvents: LogEntry[] = [];
|
||||||
constructor(web3Wrapper: Web3Wrapper, pollingIntervalIfExistsMs: undefined|number) {
|
private _stateLayer: BlockParamLiteral;
|
||||||
|
constructor(
|
||||||
|
web3Wrapper: Web3Wrapper,
|
||||||
|
pollingIntervalIfExistsMs: undefined | number,
|
||||||
|
stateLayer: BlockParamLiteral = BlockParamLiteral.Latest,
|
||||||
|
) {
|
||||||
this._web3Wrapper = web3Wrapper;
|
this._web3Wrapper = web3Wrapper;
|
||||||
this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs) ?
|
this._stateLayer = stateLayer;
|
||||||
DEFAULT_EVENT_POLLING_INTERVAL_MS :
|
this._pollingIntervalMs = _.isUndefined(pollingIntervalIfExistsMs)
|
||||||
pollingIntervalIfExistsMs;
|
? DEFAULT_EVENT_POLLING_INTERVAL_MS
|
||||||
|
: pollingIntervalIfExistsMs;
|
||||||
}
|
}
|
||||||
public subscribe(callback: EventWatcherCallback): void {
|
public subscribe(callback: EventWatcherCallback): void {
|
||||||
assert.isFunction('callback', callback);
|
assert.isFunction('callback', callback);
|
||||||
@@ -38,7 +40,12 @@ export class EventWatcher {
|
|||||||
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
|
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
|
||||||
}
|
}
|
||||||
this._intervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
this._intervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
||||||
this._pollForBlockchainEventsAsync.bind(this, callback), this._pollingIntervalMs,
|
this._pollForBlockchainEventsAsync.bind(this, callback),
|
||||||
|
this._pollingIntervalMs,
|
||||||
|
(err: Error) => {
|
||||||
|
this.unsubscribe();
|
||||||
|
callback(err);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public unsubscribe(): void {
|
public unsubscribe(): void {
|
||||||
@@ -50,6 +57,10 @@ export class EventWatcher {
|
|||||||
}
|
}
|
||||||
private async _pollForBlockchainEventsAsync(callback: EventWatcherCallback): Promise<void> {
|
private async _pollForBlockchainEventsAsync(callback: EventWatcherCallback): Promise<void> {
|
||||||
const pendingEvents = await this._getEventsAsync();
|
const pendingEvents = await this._getEventsAsync();
|
||||||
|
if (_.isUndefined(pendingEvents)) {
|
||||||
|
// HACK: This should never happen, but happens frequently on CI due to a ganache bug
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (pendingEvents.length === 0) {
|
if (pendingEvents.length === 0) {
|
||||||
// HACK: Sometimes when node rebuilds the pending block we get back the empty result.
|
// 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,
|
// We don't want to emit a lot of removal events and bring them back after a couple of miliseconds,
|
||||||
@@ -62,16 +73,18 @@ export class EventWatcher {
|
|||||||
await this._emitDifferencesAsync(newEvents, LogEventState.Added, callback);
|
await this._emitDifferencesAsync(newEvents, LogEventState.Added, callback);
|
||||||
this._lastEvents = pendingEvents;
|
this._lastEvents = pendingEvents;
|
||||||
}
|
}
|
||||||
private async _getEventsAsync(): Promise<Web3.LogEntry[]> {
|
private async _getEventsAsync(): Promise<LogEntry[]> {
|
||||||
const eventFilter = {
|
const eventFilter = {
|
||||||
fromBlock: BlockParamLiteral.Pending,
|
fromBlock: this._stateLayer,
|
||||||
toBlock: BlockParamLiteral.Pending,
|
toBlock: this._stateLayer,
|
||||||
};
|
};
|
||||||
const events = await this._web3Wrapper.getLogsAsync(eventFilter);
|
const events = await this._web3Wrapper.getLogsAsync(eventFilter);
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
private async _emitDifferencesAsync(
|
private async _emitDifferencesAsync(
|
||||||
logs: Web3.LogEntry[], logEventState: LogEventState, callback: EventWatcherCallback,
|
logs: LogEntry[],
|
||||||
|
logEventState: LogEventState,
|
||||||
|
callback: EventWatcherCallback,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
for (const log of logs) {
|
for (const log of logs) {
|
||||||
const logEvent = {
|
const logEvent = {
|
||||||
@@ -79,7 +92,7 @@ export class EventWatcher {
|
|||||||
...log,
|
...log,
|
||||||
};
|
};
|
||||||
if (!_.isUndefined(this._intervalIdIfExists)) {
|
if (!_.isUndefined(this._intervalIdIfExists)) {
|
||||||
callback(logEvent);
|
callback(null, logEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import {intervalUtils} from '@0xproject/utils';
|
import { BigNumber, intervalUtils } from '@0xproject/utils';
|
||||||
import {BigNumber} from 'bignumber.js';
|
import { RBTree } from 'bintrees';
|
||||||
import {RBTree} from 'bintrees';
|
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {ZeroExError} from '../types';
|
import { ZeroExError } from '../types';
|
||||||
import {utils} from '../utils/utils';
|
import { utils } from '../utils/utils';
|
||||||
|
|
||||||
const DEFAULT_EXPIRATION_MARGIN_MS = 0;
|
const DEFAULT_EXPIRATION_MARGIN_MS = 0;
|
||||||
const DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS = 50;
|
const DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS = 50;
|
||||||
@@ -15,16 +14,14 @@ const DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS = 50;
|
|||||||
*/
|
*/
|
||||||
export class ExpirationWatcher {
|
export class ExpirationWatcher {
|
||||||
private _orderHashByExpirationRBTree: RBTree<string>;
|
private _orderHashByExpirationRBTree: RBTree<string>;
|
||||||
private _expiration: {[orderHash: string]: BigNumber} = {};
|
private _expiration: { [orderHash: string]: BigNumber } = {};
|
||||||
private _orderExpirationCheckingIntervalMs: number;
|
private _orderExpirationCheckingIntervalMs: number;
|
||||||
private _expirationMarginMs: number;
|
private _expirationMarginMs: number;
|
||||||
private _orderExpirationCheckingIntervalIdIfExists?: NodeJS.Timer;
|
private _orderExpirationCheckingIntervalIdIfExists?: NodeJS.Timer;
|
||||||
constructor(expirationMarginIfExistsMs?: number,
|
constructor(expirationMarginIfExistsMs?: number, orderExpirationCheckingIntervalIfExistsMs?: number) {
|
||||||
orderExpirationCheckingIntervalIfExistsMs?: number) {
|
this._expirationMarginMs = expirationMarginIfExistsMs || DEFAULT_EXPIRATION_MARGIN_MS;
|
||||||
this._expirationMarginMs = expirationMarginIfExistsMs ||
|
this._orderExpirationCheckingIntervalMs =
|
||||||
DEFAULT_EXPIRATION_MARGIN_MS;
|
expirationMarginIfExistsMs || DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS;
|
||||||
this._orderExpirationCheckingIntervalMs = expirationMarginIfExistsMs ||
|
|
||||||
DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS;
|
|
||||||
const scoreFunction = (orderHash: string) => this._expiration[orderHash].toNumber();
|
const scoreFunction = (orderHash: string) => this._expiration[orderHash].toNumber();
|
||||||
const comparator = (lhs: string, rhs: string) => scoreFunction(lhs) - scoreFunction(rhs);
|
const comparator = (lhs: string, rhs: string) => scoreFunction(lhs) - scoreFunction(rhs);
|
||||||
this._orderHashByExpirationRBTree = new RBTree(comparator);
|
this._orderHashByExpirationRBTree = new RBTree(comparator);
|
||||||
@@ -33,15 +30,17 @@ export class ExpirationWatcher {
|
|||||||
if (!_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
|
if (!_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
|
||||||
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
|
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
|
||||||
}
|
}
|
||||||
this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setInterval(
|
||||||
this._pruneExpiredOrders.bind(this, callback), this._orderExpirationCheckingIntervalMs,
|
this._pruneExpiredOrders.bind(this, callback),
|
||||||
|
this._orderExpirationCheckingIntervalMs,
|
||||||
|
_.noop, // _pruneExpiredOrders never throws
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public unsubscribe(): void {
|
public unsubscribe(): void {
|
||||||
if (_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
|
if (_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) {
|
||||||
throw new Error(ZeroExError.SubscriptionNotFound);
|
throw new Error(ZeroExError.SubscriptionNotFound);
|
||||||
}
|
}
|
||||||
intervalUtils.clearAsyncExcludingInterval(this._orderExpirationCheckingIntervalIdIfExists);
|
intervalUtils.clearInterval(this._orderExpirationCheckingIntervalIdIfExists);
|
||||||
delete this._orderExpirationCheckingIntervalIdIfExists;
|
delete this._orderExpirationCheckingIntervalIdIfExists;
|
||||||
}
|
}
|
||||||
public addOrder(orderHash: string, expirationUnixTimestampMs: BigNumber): void {
|
public addOrder(orderHash: string, expirationUnixTimestampMs: BigNumber): void {
|
||||||
|
|||||||
@@ -1,41 +1,44 @@
|
|||||||
import {schemas} from '@0xproject/json-schemas';
|
import { schemas } from '@0xproject/json-schemas';
|
||||||
import {intervalUtils} from '@0xproject/utils';
|
import { BlockParamLiteral, LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { AbiDecoder, intervalUtils } from '@0xproject/utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {ZeroEx} from '../0x';
|
import { ZeroEx } from '../0x';
|
||||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
|
||||||
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
|
|
||||||
import {OrderFilledCancelledLazyStore} from '../stores/order_filled_cancelled_lazy_store';
|
|
||||||
import {
|
import {
|
||||||
ApprovalContractEventArgs,
|
|
||||||
BlockParamLiteral,
|
|
||||||
ContractEventArgs,
|
|
||||||
DepositContractEventArgs,
|
DepositContractEventArgs,
|
||||||
EtherTokenEvents,
|
EtherTokenEvents,
|
||||||
ExchangeContractErrs,
|
WithdrawalContractEventArgs,
|
||||||
|
} from '../contract_wrappers/generated/ether_token';
|
||||||
|
import {
|
||||||
ExchangeEvents,
|
ExchangeEvents,
|
||||||
LogCancelContractEventArgs,
|
LogCancelContractEventArgs,
|
||||||
LogEvent,
|
|
||||||
LogFillContractEventArgs,
|
LogFillContractEventArgs,
|
||||||
LogWithDecodedArgs,
|
} from '../contract_wrappers/generated/exchange';
|
||||||
|
import {
|
||||||
|
ApprovalContractEventArgs,
|
||||||
|
TokenEvents,
|
||||||
|
TransferContractEventArgs,
|
||||||
|
} from '../contract_wrappers/generated/token';
|
||||||
|
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||||
|
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
||||||
|
import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
|
||||||
|
import {
|
||||||
|
ContractEventArgs,
|
||||||
|
ExchangeContractErrs,
|
||||||
|
LogEvent,
|
||||||
OnOrderStateChangeCallback,
|
OnOrderStateChangeCallback,
|
||||||
OrderState,
|
OrderState,
|
||||||
OrderStateWatcherConfig,
|
OrderStateWatcherConfig,
|
||||||
SignedOrder,
|
|
||||||
TokenEvents,
|
|
||||||
TransferContractEventArgs,
|
|
||||||
WithdrawalContractEventArgs,
|
|
||||||
ZeroExError,
|
ZeroExError,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {AbiDecoder} from '../utils/abi_decoder';
|
import { assert } from '../utils/assert';
|
||||||
import {assert} from '../utils/assert';
|
import { OrderStateUtils } from '../utils/order_state_utils';
|
||||||
import {OrderStateUtils} from '../utils/order_state_utils';
|
import { utils } from '../utils/utils';
|
||||||
import {utils} from '../utils/utils';
|
|
||||||
|
|
||||||
import {EventWatcher} from './event_watcher';
|
import { EventWatcher } from './event_watcher';
|
||||||
import {ExpirationWatcher} from './expiration_watcher';
|
import { ExpirationWatcher } from './expiration_watcher';
|
||||||
|
|
||||||
interface DependentOrderHashes {
|
interface DependentOrderHashes {
|
||||||
[makerAddress: string]: {
|
[makerAddress: string]: {
|
||||||
@@ -56,7 +59,7 @@ const DEFAULT_CLEANUP_JOB_INTERVAL_MS = 1000 * 60 * 60; // 1h
|
|||||||
/**
|
/**
|
||||||
* This class includes all the functionality related to watching a set of orders
|
* This class includes all the functionality related to watching a set of orders
|
||||||
* for potential changes in order validity/fillability. The orderWatcher notifies
|
* for potential changes in order validity/fillability. The orderWatcher notifies
|
||||||
* the subscriber of these changes so that a final decison can be made on whether
|
* the subscriber of these changes so that a final decision can be made on whether
|
||||||
* the order should be deemed invalid.
|
* the order should be deemed invalid.
|
||||||
*/
|
*/
|
||||||
export class OrderStateWatcher {
|
export class OrderStateWatcher {
|
||||||
@@ -66,7 +69,6 @@ export class OrderStateWatcher {
|
|||||||
private _callbackIfExists?: OnOrderStateChangeCallback;
|
private _callbackIfExists?: OnOrderStateChangeCallback;
|
||||||
private _eventWatcher: EventWatcher;
|
private _eventWatcher: EventWatcher;
|
||||||
private _web3Wrapper: Web3Wrapper;
|
private _web3Wrapper: Web3Wrapper;
|
||||||
private _abiDecoder: AbiDecoder;
|
|
||||||
private _expirationWatcher: ExpirationWatcher;
|
private _expirationWatcher: ExpirationWatcher;
|
||||||
private _orderStateUtils: OrderStateUtils;
|
private _orderStateUtils: OrderStateUtils;
|
||||||
private _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
|
private _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
|
||||||
@@ -74,32 +76,34 @@ export class OrderStateWatcher {
|
|||||||
private _cleanupJobInterval: number;
|
private _cleanupJobInterval: number;
|
||||||
private _cleanupJobIntervalIdIfExists?: NodeJS.Timer;
|
private _cleanupJobIntervalIdIfExists?: NodeJS.Timer;
|
||||||
constructor(
|
constructor(
|
||||||
web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder, token: TokenWrapper, exchange: ExchangeWrapper,
|
web3Wrapper: Web3Wrapper,
|
||||||
|
token: TokenWrapper,
|
||||||
|
exchange: ExchangeWrapper,
|
||||||
config?: OrderStateWatcherConfig,
|
config?: OrderStateWatcherConfig,
|
||||||
) {
|
) {
|
||||||
this._abiDecoder = abiDecoder;
|
|
||||||
this._web3Wrapper = web3Wrapper;
|
this._web3Wrapper = web3Wrapper;
|
||||||
const pollingIntervalIfExistsMs = _.isUndefined(config) ? undefined : config.eventPollingIntervalMs;
|
const pollingIntervalIfExistsMs = _.isUndefined(config) ? undefined : config.eventPollingIntervalMs;
|
||||||
this._eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalIfExistsMs);
|
const stateLayer =
|
||||||
this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(
|
_.isUndefined(config) || _.isUndefined(config.stateLayer) ? BlockParamLiteral.Latest : config.stateLayer;
|
||||||
token, BlockParamLiteral.Pending,
|
this._eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalIfExistsMs, stateLayer);
|
||||||
);
|
this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(token, stateLayer);
|
||||||
this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(exchange);
|
this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(exchange);
|
||||||
this._orderStateUtils = new OrderStateUtils(
|
this._orderStateUtils = new OrderStateUtils(
|
||||||
this._balanceAndProxyAllowanceLazyStore, this._orderFilledCancelledLazyStore,
|
this._balanceAndProxyAllowanceLazyStore,
|
||||||
|
this._orderFilledCancelledLazyStore,
|
||||||
);
|
);
|
||||||
const orderExpirationCheckingIntervalMsIfExists = _.isUndefined(config) ?
|
const orderExpirationCheckingIntervalMsIfExists = _.isUndefined(config)
|
||||||
undefined :
|
? undefined
|
||||||
config.orderExpirationCheckingIntervalMs;
|
: config.orderExpirationCheckingIntervalMs;
|
||||||
const expirationMarginIfExistsMs = _.isUndefined(config) ?
|
const expirationMarginIfExistsMs = _.isUndefined(config) ? undefined : config.expirationMarginMs;
|
||||||
undefined :
|
|
||||||
config.expirationMarginMs;
|
|
||||||
this._expirationWatcher = new ExpirationWatcher(
|
this._expirationWatcher = new ExpirationWatcher(
|
||||||
expirationMarginIfExistsMs, orderExpirationCheckingIntervalMsIfExists,
|
expirationMarginIfExistsMs,
|
||||||
|
orderExpirationCheckingIntervalMsIfExists,
|
||||||
);
|
);
|
||||||
this._cleanupJobInterval = _.isUndefined(config) || _.isUndefined(config.cleanupJobIntervalMs) ?
|
this._cleanupJobInterval =
|
||||||
DEFAULT_CLEANUP_JOB_INTERVAL_MS :
|
_.isUndefined(config) || _.isUndefined(config.cleanupJobIntervalMs)
|
||||||
config.cleanupJobIntervalMs;
|
? DEFAULT_CLEANUP_JOB_INTERVAL_MS
|
||||||
|
: config.cleanupJobIntervalMs;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Add an order to the orderStateWatcher. Before the order is added, it's
|
* Add an order to the orderStateWatcher. Before the order is added, it's
|
||||||
@@ -129,8 +133,12 @@ export class OrderStateWatcher {
|
|||||||
delete this._orderStateByOrderHashCache[orderHash];
|
delete this._orderStateByOrderHashCache[orderHash];
|
||||||
const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
|
const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
|
||||||
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
||||||
|
|
||||||
this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
|
this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
|
||||||
this._removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
|
if (zrxTokenAddress !== signedOrder.makerTokenAddress) {
|
||||||
|
this._removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash);
|
||||||
|
}
|
||||||
|
|
||||||
this._expirationWatcher.removeOrder(orderHash);
|
this._expirationWatcher.removeOrder(orderHash);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -148,7 +156,12 @@ export class OrderStateWatcher {
|
|||||||
this._eventWatcher.subscribe(this._onEventWatcherCallbackAsync.bind(this));
|
this._eventWatcher.subscribe(this._onEventWatcherCallbackAsync.bind(this));
|
||||||
this._expirationWatcher.subscribe(this._onOrderExpired.bind(this));
|
this._expirationWatcher.subscribe(this._onOrderExpired.bind(this));
|
||||||
this._cleanupJobIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
this._cleanupJobIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval(
|
||||||
this._cleanupAsync.bind(this), this._cleanupJobInterval,
|
this._cleanupAsync.bind(this),
|
||||||
|
this._cleanupJobInterval,
|
||||||
|
(err: Error) => {
|
||||||
|
this.unsubscribe();
|
||||||
|
callback(err);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -201,37 +214,45 @@ export class OrderStateWatcher {
|
|||||||
if (!_.isUndefined(this._orderByOrderHash[orderHash])) {
|
if (!_.isUndefined(this._orderByOrderHash[orderHash])) {
|
||||||
this.removeOrder(orderHash);
|
this.removeOrder(orderHash);
|
||||||
if (!_.isUndefined(this._callbackIfExists)) {
|
if (!_.isUndefined(this._callbackIfExists)) {
|
||||||
this._callbackIfExists(orderState);
|
this._callbackIfExists(null, orderState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async _onEventWatcherCallbackAsync(log: LogEvent): Promise<void> {
|
private async _onEventWatcherCallbackAsync(err: Error | null, logIfExists?: LogEvent): Promise<void> {
|
||||||
const maybeDecodedLog = this._abiDecoder.tryToDecodeLogOrNoop(log);
|
if (!_.isNull(err)) {
|
||||||
const isLogDecoded = !_.isUndefined((maybeDecodedLog as LogWithDecodedArgs<any>).event);
|
if (!_.isUndefined(this._callbackIfExists)) {
|
||||||
|
this._callbackIfExists(err);
|
||||||
|
this.unsubscribe();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const log = logIfExists as LogEvent; // At this moment we are sure that no error occured and log is defined.
|
||||||
|
const maybeDecodedLog = this._web3Wrapper.abiDecoder.tryToDecodeLogOrNoop<ContractEventArgs>(log);
|
||||||
|
const isLogDecoded = !_.isUndefined(((maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>).event);
|
||||||
if (!isLogDecoded) {
|
if (!isLogDecoded) {
|
||||||
return; // noop
|
return; // noop
|
||||||
}
|
}
|
||||||
const decodedLog = maybeDecodedLog as LogWithDecodedArgs<ContractEventArgs>;
|
const decodedLog = (maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>;
|
||||||
let makerToken: string;
|
let makerToken: string;
|
||||||
let makerAddress: string;
|
let makerAddress: string;
|
||||||
switch (decodedLog.event) {
|
switch (decodedLog.event) {
|
||||||
case TokenEvents.Approval:
|
case TokenEvents.Approval: {
|
||||||
{
|
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
const args = decodedLog.args as ApprovalContractEventArgs;
|
const args = decodedLog.args as ApprovalContractEventArgs;
|
||||||
this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(decodedLog.address, args._owner);
|
this._balanceAndProxyAllowanceLazyStore.deleteProxyAllowance(decodedLog.address, args._owner);
|
||||||
// Revalidate orders
|
// Revalidate orders
|
||||||
makerToken = decodedLog.address;
|
makerToken = decodedLog.address;
|
||||||
makerAddress = args._owner;
|
makerAddress = args._owner;
|
||||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
if (
|
||||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||||
|
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
|
||||||
|
) {
|
||||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TokenEvents.Transfer:
|
case TokenEvents.Transfer: {
|
||||||
{
|
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
const args = decodedLog.args as TransferContractEventArgs;
|
const args = decodedLog.args as TransferContractEventArgs;
|
||||||
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._from);
|
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._from);
|
||||||
@@ -239,45 +260,48 @@ export class OrderStateWatcher {
|
|||||||
// Revalidate orders
|
// Revalidate orders
|
||||||
makerToken = decodedLog.address;
|
makerToken = decodedLog.address;
|
||||||
makerAddress = args._from;
|
makerAddress = args._from;
|
||||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
if (
|
||||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||||
|
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
|
||||||
|
) {
|
||||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EtherTokenEvents.Deposit:
|
case EtherTokenEvents.Deposit: {
|
||||||
{
|
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
const args = decodedLog.args as DepositContractEventArgs;
|
const args = decodedLog.args as DepositContractEventArgs;
|
||||||
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
|
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
|
||||||
// Revalidate orders
|
// Revalidate orders
|
||||||
makerToken = decodedLog.address;
|
makerToken = decodedLog.address;
|
||||||
makerAddress = args._owner;
|
makerAddress = args._owner;
|
||||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
if (
|
||||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||||
|
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
|
||||||
|
) {
|
||||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EtherTokenEvents.Withdrawal:
|
case EtherTokenEvents.Withdrawal: {
|
||||||
{
|
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
const args = decodedLog.args as WithdrawalContractEventArgs;
|
const args = decodedLog.args as WithdrawalContractEventArgs;
|
||||||
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
|
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
|
||||||
// Revalidate orders
|
// Revalidate orders
|
||||||
makerToken = decodedLog.address;
|
makerToken = decodedLog.address;
|
||||||
makerAddress = args._owner;
|
makerAddress = args._owner;
|
||||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
if (
|
||||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||||
|
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])
|
||||||
|
) {
|
||||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExchangeEvents.LogFill:
|
case ExchangeEvents.LogFill: {
|
||||||
{
|
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
const args = decodedLog.args as LogFillContractEventArgs;
|
const args = decodedLog.args as LogFillContractEventArgs;
|
||||||
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(args.orderHash);
|
this._orderFilledCancelledLazyStore.deleteFilledTakerAmount(args.orderHash);
|
||||||
@@ -289,8 +313,7 @@ export class OrderStateWatcher {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExchangeEvents.LogCancel:
|
case ExchangeEvents.LogCancel: {
|
||||||
{
|
|
||||||
// Invalidate cache
|
// Invalidate cache
|
||||||
const args = decodedLog.args as LogCancelContractEventArgs;
|
const args = decodedLog.args as LogCancelContractEventArgs;
|
||||||
this._orderFilledCancelledLazyStore.deleteCancelledTakerAmount(args.orderHash);
|
this._orderFilledCancelledLazyStore.deleteCancelledTakerAmount(args.orderHash);
|
||||||
@@ -324,7 +347,7 @@ export class OrderStateWatcher {
|
|||||||
} else {
|
} else {
|
||||||
this._orderStateByOrderHashCache[orderHash] = orderState;
|
this._orderStateByOrderHashCache[orderHash] = orderState;
|
||||||
}
|
}
|
||||||
this._callbackIfExists(orderState);
|
this._callbackIfExists(null, orderState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private _addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string): void {
|
private _addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string): void {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {BigNumber} from 'bignumber.js';
|
import { SignedOrder } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import {SignedOrder} from '../types';
|
|
||||||
|
|
||||||
export class RemainingFillableCalculator {
|
export class RemainingFillableCalculator {
|
||||||
private _signedOrder: SignedOrder;
|
private _signedOrder: SignedOrder;
|
||||||
@@ -10,18 +9,21 @@ export class RemainingFillableCalculator {
|
|||||||
private _transferrableMakerFeeTokenAmount: BigNumber;
|
private _transferrableMakerFeeTokenAmount: BigNumber;
|
||||||
private _remainingMakerTokenAmount: BigNumber;
|
private _remainingMakerTokenAmount: BigNumber;
|
||||||
private _remainingMakerFeeAmount: BigNumber;
|
private _remainingMakerFeeAmount: BigNumber;
|
||||||
constructor(signedOrder: SignedOrder,
|
constructor(
|
||||||
isMakerTokenZRX: boolean,
|
signedOrder: SignedOrder,
|
||||||
transferrableMakerTokenAmount: BigNumber,
|
isMakerTokenZRX: boolean,
|
||||||
transferrableMakerFeeTokenAmount: BigNumber,
|
transferrableMakerTokenAmount: BigNumber,
|
||||||
remainingMakerTokenAmount: BigNumber) {
|
transferrableMakerFeeTokenAmount: BigNumber,
|
||||||
|
remainingMakerTokenAmount: BigNumber,
|
||||||
|
) {
|
||||||
this._signedOrder = signedOrder;
|
this._signedOrder = signedOrder;
|
||||||
this._isMakerTokenZRX = isMakerTokenZRX;
|
this._isMakerTokenZRX = isMakerTokenZRX;
|
||||||
this._transferrableMakerTokenAmount = transferrableMakerTokenAmount;
|
this._transferrableMakerTokenAmount = transferrableMakerTokenAmount;
|
||||||
this._transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount;
|
this._transferrableMakerFeeTokenAmount = transferrableMakerFeeTokenAmount;
|
||||||
this._remainingMakerTokenAmount = remainingMakerTokenAmount;
|
this._remainingMakerTokenAmount = remainingMakerTokenAmount;
|
||||||
this._remainingMakerFeeAmount = remainingMakerTokenAmount.times(signedOrder.makerFee)
|
this._remainingMakerFeeAmount = remainingMakerTokenAmount
|
||||||
.dividedToIntegerBy(signedOrder.makerTokenAmount);
|
.times(signedOrder.makerFee)
|
||||||
|
.dividedToIntegerBy(signedOrder.makerTokenAmount);
|
||||||
}
|
}
|
||||||
public computeRemainingMakerFillable(): BigNumber {
|
public computeRemainingMakerFillable(): BigNumber {
|
||||||
if (this._hasSufficientFundsForFeeAndTransferAmount()) {
|
if (this._hasSufficientFundsForFeeAndTransferAmount()) {
|
||||||
@@ -33,20 +35,24 @@ export class RemainingFillableCalculator {
|
|||||||
return this._calculatePartiallyFillableMakerTokenAmount();
|
return this._calculatePartiallyFillableMakerTokenAmount();
|
||||||
}
|
}
|
||||||
public computeRemainingTakerFillable(): BigNumber {
|
public computeRemainingTakerFillable(): BigNumber {
|
||||||
return this.computeRemainingMakerFillable().times(this._signedOrder.takerTokenAmount)
|
return this.computeRemainingMakerFillable()
|
||||||
.dividedToIntegerBy(this._signedOrder.makerTokenAmount);
|
.times(this._signedOrder.takerTokenAmount)
|
||||||
|
.dividedToIntegerBy(this._signedOrder.makerTokenAmount);
|
||||||
}
|
}
|
||||||
private _hasSufficientFundsForFeeAndTransferAmount(): boolean {
|
private _hasSufficientFundsForFeeAndTransferAmount(): boolean {
|
||||||
if (this._isMakerTokenZRX) {
|
if (this._isMakerTokenZRX) {
|
||||||
const totalZRXTransferAmountRequired = this._remainingMakerTokenAmount.plus(this._remainingMakerFeeAmount);
|
const totalZRXTransferAmountRequired = this._remainingMakerTokenAmount.plus(this._remainingMakerFeeAmount);
|
||||||
const hasSufficientFunds = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
|
const hasSufficientFunds = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
|
||||||
totalZRXTransferAmountRequired);
|
totalZRXTransferAmountRequired,
|
||||||
|
);
|
||||||
return hasSufficientFunds;
|
return hasSufficientFunds;
|
||||||
} else {
|
} else {
|
||||||
const hasSufficientFundsForTransferAmount = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
|
const hasSufficientFundsForTransferAmount = this._transferrableMakerTokenAmount.greaterThanOrEqualTo(
|
||||||
this._remainingMakerTokenAmount);
|
this._remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
const hasSufficientFundsForFeeAmount = this._transferrableMakerFeeTokenAmount.greaterThanOrEqualTo(
|
const hasSufficientFundsForFeeAmount = this._transferrableMakerFeeTokenAmount.greaterThanOrEqualTo(
|
||||||
this._remainingMakerFeeAmount);
|
this._remainingMakerFeeAmount,
|
||||||
|
);
|
||||||
const hasSufficientFunds = hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount;
|
const hasSufficientFunds = hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount;
|
||||||
return hasSufficientFunds;
|
return hasSufficientFunds;
|
||||||
}
|
}
|
||||||
@@ -57,8 +63,10 @@ export class RemainingFillableCalculator {
|
|||||||
// The number of times the maker can fill the order, if each fill only required the transfer of a single
|
// The number of times the maker can fill the order, if each fill only required the transfer of a single
|
||||||
// baseUnit of fee tokens.
|
// baseUnit of fee tokens.
|
||||||
// Given 2 ZRXwei, the maximum amount of times Maker can fill this order, in terms of fees, is 2
|
// Given 2 ZRXwei, the maximum amount of times Maker can fill this order, in terms of fees, is 2
|
||||||
const fillableTimesInFeeTokenBaseUnits = BigNumber.min(this._transferrableMakerFeeTokenAmount,
|
const fillableTimesInFeeTokenBaseUnits = BigNumber.min(
|
||||||
this._remainingMakerFeeAmount);
|
this._transferrableMakerFeeTokenAmount,
|
||||||
|
this._remainingMakerFeeAmount,
|
||||||
|
);
|
||||||
// The number of times the Maker can fill the order, given the Maker Token Balance
|
// The number of times the Maker can fill the order, given the Maker Token Balance
|
||||||
// Assuming a balance of 150 wei, and an orderToFeeRatio of 100:1, maker can fill this order 1 time.
|
// Assuming a balance of 150 wei, and an orderToFeeRatio of 100:1, maker can fill this order 1 time.
|
||||||
let fillableTimesInMakerTokenUnits = this._transferrableMakerTokenAmount.dividedBy(orderToFeeRatio);
|
let fillableTimesInMakerTokenUnits = this._transferrableMakerTokenAmount.dividedBy(orderToFeeRatio);
|
||||||
@@ -68,20 +76,20 @@ export class RemainingFillableCalculator {
|
|||||||
const totalZRXTokenPooled = this._transferrableMakerTokenAmount;
|
const totalZRXTokenPooled = this._transferrableMakerTokenAmount;
|
||||||
// The purchasing power here is less as the tokens are taken from the same Pool
|
// The purchasing power here is less as the tokens are taken from the same Pool
|
||||||
// For every one number of fills, we have to take an extra ZRX out of the pool
|
// For every one number of fills, we have to take an extra ZRX out of the pool
|
||||||
fillableTimesInMakerTokenUnits = totalZRXTokenPooled.dividedBy(
|
fillableTimesInMakerTokenUnits = totalZRXTokenPooled.dividedBy(orderToFeeRatio.plus(new BigNumber(1)));
|
||||||
orderToFeeRatio.plus(new BigNumber(1)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// When Ratio is not fully divisible there can be remainders which cannot be represented, so they are floored.
|
// When Ratio is not fully divisible there can be remainders which cannot be represented, so they are floored.
|
||||||
// This can result in a RoundingError being thrown by the Exchange Contract.
|
// This can result in a RoundingError being thrown by the Exchange Contract.
|
||||||
const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits
|
const partiallyFillableMakerTokenAmount = fillableTimesInMakerTokenUnits
|
||||||
.times(this._signedOrder.makerTokenAmount)
|
.times(this._signedOrder.makerTokenAmount)
|
||||||
.dividedToIntegerBy(this._signedOrder.makerFee);
|
.dividedToIntegerBy(this._signedOrder.makerFee);
|
||||||
const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenBaseUnits
|
const partiallyFillableFeeTokenAmount = fillableTimesInFeeTokenBaseUnits
|
||||||
.times(this._signedOrder.makerTokenAmount)
|
.times(this._signedOrder.makerTokenAmount)
|
||||||
.dividedToIntegerBy(this._signedOrder.makerFee);
|
.dividedToIntegerBy(this._signedOrder.makerFee);
|
||||||
const partiallyFillableAmount = BigNumber.min(partiallyFillableMakerTokenAmount,
|
const partiallyFillableAmount = BigNumber.min(
|
||||||
partiallyFillableFeeTokenAmount);
|
partiallyFillableMakerTokenAmount,
|
||||||
|
partiallyFillableFeeTokenAmount,
|
||||||
|
);
|
||||||
return partiallyFillableAmount;
|
return partiallyFillableAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,5 @@
|
|||||||
export const zeroExConfigSchema = {
|
export const zeroExConfigSchema = {
|
||||||
id: '/ZeroExConfig',
|
id: '/ZeroExConfig',
|
||||||
properties: {
|
oneOf: [{ $ref: '/ZeroExPrivateNetworkConfig' }, { $ref: '/ZeroExPublicNetworkConfig' }],
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
type: 'object',
|
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,29 @@
|
|||||||
|
export const zeroExPublicNetworkConfigSchema = {
|
||||||
|
id: '/ZeroExPublicNetworkConfig',
|
||||||
|
properties: {
|
||||||
|
networkId: {
|
||||||
|
type: 'number',
|
||||||
|
enum: [1, 3, 4, 42, 50],
|
||||||
|
},
|
||||||
|
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,8 +1,8 @@
|
|||||||
import {BigNumber} from 'bignumber.js';
|
import { BlockParamLiteral } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||||
import {BlockParamLiteral} from '../types';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy on read store for balances/proxyAllowances of tokens/accounts
|
* Copy on read store for balances/proxyAllowances of tokens/accounts
|
||||||
@@ -52,8 +52,10 @@ export class BalanceAndProxyAllowanceLazyStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
|
public async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
|
||||||
if (_.isUndefined(this._proxyAllowance[tokenAddress]) ||
|
if (
|
||||||
_.isUndefined(this._proxyAllowance[tokenAddress][userAddress])) {
|
_.isUndefined(this._proxyAllowance[tokenAddress]) ||
|
||||||
|
_.isUndefined(this._proxyAllowance[tokenAddress][userAddress])
|
||||||
|
) {
|
||||||
const methodOpts = {
|
const methodOpts = {
|
||||||
defaultBlock: this._defaultBlock,
|
defaultBlock: this._defaultBlock,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {BigNumber} from 'bignumber.js';
|
import { BlockParamLiteral } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||||
import {BlockParamLiteral} from '../types';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy on read store for filled/cancelled taker amounts
|
* Copy on read store for filled/cancelled taker amounts
|
||||||
|
|||||||
@@ -1,7 +1,23 @@
|
|||||||
import {TransactionReceipt} from '@0xproject/types';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import BigNumber from 'bignumber.js';
|
|
||||||
|
import {
|
||||||
|
BlockParam,
|
||||||
|
BlockParamLiteral,
|
||||||
|
ContractAbi,
|
||||||
|
ContractEventArg,
|
||||||
|
FilterObject,
|
||||||
|
LogEntryEvent,
|
||||||
|
LogWithDecodedArgs,
|
||||||
|
Order,
|
||||||
|
SignedOrder,
|
||||||
|
} from '@0xproject/types';
|
||||||
|
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
import { EtherTokenContractEventArgs, EtherTokenEvents } from './contract_wrappers/generated/ether_token';
|
||||||
|
import { ExchangeContractEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange';
|
||||||
|
import { TokenContractEventArgs, TokenEvents } from './contract_wrappers/generated/token';
|
||||||
|
|
||||||
export enum ZeroExError {
|
export enum ZeroExError {
|
||||||
ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
|
ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
|
||||||
ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
|
ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
|
||||||
@@ -22,7 +38,6 @@ export enum ZeroExError {
|
|||||||
NoNetworkId = 'NO_NETWORK_ID',
|
NoNetworkId = 'NO_NETWORK_ID',
|
||||||
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
|
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
|
||||||
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
|
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
|
||||||
TransactionMiningTimeout = 'TRANSACTION_MINING_TIMEOUT',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum InternalZeroExError {
|
export enum InternalZeroExError {
|
||||||
@@ -31,35 +46,18 @@ export enum InternalZeroExError {
|
|||||||
WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY',
|
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 OrderAddresses = [string, string, string, string, string];
|
||||||
|
|
||||||
export type OrderValues = [BigNumber, BigNumber, BigNumber,
|
export type OrderValues = [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber, BigNumber];
|
||||||
BigNumber, BigNumber, BigNumber];
|
|
||||||
|
|
||||||
export type LogEvent = Web3.LogEntryEvent;
|
export type LogEvent = LogEntryEvent;
|
||||||
export interface DecodedLogEvent<ArgsType> {
|
export interface DecodedLogEvent<ArgsType> {
|
||||||
isRemoved: boolean;
|
isRemoved: boolean;
|
||||||
log: LogWithDecodedArgs<ArgsType>;
|
log: LogWithDecodedArgs<ArgsType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EventCallback<ArgsType> = (err: null|Error, log?: DecodedLogEvent<ArgsType>) => void;
|
export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void;
|
||||||
export type EventWatcherCallback = (log: LogEvent) => void;
|
export type EventWatcherCallback = (err: null | Error, log?: LogEvent) => void;
|
||||||
|
|
||||||
export enum SolidityTypes {
|
|
||||||
Address = 'address',
|
|
||||||
Uint256 = 'uint256',
|
|
||||||
Uint8 = 'uint8',
|
|
||||||
Uint = 'uint',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ExchangeContractErrCodes {
|
export enum ExchangeContractErrCodes {
|
||||||
ERROR_FILL_EXPIRED, // Order has already expired
|
ERROR_FILL_EXPIRED, // Order has already expired
|
||||||
@@ -95,8 +93,6 @@ export enum ExchangeContractErrs {
|
|||||||
BatchOrdersMustHaveAtLeastOneItem = 'BATCH_ORDERS_MUST_HAVE_AT_LEAST_ONE_ITEM',
|
BatchOrdersMustHaveAtLeastOneItem = 'BATCH_ORDERS_MUST_HAVE_AT_LEAST_ONE_ITEM',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RawLog = Web3.LogEntry;
|
|
||||||
|
|
||||||
export interface ContractEvent {
|
export interface ContractEvent {
|
||||||
logIndex: number;
|
logIndex: number;
|
||||||
transactionIndex: number;
|
transactionIndex: number;
|
||||||
@@ -109,78 +105,10 @@ export interface ContractEvent {
|
|||||||
args: ContractEventArgs;
|
args: ContractEventArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LogFillContractEventArgs {
|
export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs;
|
||||||
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]
|
// [address, name, symbol, decimals, ipfsHash, swarmHash]
|
||||||
export type TokenMetadata = [string, string, string, BigNumber, string, string];
|
export type TokenMetadata = [string, string, string, number, string, string];
|
||||||
|
|
||||||
export interface Token {
|
export interface Token {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -200,40 +128,12 @@ export interface TokenAddressBySymbol {
|
|||||||
[symbol: string]: string;
|
[symbol: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ExchangeEvents {
|
export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents;
|
||||||
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 {
|
export interface IndexedFilterValues {
|
||||||
[index: string]: ContractEventArg;
|
[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 {
|
export interface BlockRange {
|
||||||
fromBlock: BlockParam;
|
fromBlock: BlockParam;
|
||||||
toBlock: BlockParam;
|
toBlock: BlockParam;
|
||||||
@@ -242,7 +142,7 @@ export interface BlockRange {
|
|||||||
export type DoneCallback = (err?: Error) => void;
|
export type DoneCallback = (err?: Error) => void;
|
||||||
|
|
||||||
export interface OrderCancellationRequest {
|
export interface OrderCancellationRequest {
|
||||||
order: Order|SignedOrder;
|
order: Order | SignedOrder;
|
||||||
takerTokenCancelAmount: BigNumber;
|
takerTokenCancelAmount: BigNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,37 +154,27 @@ export interface OrderFillRequest {
|
|||||||
export type AsyncMethod = (...args: any[]) => Promise<any>;
|
export type AsyncMethod = (...args: any[]) => Promise<any>;
|
||||||
export type SyncMethod = (...args: any[]) => 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
|
* orderExpirationCheckingIntervalMs: How often to check for expired orders. Default: 50
|
||||||
* eventPollingIntervalMs: How often to poll the Ethereum node for new events. Defaults: 200
|
* eventPollingIntervalMs: How often to poll the Ethereum node for new events. Default: 200
|
||||||
* expirationMarginMs: Amount of time before order expiry that you'd like to be notified
|
* expirationMarginMs: Amount of time before order expiry that you'd like to be notified
|
||||||
* of an orders expiration. Defaults: 0
|
* of an orders expiration. Default: 0
|
||||||
* cleanupJobIntervalMs: How often to run a cleanup job which revalidates all the orders. Defaults: 1h
|
* cleanupJobIntervalMs: How often to run a cleanup job which revalidates all the orders. Defaults: 1h
|
||||||
|
* stateLayer: Optional blockchain state layer OrderWatcher will monitor for new events. Default: latest
|
||||||
*/
|
*/
|
||||||
export interface OrderStateWatcherConfig {
|
export interface OrderStateWatcherConfig {
|
||||||
orderExpirationCheckingIntervalMs?: number;
|
orderExpirationCheckingIntervalMs?: number;
|
||||||
eventPollingIntervalMs?: number;
|
eventPollingIntervalMs?: number;
|
||||||
expirationMarginMs?: number;
|
expirationMarginMs?: number;
|
||||||
cleanupJobIntervalMs?: number;
|
cleanupJobIntervalMs?: number;
|
||||||
|
stateLayer: BlockParamLiteral;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 42-kovan, 50-testrpc)
|
* networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 3-ropsten, 4-rinkeby, 42-kovan, 50-testrpc)
|
||||||
* gasPrice: Gas price to use with every transaction
|
* gasPrice: Gas price to use with every transaction
|
||||||
* exchangeContractAddress: The address of an exchange contract to use
|
* exchangeContractAddress: The address of an exchange contract to use
|
||||||
|
* zrxContractAddress: The address of the ZRX contract to use
|
||||||
* tokenRegistryContractAddress: The address of a token registry contract to use
|
* tokenRegistryContractAddress: The address of a token registry contract to use
|
||||||
* tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use
|
* tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use
|
||||||
* orderWatcherConfig: All the configs related to the orderWatcher
|
* orderWatcherConfig: All the configs related to the orderWatcher
|
||||||
@@ -293,33 +183,17 @@ export interface ZeroExConfig {
|
|||||||
networkId: number;
|
networkId: number;
|
||||||
gasPrice?: BigNumber;
|
gasPrice?: BigNumber;
|
||||||
exchangeContractAddress?: string;
|
exchangeContractAddress?: string;
|
||||||
|
zrxContractAddress?: string;
|
||||||
tokenRegistryContractAddress?: string;
|
tokenRegistryContractAddress?: string;
|
||||||
tokenTransferProxyContractAddress?: string;
|
tokenTransferProxyContractAddress?: string;
|
||||||
orderWatcherConfig?: OrderStateWatcherConfig;
|
orderWatcherConfig?: OrderStateWatcherConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AbiType {
|
export type ArtifactContractName = 'ZRX' | 'TokenTransferProxy' | 'TokenRegistry' | 'Token' | 'Exchange' | 'EtherToken';
|
||||||
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 {
|
export interface Artifact {
|
||||||
contract_name: ArtifactContractName;
|
contract_name: ArtifactContractName;
|
||||||
abi: Web3.ContractAbi;
|
abi: ContractAbi;
|
||||||
networks: {
|
networks: {
|
||||||
[networkId: number]: {
|
[networkId: number]: {
|
||||||
address: string;
|
address: string;
|
||||||
@@ -344,7 +218,7 @@ export interface ValidateOrderFillableOpts {
|
|||||||
* flag when running Parity).
|
* flag when running Parity).
|
||||||
*/
|
*/
|
||||||
export interface MethodOpts {
|
export interface MethodOpts {
|
||||||
defaultBlock?: Web3.BlockParam;
|
defaultBlock?: BlockParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -364,8 +238,6 @@ export interface OrderTransactionOpts extends TransactionOpts {
|
|||||||
shouldValidate?: boolean;
|
shouldValidate?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FilterObject = Web3.FilterObject;
|
|
||||||
|
|
||||||
export enum TradeSide {
|
export enum TradeSide {
|
||||||
Maker = 'maker',
|
Maker = 'maker',
|
||||||
Taker = 'taker',
|
Taker = 'taker',
|
||||||
@@ -399,7 +271,7 @@ export interface OrderStateInvalid {
|
|||||||
error: ExchangeContractErrs;
|
error: ExchangeContractErrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OrderState = OrderStateValid|OrderStateInvalid;
|
export type OrderState = OrderStateValid | OrderStateInvalid;
|
||||||
|
|
||||||
export type OnOrderStateChangeCallback = (orderState: OrderState) => void;
|
export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void;
|
||||||
// tslint:disable:max-file-line-count
|
// 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,14 +1,14 @@
|
|||||||
import {assert as sharedAssert} from '@0xproject/assert';
|
import { assert as sharedAssert } from '@0xproject/assert';
|
||||||
// We need those two unused imports because they're actually used by sharedAssert which gets injected here
|
// We need those two unused imports because they're actually used by sharedAssert which gets injected here
|
||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
import {Schema} from '@0xproject/json-schemas';
|
import { Schema } from '@0xproject/json-schemas';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
|
||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
import * as BigNumber from 'bignumber.js';
|
import { ECSignature } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {ECSignature} from '../types';
|
import { signatureUtils } from '../utils/signature_utils';
|
||||||
import {signatureUtils} from '../utils/signature_utils';
|
|
||||||
|
|
||||||
export const assert = {
|
export const assert = {
|
||||||
...sharedAssert,
|
...sharedAssert,
|
||||||
@@ -16,11 +16,15 @@ export const assert = {
|
|||||||
const isValidSignature = signatureUtils.isValidSignature(orderHash, ecSignature, signerAddress);
|
const isValidSignature = signatureUtils.isValidSignature(orderHash, ecSignature, signerAddress);
|
||||||
this.assert(isValidSignature, `Expected order with hash '${orderHash}' to have a valid signature`);
|
this.assert(isValidSignature, `Expected order with hash '${orderHash}' to have a valid signature`);
|
||||||
},
|
},
|
||||||
async isSenderAddressAsync(variableName: string, senderAddressHex: string,
|
async isSenderAddressAsync(
|
||||||
web3Wrapper: Web3Wrapper): Promise<void> {
|
variableName: string,
|
||||||
|
senderAddressHex: string,
|
||||||
|
web3Wrapper: Web3Wrapper,
|
||||||
|
): Promise<void> {
|
||||||
sharedAssert.isETHAddressHex(variableName, senderAddressHex);
|
sharedAssert.isETHAddressHex(variableName, senderAddressHex);
|
||||||
const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex);
|
const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex);
|
||||||
sharedAssert.assert(isSenderAddressAvailable,
|
sharedAssert.assert(
|
||||||
|
isSenderAddressAvailable,
|
||||||
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
export const constants = {
|
export const constants = {
|
||||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {AsyncMethod, SyncMethod, ZeroExError} from '../types';
|
import { AsyncMethod, SyncMethod, ZeroExError } from '../types';
|
||||||
|
|
||||||
import {constants} from './constants';
|
import { constants } from './constants';
|
||||||
|
|
||||||
type ErrorTransformer = (err: Error) => Error;
|
type ErrorTransformer = (err: Error) => Error;
|
||||||
|
|
||||||
@@ -18,8 +18,8 @@ const contractCallErrorTransformer = (error: Error) => {
|
|||||||
|
|
||||||
const schemaErrorTransformer = (error: Error) => {
|
const schemaErrorTransformer = (error: Error) => {
|
||||||
if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) {
|
if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) {
|
||||||
// tslint:disable-next-line:max-line-length
|
const errMsg =
|
||||||
const errMsg = 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||||
return new Error(errMsg);
|
return new Error(errMsg);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
@@ -30,14 +30,16 @@ const schemaErrorTransformer = (error: Error) => {
|
|||||||
*/
|
*/
|
||||||
const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
||||||
const asyncErrorHandlingDecorator = (
|
const asyncErrorHandlingDecorator = (
|
||||||
target: object, key: string|symbol, descriptor: TypedPropertyDescriptor<AsyncMethod>,
|
target: object,
|
||||||
|
key: string | symbol,
|
||||||
|
descriptor: TypedPropertyDescriptor<AsyncMethod>,
|
||||||
) => {
|
) => {
|
||||||
const originalMethod = (descriptor.value as AsyncMethod);
|
const originalMethod = descriptor.value as AsyncMethod;
|
||||||
|
|
||||||
// Do not use arrow syntax here. Use a function expression in
|
// Do not use arrow syntax here. Use a function expression in
|
||||||
// order to use the correct value of `this` in this method
|
// order to use the correct value of `this` in this method
|
||||||
// tslint:disable-next-line:only-arrow-functions
|
// tslint:disable-next-line:only-arrow-functions
|
||||||
descriptor.value = async function(...args: any[]) {
|
descriptor.value = async function(...args: any[]) {
|
||||||
try {
|
try {
|
||||||
const result = await originalMethod.apply(this, args);
|
const result = await originalMethod.apply(this, args);
|
||||||
return result;
|
return result;
|
||||||
@@ -55,9 +57,11 @@ const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
|||||||
|
|
||||||
const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
||||||
const syncErrorHandlingDecorator = (
|
const syncErrorHandlingDecorator = (
|
||||||
target: object, key: string|symbol, descriptor: TypedPropertyDescriptor<SyncMethod>,
|
target: object,
|
||||||
|
key: string | symbol,
|
||||||
|
descriptor: TypedPropertyDescriptor<SyncMethod>,
|
||||||
) => {
|
) => {
|
||||||
const originalMethod = (descriptor.value as SyncMethod);
|
const originalMethod = descriptor.value as SyncMethod;
|
||||||
|
|
||||||
// Do not use arrow syntax here. Use a function expression in
|
// Do not use arrow syntax here. Use a function expression in
|
||||||
// order to use the correct value of `this` in this method
|
// order to use the correct value of `this` in this method
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import { BlockParamLiteral } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||||
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
|
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
||||||
import {BlockParamLiteral, ExchangeContractErrs, TradeSide, TransferType} from '../types';
|
import { ExchangeContractErrs, TradeSide, TransferType } from '../types';
|
||||||
|
|
||||||
enum FailureReason {
|
enum FailureReason {
|
||||||
Balance = 'balance',
|
Balance = 'balance',
|
||||||
@@ -36,8 +37,11 @@ const ERR_MSG_MAPPING = {
|
|||||||
export class ExchangeTransferSimulator {
|
export class ExchangeTransferSimulator {
|
||||||
private _store: BalanceAndProxyAllowanceLazyStore;
|
private _store: BalanceAndProxyAllowanceLazyStore;
|
||||||
private _UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
|
private _UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
|
||||||
private static _throwValidationError(failureReason: FailureReason, tradeSide: TradeSide,
|
private static _throwValidationError(
|
||||||
transferType: TransferType): never {
|
failureReason: FailureReason,
|
||||||
|
tradeSide: TradeSide,
|
||||||
|
transferType: TransferType,
|
||||||
|
): never {
|
||||||
const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType];
|
const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType];
|
||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
@@ -54,9 +58,14 @@ export class ExchangeTransferSimulator {
|
|||||||
* @param tradeSide Is Maker/Taker transferring
|
* @param tradeSide Is Maker/Taker transferring
|
||||||
* @param transferType Is it a fee payment or a value transfer
|
* @param transferType Is it a fee payment or a value transfer
|
||||||
*/
|
*/
|
||||||
public async transferFromAsync(tokenAddress: string, from: string, to: string,
|
public async transferFromAsync(
|
||||||
amountInBaseUnits: BigNumber, tradeSide: TradeSide,
|
tokenAddress: string,
|
||||||
transferType: TransferType): Promise<void> {
|
from: string,
|
||||||
|
to: string,
|
||||||
|
amountInBaseUnits: BigNumber,
|
||||||
|
tradeSide: TradeSide,
|
||||||
|
transferType: TransferType,
|
||||||
|
): Promise<void> {
|
||||||
const balance = await this._store.getBalanceAsync(tokenAddress, from);
|
const balance = await this._store.getBalanceAsync(tokenAddress, from);
|
||||||
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from);
|
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from);
|
||||||
if (proxyAllowance.lessThan(amountInBaseUnits)) {
|
if (proxyAllowance.lessThan(amountInBaseUnits)) {
|
||||||
@@ -69,20 +78,29 @@ export class ExchangeTransferSimulator {
|
|||||||
await this._decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits);
|
await this._decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits);
|
||||||
await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
|
await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
|
||||||
}
|
}
|
||||||
private async _decreaseProxyAllowanceAsync(tokenAddress: string, userAddress: string,
|
private async _decreaseProxyAllowanceAsync(
|
||||||
amountInBaseUnits: BigNumber): Promise<void> {
|
tokenAddress: string,
|
||||||
|
userAddress: string,
|
||||||
|
amountInBaseUnits: BigNumber,
|
||||||
|
): Promise<void> {
|
||||||
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress);
|
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress);
|
||||||
if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
|
if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
|
||||||
this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits));
|
this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async _increaseBalanceAsync(tokenAddress: string, userAddress: string,
|
private async _increaseBalanceAsync(
|
||||||
amountInBaseUnits: BigNumber): Promise<void> {
|
tokenAddress: string,
|
||||||
|
userAddress: string,
|
||||||
|
amountInBaseUnits: BigNumber,
|
||||||
|
): Promise<void> {
|
||||||
const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
|
const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
|
||||||
this._store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits));
|
this._store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits));
|
||||||
}
|
}
|
||||||
private async _decreaseBalanceAsync(tokenAddress: string, userAddress: string,
|
private async _decreaseBalanceAsync(
|
||||||
amountInBaseUnits: BigNumber): Promise<void> {
|
tokenAddress: string,
|
||||||
|
userAddress: string,
|
||||||
|
amountInBaseUnits: BigNumber,
|
||||||
|
): Promise<void> {
|
||||||
const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
|
const balance = await this._store.getBalanceAsync(tokenAddress, userAddress);
|
||||||
this._store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits));
|
this._store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
|
import {
|
||||||
|
ConstructorAbi,
|
||||||
|
ContractAbi,
|
||||||
|
EventAbi,
|
||||||
|
FallbackAbi,
|
||||||
|
FilterObject,
|
||||||
|
LogEntry,
|
||||||
|
MethodAbi,
|
||||||
|
} from '@0xproject/types';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
import * as jsSHA3 from 'js-sha3';
|
import * as jsSHA3 from 'js-sha3';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as uuid from 'uuid/v4';
|
import * as uuid from 'uuid/v4';
|
||||||
import * as Web3 from 'web3';
|
|
||||||
|
|
||||||
import {BlockRange, ContractEvents, IndexedFilterValues} from '../types';
|
import { BlockRange, ContractEvents, IndexedFilterValues } from '../types';
|
||||||
|
|
||||||
const TOPIC_LENGTH = 32;
|
const TOPIC_LENGTH = 32;
|
||||||
|
|
||||||
@@ -12,15 +20,19 @@ export const filterUtils = {
|
|||||||
generateUUID(): string {
|
generateUUID(): string {
|
||||||
return uuid();
|
return uuid();
|
||||||
},
|
},
|
||||||
getFilter(address: string, eventName: ContractEvents,
|
getFilter(
|
||||||
indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi,
|
address: string,
|
||||||
blockRange?: BlockRange): Web3.FilterObject {
|
eventName: ContractEvents,
|
||||||
const eventAbi = _.find(abi, {name: eventName}) as Web3.EventAbi;
|
indexFilterValues: IndexedFilterValues,
|
||||||
|
abi: ContractAbi,
|
||||||
|
blockRange?: BlockRange,
|
||||||
|
): FilterObject {
|
||||||
|
const eventAbi = _.find(abi, { name: eventName }) as EventAbi;
|
||||||
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi, eventName);
|
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi, eventName);
|
||||||
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
|
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
|
||||||
const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
|
const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
|
||||||
const topics = [topicForEventSignature, ...topicsForIndexedArgs];
|
const topics = [topicForEventSignature, ...topicsForIndexedArgs];
|
||||||
let filter: Web3.FilterObject = {
|
let filter: FilterObject = {
|
||||||
address,
|
address,
|
||||||
topics,
|
topics,
|
||||||
};
|
};
|
||||||
@@ -32,13 +44,13 @@ export const filterUtils = {
|
|||||||
}
|
}
|
||||||
return filter;
|
return filter;
|
||||||
},
|
},
|
||||||
getEventSignatureFromAbiByName(eventAbi: Web3.EventAbi, eventName: ContractEvents): string {
|
getEventSignatureFromAbiByName(eventAbi: EventAbi, eventName: ContractEvents): string {
|
||||||
const types = _.map(eventAbi.inputs, 'type');
|
const types = _.map(eventAbi.inputs, 'type');
|
||||||
const signature = `${eventAbi.name}(${types.join(',')})`;
|
const signature = `${eventAbi.name}(${types.join(',')})`;
|
||||||
return signature;
|
return signature;
|
||||||
},
|
},
|
||||||
getTopicsForIndexedArgs(abi: Web3.EventAbi, indexFilterValues: IndexedFilterValues): Array<string|null> {
|
getTopicsForIndexedArgs(abi: EventAbi, indexFilterValues: IndexedFilterValues): Array<string | null> {
|
||||||
const topics: Array<string|null> = [];
|
const topics: Array<string | null> = [];
|
||||||
for (const eventInput of abi.inputs) {
|
for (const eventInput of abi.inputs) {
|
||||||
if (!eventInput.indexed) {
|
if (!eventInput.indexed) {
|
||||||
continue;
|
continue;
|
||||||
@@ -56,7 +68,7 @@ export const filterUtils = {
|
|||||||
}
|
}
|
||||||
return topics;
|
return topics;
|
||||||
},
|
},
|
||||||
matchesFilter(log: Web3.LogEntry, filter: Web3.FilterObject): boolean {
|
matchesFilter(log: LogEntry, filter: FilterObject): boolean {
|
||||||
if (!_.isUndefined(filter.address) && log.address !== filter.address) {
|
if (!_.isUndefined(filter.address) && log.address !== filter.address) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -65,12 +77,12 @@ export const filterUtils = {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
matchesTopics(logTopics: string[], filterTopics: Array<string[]|string|null>): boolean {
|
matchesTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean {
|
||||||
const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils));
|
const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils));
|
||||||
const matchesTopics = _.every(matchesTopic);
|
const matchesTopics = _.every(matchesTopic);
|
||||||
return matchesTopics;
|
return matchesTopics;
|
||||||
},
|
},
|
||||||
matchesTopic(logTopic: string, filterTopic: string[]|string|null): boolean {
|
matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean {
|
||||||
if (_.isArray(filterTopic)) {
|
if (_.isArray(filterTopic)) {
|
||||||
return _.includes(filterTopic, logTopic);
|
return _.includes(filterTopic, logTopic);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import { SignedOrder } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {ZeroEx} from '../0x';
|
import { ZeroEx } from '../0x';
|
||||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||||
import {RemainingFillableCalculator} from '../order_watcher/remaining_fillable_calculator';
|
import { RemainingFillableCalculator } from '../order_watcher/remaining_fillable_calculator';
|
||||||
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
|
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
|
||||||
import {OrderFilledCancelledLazyStore} from '../stores/order_filled_cancelled_lazy_store';
|
import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
|
||||||
import {
|
import { ExchangeContractErrs, OrderRelevantState, OrderState, OrderStateInvalid, OrderStateValid } from '../types';
|
||||||
ExchangeContractErrs,
|
|
||||||
OrderRelevantState,
|
|
||||||
OrderState,
|
|
||||||
OrderStateInvalid,
|
|
||||||
OrderStateValid,
|
|
||||||
SignedOrder,
|
|
||||||
} from '../types';
|
|
||||||
|
|
||||||
const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
|
const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
|
||||||
|
|
||||||
@@ -44,15 +38,20 @@ export class OrderStateUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const minFillableTakerTokenAmountWithinNoRoundingErrorRange = signedOrder.takerTokenAmount
|
const minFillableTakerTokenAmountWithinNoRoundingErrorRange = signedOrder.takerTokenAmount
|
||||||
.dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
|
.dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
|
||||||
.dividedBy(signedOrder.makerTokenAmount);
|
.dividedBy(signedOrder.makerTokenAmount);
|
||||||
if (orderRelevantState.remainingFillableTakerTokenAmount
|
if (
|
||||||
.lessThan(minFillableTakerTokenAmountWithinNoRoundingErrorRange)) {
|
orderRelevantState.remainingFillableTakerTokenAmount.lessThan(
|
||||||
|
minFillableTakerTokenAmountWithinNoRoundingErrorRange,
|
||||||
|
)
|
||||||
|
) {
|
||||||
throw new Error(ExchangeContractErrs.OrderFillRoundingError);
|
throw new Error(ExchangeContractErrs.OrderFillRoundingError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
constructor(balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore,
|
constructor(
|
||||||
orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore) {
|
balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore,
|
||||||
|
orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore,
|
||||||
|
) {
|
||||||
this._balanceAndProxyAllowanceLazyStore = balanceAndProxyAllowanceLazyStore;
|
this._balanceAndProxyAllowanceLazyStore = balanceAndProxyAllowanceLazyStore;
|
||||||
this._orderFilledCancelledLazyStore = orderFilledCancelledLazyStore;
|
this._orderFilledCancelledLazyStore = orderFilledCancelledLazyStore;
|
||||||
}
|
}
|
||||||
@@ -85,16 +84,20 @@ export class OrderStateUtils {
|
|||||||
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
const makerBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
|
const makerBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
|
||||||
signedOrder.makerTokenAddress, signedOrder.maker,
|
signedOrder.makerTokenAddress,
|
||||||
|
signedOrder.maker,
|
||||||
);
|
);
|
||||||
const makerProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
|
const makerProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
|
||||||
signedOrder.makerTokenAddress, signedOrder.maker,
|
signedOrder.makerTokenAddress,
|
||||||
|
signedOrder.maker,
|
||||||
);
|
);
|
||||||
const makerFeeBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
|
const makerFeeBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
|
||||||
zrxTokenAddress, signedOrder.maker,
|
zrxTokenAddress,
|
||||||
|
signedOrder.maker,
|
||||||
);
|
);
|
||||||
const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
|
const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
|
||||||
zrxTokenAddress, signedOrder.maker,
|
zrxTokenAddress,
|
||||||
|
signedOrder.maker,
|
||||||
);
|
);
|
||||||
const filledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getFilledTakerAmountAsync(orderHash);
|
const filledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getFilledTakerAmountAsync(orderHash);
|
||||||
const cancelledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getCancelledTakerAmountAsync(
|
const cancelledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getCancelledTakerAmountAsync(
|
||||||
@@ -104,17 +107,20 @@ export class OrderStateUtils {
|
|||||||
const totalMakerTokenAmount = signedOrder.makerTokenAmount;
|
const totalMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||||
const totalTakerTokenAmount = signedOrder.takerTokenAmount;
|
const totalTakerTokenAmount = signedOrder.takerTokenAmount;
|
||||||
const remainingTakerTokenAmount = totalTakerTokenAmount.minus(unavailableTakerTokenAmount);
|
const remainingTakerTokenAmount = totalTakerTokenAmount.minus(unavailableTakerTokenAmount);
|
||||||
const remainingMakerTokenAmount = remainingTakerTokenAmount.times(totalMakerTokenAmount)
|
const remainingMakerTokenAmount = remainingTakerTokenAmount
|
||||||
.dividedToIntegerBy(totalTakerTokenAmount);
|
.times(totalMakerTokenAmount)
|
||||||
|
.dividedToIntegerBy(totalTakerTokenAmount);
|
||||||
const transferrableMakerTokenAmount = BigNumber.min([makerProxyAllowance, makerBalance]);
|
const transferrableMakerTokenAmount = BigNumber.min([makerProxyAllowance, makerBalance]);
|
||||||
const transferrableFeeTokenAmount = BigNumber.min([makerFeeProxyAllowance, makerFeeBalance]);
|
const transferrableFeeTokenAmount = BigNumber.min([makerFeeProxyAllowance, makerFeeBalance]);
|
||||||
|
|
||||||
const isMakerTokenZRX = signedOrder.makerTokenAddress === zrxTokenAddress;
|
const isMakerTokenZRX = signedOrder.makerTokenAddress === zrxTokenAddress;
|
||||||
const remainingFillableCalculator = new RemainingFillableCalculator(signedOrder,
|
const remainingFillableCalculator = new RemainingFillableCalculator(
|
||||||
isMakerTokenZRX,
|
signedOrder,
|
||||||
transferrableMakerTokenAmount,
|
isMakerTokenZRX,
|
||||||
transferrableFeeTokenAmount,
|
transferrableMakerTokenAmount,
|
||||||
remainingMakerTokenAmount);
|
transferrableFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
const remainingFillableMakerTokenAmount = remainingFillableCalculator.computeRemainingMakerFillable();
|
const remainingFillableMakerTokenAmount = remainingFillableCalculator.computeRemainingMakerFillable();
|
||||||
const remainingFillableTakerTokenAmount = remainingFillableCalculator.computeRemainingTakerFillable();
|
const remainingFillableTakerTokenAmount = remainingFillableCalculator.computeRemainingTakerFillable();
|
||||||
const orderRelevantState = {
|
const orderRelevantState = {
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import { Order, SignedOrder } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {ZeroEx} from '../0x';
|
import { ZeroEx } from '../0x';
|
||||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||||
import {ExchangeContractErrs, Order, SignedOrder, TradeSide, TransferType, ZeroExError} from '../types';
|
import { ExchangeContractErrs, TradeSide, TransferType, ZeroExError } from '../types';
|
||||||
import {constants} from '../utils/constants';
|
import { constants } from '../utils/constants';
|
||||||
import {utils} from '../utils/utils';
|
import { utils } from '../utils/utils';
|
||||||
|
|
||||||
import {ExchangeTransferSimulator} from './exchange_transfer_simulator';
|
import { ExchangeTransferSimulator } from './exchange_transfer_simulator';
|
||||||
|
|
||||||
export class OrderValidationUtils {
|
export class OrderValidationUtils {
|
||||||
private _exchangeWrapper: ExchangeWrapper;
|
private _exchangeWrapper: ExchangeWrapper;
|
||||||
public static validateCancelOrderThrowIfInvalid(
|
public static validateCancelOrderThrowIfInvalid(
|
||||||
order: Order, cancelTakerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
|
order: Order,
|
||||||
|
cancelTakerTokenAmount: BigNumber,
|
||||||
|
unavailableTakerTokenAmount: BigNumber,
|
||||||
): void {
|
): void {
|
||||||
if (cancelTakerTokenAmount.eq(0)) {
|
if (cancelTakerTokenAmount.eq(0)) {
|
||||||
throw new Error(ExchangeContractErrs.OrderCancelAmountZero);
|
throw new Error(ExchangeContractErrs.OrderCancelAmountZero);
|
||||||
@@ -26,8 +29,11 @@ export class OrderValidationUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
|
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||||
fillTakerTokenAmount: BigNumber, senderAddress: string, zrxTokenAddress: string,
|
signedOrder: SignedOrder,
|
||||||
|
fillTakerTokenAmount: BigNumber,
|
||||||
|
senderAddress: string,
|
||||||
|
zrxTokenAddress: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
|
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
|
||||||
fillTakerTokenAmount,
|
fillTakerTokenAmount,
|
||||||
@@ -35,12 +41,20 @@ export class OrderValidationUtils {
|
|||||||
signedOrder.makerTokenAmount,
|
signedOrder.makerTokenAmount,
|
||||||
);
|
);
|
||||||
await exchangeTradeEmulator.transferFromAsync(
|
await exchangeTradeEmulator.transferFromAsync(
|
||||||
signedOrder.makerTokenAddress, signedOrder.maker, senderAddress, fillMakerTokenAmount,
|
signedOrder.makerTokenAddress,
|
||||||
TradeSide.Maker, TransferType.Trade,
|
signedOrder.maker,
|
||||||
|
senderAddress,
|
||||||
|
fillMakerTokenAmount,
|
||||||
|
TradeSide.Maker,
|
||||||
|
TransferType.Trade,
|
||||||
);
|
);
|
||||||
await exchangeTradeEmulator.transferFromAsync(
|
await exchangeTradeEmulator.transferFromAsync(
|
||||||
signedOrder.takerTokenAddress, senderAddress, signedOrder.maker, fillTakerTokenAmount,
|
signedOrder.takerTokenAddress,
|
||||||
TradeSide.Taker, TransferType.Trade,
|
senderAddress,
|
||||||
|
signedOrder.maker,
|
||||||
|
fillTakerTokenAmount,
|
||||||
|
TradeSide.Taker,
|
||||||
|
TransferType.Trade,
|
||||||
);
|
);
|
||||||
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||||
fillTakerTokenAmount,
|
fillTakerTokenAmount,
|
||||||
@@ -48,7 +62,11 @@ export class OrderValidationUtils {
|
|||||||
signedOrder.makerFee,
|
signedOrder.makerFee,
|
||||||
);
|
);
|
||||||
await exchangeTradeEmulator.transferFromAsync(
|
await exchangeTradeEmulator.transferFromAsync(
|
||||||
zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount, TradeSide.Maker,
|
zrxTokenAddress,
|
||||||
|
signedOrder.maker,
|
||||||
|
signedOrder.feeRecipient,
|
||||||
|
makerFeeAmount,
|
||||||
|
TradeSide.Maker,
|
||||||
TransferType.Fee,
|
TransferType.Fee,
|
||||||
);
|
);
|
||||||
const takerFeeAmount = OrderValidationUtils._getPartialAmount(
|
const takerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||||
@@ -57,12 +75,17 @@ export class OrderValidationUtils {
|
|||||||
signedOrder.takerFee,
|
signedOrder.takerFee,
|
||||||
);
|
);
|
||||||
await exchangeTradeEmulator.transferFromAsync(
|
await exchangeTradeEmulator.transferFromAsync(
|
||||||
zrxTokenAddress, senderAddress, signedOrder.feeRecipient, takerFeeAmount, TradeSide.Taker,
|
zrxTokenAddress,
|
||||||
|
senderAddress,
|
||||||
|
signedOrder.feeRecipient,
|
||||||
|
takerFeeAmount,
|
||||||
|
TradeSide.Taker,
|
||||||
TransferType.Fee,
|
TransferType.Fee,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
private static _validateRemainingFillAmountNotZeroOrThrow(
|
private static _validateRemainingFillAmountNotZeroOrThrow(
|
||||||
takerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
|
takerTokenAmount: BigNumber,
|
||||||
|
unavailableTakerTokenAmount: BigNumber,
|
||||||
) {
|
) {
|
||||||
if (takerTokenAmount.eq(unavailableTakerTokenAmount)) {
|
if (takerTokenAmount.eq(unavailableTakerTokenAmount)) {
|
||||||
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||||
@@ -74,24 +97,27 @@ export class OrderValidationUtils {
|
|||||||
throw new Error(ExchangeContractErrs.OrderFillExpired);
|
throw new Error(ExchangeContractErrs.OrderFillExpired);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static _getPartialAmount(numerator: BigNumber, denominator: BigNumber,
|
private static _getPartialAmount(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
|
||||||
target: BigNumber): BigNumber {
|
|
||||||
const fillMakerTokenAmount = numerator
|
const fillMakerTokenAmount = numerator
|
||||||
.mul(target)
|
.mul(target)
|
||||||
.div(denominator)
|
.div(denominator)
|
||||||
.round(0);
|
.round(0);
|
||||||
return fillMakerTokenAmount;
|
return fillMakerTokenAmount;
|
||||||
}
|
}
|
||||||
constructor(exchangeWrapper: ExchangeWrapper) {
|
constructor(exchangeWrapper: ExchangeWrapper) {
|
||||||
this._exchangeWrapper = exchangeWrapper;
|
this._exchangeWrapper = exchangeWrapper;
|
||||||
}
|
}
|
||||||
public async validateOrderFillableOrThrowAsync(
|
public async validateOrderFillableOrThrowAsync(
|
||||||
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder, zrxTokenAddress: string,
|
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||||
expectedFillTakerTokenAmount?: BigNumber): Promise<void> {
|
signedOrder: SignedOrder,
|
||||||
|
zrxTokenAddress: string,
|
||||||
|
expectedFillTakerTokenAmount?: BigNumber,
|
||||||
|
): Promise<void> {
|
||||||
const orderHash = utils.getOrderHashHex(signedOrder);
|
const orderHash = utils.getOrderHashHex(signedOrder);
|
||||||
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||||
signedOrder.takerTokenAmount, unavailableTakerTokenAmount,
|
signedOrder.takerTokenAmount,
|
||||||
|
unavailableTakerTokenAmount,
|
||||||
);
|
);
|
||||||
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
|
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
|
||||||
let fillTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
|
let fillTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
|
||||||
@@ -104,8 +130,12 @@ export class OrderValidationUtils {
|
|||||||
signedOrder.makerTokenAmount,
|
signedOrder.makerTokenAmount,
|
||||||
);
|
);
|
||||||
await exchangeTradeEmulator.transferFromAsync(
|
await exchangeTradeEmulator.transferFromAsync(
|
||||||
signedOrder.makerTokenAddress, signedOrder.maker, signedOrder.taker, fillMakerTokenAmount,
|
signedOrder.makerTokenAddress,
|
||||||
TradeSide.Maker, TransferType.Trade,
|
signedOrder.maker,
|
||||||
|
signedOrder.taker,
|
||||||
|
fillMakerTokenAmount,
|
||||||
|
TradeSide.Maker,
|
||||||
|
TransferType.Trade,
|
||||||
);
|
);
|
||||||
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||||
fillTakerTokenAmount,
|
fillTakerTokenAmount,
|
||||||
@@ -113,14 +143,21 @@ export class OrderValidationUtils {
|
|||||||
signedOrder.makerFee,
|
signedOrder.makerFee,
|
||||||
);
|
);
|
||||||
await exchangeTradeEmulator.transferFromAsync(
|
await exchangeTradeEmulator.transferFromAsync(
|
||||||
zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount,
|
zrxTokenAddress,
|
||||||
TradeSide.Maker, TransferType.Fee,
|
signedOrder.maker,
|
||||||
|
signedOrder.feeRecipient,
|
||||||
|
makerFeeAmount,
|
||||||
|
TradeSide.Maker,
|
||||||
|
TransferType.Fee,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public async validateFillOrderThrowIfInvalidAsync(
|
public async validateFillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
|
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||||
fillTakerTokenAmount: BigNumber, takerAddress: string,
|
signedOrder: SignedOrder,
|
||||||
zrxTokenAddress: string): Promise<BigNumber> {
|
fillTakerTokenAmount: BigNumber,
|
||||||
|
takerAddress: string,
|
||||||
|
zrxTokenAddress: string,
|
||||||
|
): Promise<BigNumber> {
|
||||||
if (fillTakerTokenAmount.eq(0)) {
|
if (fillTakerTokenAmount.eq(0)) {
|
||||||
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
|
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
|
||||||
}
|
}
|
||||||
@@ -130,22 +167,29 @@ export class OrderValidationUtils {
|
|||||||
}
|
}
|
||||||
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||||
signedOrder.takerTokenAmount, unavailableTakerTokenAmount,
|
signedOrder.takerTokenAmount,
|
||||||
|
unavailableTakerTokenAmount,
|
||||||
);
|
);
|
||||||
if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== takerAddress) {
|
if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== takerAddress) {
|
||||||
throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
|
throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
|
||||||
}
|
}
|
||||||
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
|
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
|
||||||
const remainingTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
|
const remainingTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
|
||||||
const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount) ?
|
const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount)
|
||||||
remainingTakerTokenAmount :
|
? remainingTakerTokenAmount
|
||||||
fillTakerTokenAmount;
|
: fillTakerTokenAmount;
|
||||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, signedOrder, filledTakerTokenAmount, takerAddress, zrxTokenAddress,
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
|
filledTakerTokenAmount,
|
||||||
|
takerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
);
|
);
|
||||||
|
|
||||||
const wouldRoundingErrorOccur = await this._exchangeWrapper.isRoundingErrorAsync(
|
const wouldRoundingErrorOccur = await this._exchangeWrapper.isRoundingErrorAsync(
|
||||||
filledTakerTokenAmount, signedOrder.takerTokenAmount, signedOrder.makerTokenAmount,
|
filledTakerTokenAmount,
|
||||||
|
signedOrder.takerTokenAmount,
|
||||||
|
signedOrder.makerTokenAmount,
|
||||||
);
|
);
|
||||||
if (wouldRoundingErrorOccur) {
|
if (wouldRoundingErrorOccur) {
|
||||||
throw new Error(ExchangeContractErrs.OrderFillRoundingError);
|
throw new Error(ExchangeContractErrs.OrderFillRoundingError);
|
||||||
@@ -153,10 +197,18 @@ export class OrderValidationUtils {
|
|||||||
return filledTakerTokenAmount;
|
return filledTakerTokenAmount;
|
||||||
}
|
}
|
||||||
public async validateFillOrKillOrderThrowIfInvalidAsync(
|
public async validateFillOrKillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
|
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||||
fillTakerTokenAmount: BigNumber, takerAddress: string, zrxTokenAddress: string): Promise<void> {
|
signedOrder: SignedOrder,
|
||||||
|
fillTakerTokenAmount: BigNumber,
|
||||||
|
takerAddress: string,
|
||||||
|
zrxTokenAddress: string,
|
||||||
|
): Promise<void> {
|
||||||
const filledTakerTokenAmount = await this.validateFillOrderThrowIfInvalidAsync(
|
const filledTakerTokenAmount = await this.validateFillOrderThrowIfInvalidAsync(
|
||||||
exchangeTradeEmulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress,
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
|
fillTakerTokenAmount,
|
||||||
|
takerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
);
|
);
|
||||||
if (filledTakerTokenAmount !== fillTakerTokenAmount) {
|
if (filledTakerTokenAmount !== fillTakerTokenAmount) {
|
||||||
throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
import { ECSignature } from '@0xproject/types';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
|
|
||||||
import {ECSignature} from '../types';
|
|
||||||
|
|
||||||
export const signatureUtils = {
|
export const signatureUtils = {
|
||||||
isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
||||||
const dataBuff = ethUtil.toBuffer(data);
|
const dataBuff = ethUtil.toBuffer(data);
|
||||||
@@ -11,7 +10,8 @@ export const signatureUtils = {
|
|||||||
msgHashBuff,
|
msgHashBuff,
|
||||||
signature.v,
|
signature.v,
|
||||||
ethUtil.toBuffer(signature.r),
|
ethUtil.toBuffer(signature.r),
|
||||||
ethUtil.toBuffer(signature.s));
|
ethUtil.toBuffer(signature.s),
|
||||||
|
);
|
||||||
const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
|
const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
|
||||||
return retrievedAddress === signerAddress;
|
return retrievedAddress === signerAddress;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -34,7 +34,7 @@ export const signatureUtils = {
|
|||||||
return ecSignature;
|
return ecSignature;
|
||||||
},
|
},
|
||||||
parseSignatureHexAsRSV(signatureHex: string): ECSignature {
|
parseSignatureHexAsRSV(signatureHex: string): ECSignature {
|
||||||
const {v, r, s} = ethUtil.fromRpcSig(signatureHex);
|
const { v, r, s } = ethUtil.fromRpcSig(signatureHex);
|
||||||
const ecSignature: ECSignature = {
|
const ecSignature: ECSignature = {
|
||||||
v,
|
v,
|
||||||
r: ethUtil.bufferToHex(r),
|
r: ethUtil.bufferToHex(r),
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import { Order, SignedOrder, SolidityTypes } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import BN = require('bn.js');
|
import BN = require('bn.js');
|
||||||
import * as ethABI from 'ethereumjs-abi';
|
import * as ethABI from 'ethereumjs-abi';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {Order, SignedOrder, SolidityTypes} from '../types';
|
|
||||||
|
|
||||||
export const utils = {
|
export const utils = {
|
||||||
/**
|
/**
|
||||||
* Converts BigNumber instance to BN
|
* Converts BigNumber instance to BN
|
||||||
@@ -16,33 +15,38 @@ export const utils = {
|
|||||||
bigNumberToBN(value: BigNumber) {
|
bigNumberToBN(value: BigNumber) {
|
||||||
return new BN(value.toString(), 10);
|
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 {
|
spawnSwitchErr(name: string, value: any): Error {
|
||||||
return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
|
return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
|
||||||
},
|
},
|
||||||
getOrderHashHex(order: Order|SignedOrder): string {
|
getOrderHashHex(order: Order | SignedOrder): string {
|
||||||
const orderParts = [
|
const orderParts = [
|
||||||
{value: order.exchangeContractAddress, type: SolidityTypes.Address},
|
{ value: order.exchangeContractAddress, type: SolidityTypes.Address },
|
||||||
{value: order.maker, type: SolidityTypes.Address},
|
{ value: order.maker, type: SolidityTypes.Address },
|
||||||
{value: order.taker, type: SolidityTypes.Address},
|
{ value: order.taker, type: SolidityTypes.Address },
|
||||||
{value: order.makerTokenAddress, type: SolidityTypes.Address},
|
{ value: order.makerTokenAddress, type: SolidityTypes.Address },
|
||||||
{value: order.takerTokenAddress, type: SolidityTypes.Address},
|
{ value: order.takerTokenAddress, type: SolidityTypes.Address },
|
||||||
{value: order.feeRecipient, 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.makerTokenAmount),
|
||||||
{value: utils.bigNumberToBN(order.makerFee), type: SolidityTypes.Uint256},
|
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},
|
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 types = _.map(orderParts, o => o.type);
|
||||||
const values = _.map(orderParts, o => o.value);
|
const values = _.map(orderParts, o => o.value);
|
||||||
|
|||||||
@@ -1,23 +1,24 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
import * as Sinon from 'sinon';
|
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 { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {TokenUtils} from './utils/token_utils';
|
import { TokenUtils } from './utils/token_utils';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
|
||||||
|
|
||||||
describe('ZeroEx library', () => {
|
describe('ZeroEx library', () => {
|
||||||
const web3 = web3Factory.create();
|
|
||||||
const config = {
|
const config = {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
@@ -40,12 +41,12 @@ describe('ZeroEx library', () => {
|
|||||||
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
|
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
|
||||||
|
|
||||||
// Check that all nested web3 wrapper instances return the updated provider
|
// Check that all nested web3 wrapper instances return the updated provider
|
||||||
const nestedWeb3WrapperProvider = (zeroEx as any)._web3Wrapper.getCurrentProvider();
|
const nestedWeb3WrapperProvider = (zeroEx as any)._web3Wrapper.getProvider();
|
||||||
expect((nestedWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
expect(nestedWeb3WrapperProvider.zeroExTestId).to.be.a('number');
|
||||||
const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getCurrentProvider();
|
const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getProvider();
|
||||||
expect((exchangeWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
expect(exchangeWeb3WrapperProvider.zeroExTestId).to.be.a('number');
|
||||||
const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getCurrentProvider();
|
const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getProvider();
|
||||||
expect((tokenRegistryWeb3WrapperProvider).zeroExTestId).to.be.a('number');
|
expect(tokenRegistryWeb3WrapperProvider.zeroExTestId).to.be.a('number');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#isValidSignature', () => {
|
describe('#isValidSignature', () => {
|
||||||
@@ -58,22 +59,25 @@ describe('ZeroEx library', () => {
|
|||||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||||
};
|
};
|
||||||
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||||
it('should return false if the data doesn\'t pertain to the signature & address', async () => {
|
it("should return false if the data doesn't pertain to the signature & address", async () => {
|
||||||
expect(ZeroEx.isValidSignature('0x0', signature, address)).to.be.false();
|
expect(ZeroEx.isValidSignature('0x0', signature, address)).to.be.false();
|
||||||
return expect(
|
return expect(
|
||||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
|
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
|
||||||
).to.become(false);
|
).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';
|
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
|
||||||
expect(ZeroEx.isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
|
expect(ZeroEx.isValidSignature(dataHex, signature, validUnrelatedAddress)).to.be.false();
|
||||||
return expect(
|
return expect(
|
||||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature,
|
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
|
||||||
validUnrelatedAddress),
|
dataHex,
|
||||||
|
signature,
|
||||||
|
validUnrelatedAddress,
|
||||||
|
),
|
||||||
).to.become(false);
|
).to.become(false);
|
||||||
});
|
});
|
||||||
it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => {
|
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
|
||||||
const wrongSignature = _.assign({}, signature, {v: 28});
|
const wrongSignature = _.assign({}, signature, { v: 28 });
|
||||||
expect(ZeroEx.isValidSignature(dataHex, wrongSignature, address)).to.be.false();
|
expect(ZeroEx.isValidSignature(dataHex, wrongSignature, address)).to.be.false();
|
||||||
return expect(
|
return expect(
|
||||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
|
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
|
||||||
@@ -117,8 +121,9 @@ describe('ZeroEx library', () => {
|
|||||||
it('should throw if invalid baseUnit amount supplied as argument', () => {
|
it('should throw if invalid baseUnit amount supplied as argument', () => {
|
||||||
const invalidBaseUnitAmount = new BigNumber(1000000000.4);
|
const invalidBaseUnitAmount = new BigNumber(1000000000.4);
|
||||||
const decimals = 6;
|
const decimals = 6;
|
||||||
expect(() => ZeroEx.toUnitAmount(invalidBaseUnitAmount, decimals))
|
expect(() => ZeroEx.toUnitAmount(invalidBaseUnitAmount, decimals)).to.throw(
|
||||||
.to.throw('amount should be in baseUnits (no decimals), found value: 1000000000.4');
|
'amount should be in baseUnits (no decimals), found value: 1000000000.4',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
it('Should return the expected unit amount for the decimals passed in', () => {
|
it('Should return the expected unit amount for the decimals passed in', () => {
|
||||||
const baseUnitAmount = new BigNumber(1000000000);
|
const baseUnitAmount = new BigNumber(1000000000);
|
||||||
@@ -139,8 +144,9 @@ describe('ZeroEx library', () => {
|
|||||||
it('should throw if unitAmount has more decimals then specified as the max decimal precision', () => {
|
it('should throw if unitAmount has more decimals then specified as the max decimal precision', () => {
|
||||||
const unitAmount = new BigNumber(0.823091);
|
const unitAmount = new BigNumber(0.823091);
|
||||||
const decimals = 5;
|
const decimals = 5;
|
||||||
expect(() => ZeroEx.toBaseUnitAmount(unitAmount, decimals))
|
expect(() => ZeroEx.toBaseUnitAmount(unitAmount, decimals)).to.throw(
|
||||||
.to.throw('Invalid unit amount: 0.823091 - Too many decimal places');
|
'Invalid unit amount: 0.823091 - Too many decimal places',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getOrderHashHex', () => {
|
describe('#getOrderHashHex', () => {
|
||||||
@@ -167,10 +173,10 @@ describe('ZeroEx library', () => {
|
|||||||
it('throws a readable error message if taker format is invalid', async () => {
|
it('throws a readable error message if taker format is invalid', async () => {
|
||||||
const orderWithInvalidtakerFormat = {
|
const orderWithInvalidtakerFormat = {
|
||||||
...order,
|
...order,
|
||||||
taker: null as any as string,
|
taker: (null as any) as string,
|
||||||
};
|
};
|
||||||
// tslint:disable-next-line:max-line-length
|
const expectedErrorMessage =
|
||||||
const expectedErrorMessage = 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
'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);
|
expect(() => ZeroEx.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -193,43 +199,53 @@ describe('ZeroEx library', () => {
|
|||||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
||||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
||||||
};
|
};
|
||||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
|
const ecSignature = await zeroEx.signOrderHashAsync(
|
||||||
|
orderHash,
|
||||||
|
makerAddress,
|
||||||
|
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||||
|
);
|
||||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||||
});
|
});
|
||||||
it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
|
it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
|
||||||
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
|
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
|
||||||
// tslint:disable-next-line: max-line-length
|
const signature =
|
||||||
const signature = '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
|
'0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
|
||||||
const expectedECSignature = {
|
const expectedECSignature = {
|
||||||
v: 27,
|
v: 27,
|
||||||
r: '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3',
|
r: '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3',
|
||||||
s: '0x050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb02',
|
s: '0x050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb02',
|
||||||
};
|
};
|
||||||
stubs = [
|
stubs = [
|
||||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync')
|
Sinon.stub((zeroEx as any)._web3Wrapper, 'signMessageAsync').returns(Promise.resolve(signature)),
|
||||||
.returns(Promise.resolve(signature)),
|
|
||||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
||||||
];
|
];
|
||||||
|
|
||||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
|
const ecSignature = await zeroEx.signOrderHashAsync(
|
||||||
|
orderHash,
|
||||||
|
makerAddress,
|
||||||
|
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||||
|
);
|
||||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||||
});
|
});
|
||||||
it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
|
it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
|
||||||
const orderHash = '0xc793e33ffded933b76f2f48d9aa3339fc090399d5e7f5dec8d3660f5480793f7';
|
const orderHash = '0xc793e33ffded933b76f2f48d9aa3339fc090399d5e7f5dec8d3660f5480793f7';
|
||||||
// tslint:disable-next-line: max-line-length
|
const signature =
|
||||||
const signature = '0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
|
'0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
|
||||||
const expectedECSignature = {
|
const expectedECSignature = {
|
||||||
v: 27,
|
v: 27,
|
||||||
r: '0xc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee0',
|
r: '0xc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee0',
|
||||||
s: '0x2dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960',
|
s: '0x2dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960',
|
||||||
};
|
};
|
||||||
stubs = [
|
stubs = [
|
||||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signTransactionAsync')
|
Sinon.stub((zeroEx as any)._web3Wrapper, 'signMessageAsync').returns(Promise.resolve(signature)),
|
||||||
.returns(Promise.resolve(signature)),
|
|
||||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
||||||
];
|
];
|
||||||
|
|
||||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress);
|
const ecSignature = await zeroEx.signOrderHashAsync(
|
||||||
|
orderHash,
|
||||||
|
makerAddress,
|
||||||
|
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
||||||
|
);
|
||||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
expect(ecSignature).to.deep.equal(expectedECSignature);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -271,8 +287,9 @@ describe('ZeroEx library', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||||
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress())
|
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal(
|
||||||
.to.be.equal(ZeroEx.NULL_ADDRESS);
|
ZeroEx.NULL_ADDRESS,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import HDWalletProvider = require('truffle-hdwallet-provider');
|
import HDWalletProvider = require('truffle-hdwallet-provider');
|
||||||
|
|
||||||
import {ZeroEx} from '../src';
|
import { ZeroEx } from '../src';
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
import { web3Factory } from '@0xproject/dev-utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
|
||||||
import {ZeroEx} from '../src';
|
import { ZeroEx } from '../src';
|
||||||
import {assert} from '../src/utils/assert';
|
import { assert } from '../src/utils/assert';
|
||||||
|
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
|
||||||
|
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
@@ -19,22 +19,25 @@ describe('Assertion library', () => {
|
|||||||
it('throws when address is invalid', async () => {
|
it('throws when address is invalid', async () => {
|
||||||
const address = '0xdeadbeef';
|
const address = '0xdeadbeef';
|
||||||
const varName = 'address';
|
const varName = 'address';
|
||||||
return expect(assert.isSenderAddressAsync(varName, address, (zeroEx as any)._web3Wrapper))
|
return expect(
|
||||||
.to.be.rejectedWith(`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`);
|
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 () => {
|
it('throws when address is unavailable', async () => {
|
||||||
const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
|
const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
|
||||||
const varName = 'address';
|
const varName = 'address';
|
||||||
return expect(assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper))
|
return expect(
|
||||||
.to.be.rejectedWith(
|
assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper),
|
||||||
`Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
|
).to.be.rejectedWith(
|
||||||
);
|
`Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
it('doesn\'t throw if address is available', async () => {
|
it("doesn't throw if address is available", async () => {
|
||||||
const availableAddress = (await zeroEx.getAvailableAddressesAsync())[0];
|
const availableAddress = (await zeroEx.getAvailableAddressesAsync())[0];
|
||||||
const varName = 'address';
|
const varName = 'address';
|
||||||
return expect(assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper))
|
return expect(
|
||||||
.to.become(undefined);
|
assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper),
|
||||||
|
).to.become(undefined);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
@@ -17,17 +18,17 @@ import {
|
|||||||
ZeroEx,
|
ZeroEx,
|
||||||
ZeroExError,
|
ZeroExError,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
import {artifacts} from '../src/artifacts';
|
import { DoneCallback } from '../src/types';
|
||||||
import {DoneCallback} from '../src/types';
|
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {TokenUtils} from './utils/token_utils';
|
import { reportNodeCallbackErrors } from './utils/report_callback_errors';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { TokenUtils } from './utils/token_utils';
|
||||||
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
// Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction,
|
// 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
|
// a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between
|
||||||
@@ -36,7 +37,6 @@ const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
|||||||
const MAX_REASONABLE_GAS_COST_IN_WEI = 62517;
|
const MAX_REASONABLE_GAS_COST_IN_WEI = 62517;
|
||||||
|
|
||||||
describe('EtherTokenWrapper', () => {
|
describe('EtherTokenWrapper', () => {
|
||||||
let web3: Web3;
|
|
||||||
let zeroEx: ZeroEx;
|
let zeroEx: ZeroEx;
|
||||||
let tokens: Token[];
|
let tokens: Token[];
|
||||||
let userAddresses: string[];
|
let userAddresses: string[];
|
||||||
@@ -55,13 +55,12 @@ describe('EtherTokenWrapper', () => {
|
|||||||
const depositAmount = new BigNumber(42);
|
const depositAmount = new BigNumber(42);
|
||||||
const withdrawalAmount = new BigNumber(42);
|
const withdrawalAmount = new BigNumber(42);
|
||||||
before(async () => {
|
before(async () => {
|
||||||
web3 = web3Factory.create();
|
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
|
zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
addressWithETH = userAddresses[0];
|
addressWithETH = userAddresses[0];
|
||||||
wethContractAddress = (zeroEx.etherToken as any)._getContractAddress(artifacts.EtherTokenArtifact);
|
wethContractAddress = zeroEx.etherToken.getContractAddressIfExists() as string;
|
||||||
depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(new BigNumber(5));
|
depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5));
|
||||||
decimalPlaces = 7;
|
decimalPlaces = 7;
|
||||||
addressWithoutFunds = userAddresses[1];
|
addressWithoutFunds = userAddresses[1];
|
||||||
});
|
});
|
||||||
@@ -71,6 +70,21 @@ describe('EtherTokenWrapper', () => {
|
|||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await blockchainLifecycle.revertAsync();
|
await blockchainLifecycle.revertAsync();
|
||||||
});
|
});
|
||||||
|
describe('#getContractAddressIfExists', async () => {
|
||||||
|
it('should return contract address if connected to a known network', () => {
|
||||||
|
const contractAddressIfExists = zeroEx.etherToken.getContractAddressIfExists();
|
||||||
|
expect(contractAddressIfExists).to.not.be.undefined();
|
||||||
|
});
|
||||||
|
it('should throw if connected to a private network and contract addresses are not specified', () => {
|
||||||
|
const UNKNOWN_NETWORK_NETWORK_ID = 10;
|
||||||
|
expect(
|
||||||
|
() =>
|
||||||
|
new ZeroEx(web3.currentProvider, {
|
||||||
|
networkId: UNKNOWN_NETWORK_NETWORK_ID,
|
||||||
|
} as any),
|
||||||
|
).to.throw();
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('#depositAsync', () => {
|
describe('#depositAsync', () => {
|
||||||
it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => {
|
it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => {
|
||||||
const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||||
@@ -92,7 +106,7 @@ describe('EtherTokenWrapper', () => {
|
|||||||
it('should throw if user has insufficient ETH balance for deposit', async () => {
|
it('should throw if user has insufficient ETH balance for deposit', async () => {
|
||||||
const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||||
|
|
||||||
const extraETHBalance = (zeroEx as any)._web3Wrapper.toWei(5, 'ether');
|
const extraETHBalance = Web3Wrapper.toWei(new BigNumber(5));
|
||||||
const overETHBalanceinWei = preETHBalance.add(extraETHBalance);
|
const overETHBalanceinWei = preETHBalance.add(extraETHBalance);
|
||||||
|
|
||||||
return expect(
|
return expect(
|
||||||
@@ -124,7 +138,7 @@ describe('EtherTokenWrapper', () => {
|
|||||||
gasCost = expectedETHBalance.minus(postETHBalance);
|
gasCost = expectedETHBalance.minus(postETHBalance);
|
||||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||||
});
|
});
|
||||||
it('should throw if user has insufficient WETH balance for withdrawl', async () => {
|
it('should throw if user has insufficient WETH balance for withdrawal', async () => {
|
||||||
const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH);
|
||||||
expect(preWETHBalance).to.be.bignumber.equal(0);
|
expect(preWETHBalance).to.be.bignumber.equal(0);
|
||||||
|
|
||||||
@@ -153,118 +167,137 @@ describe('EtherTokenWrapper', () => {
|
|||||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callback = (err: Error, logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
|
const callback = reportNodeCallbackErrors(done)(
|
||||||
expect(err).to.be.null();
|
(logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
|
||||||
expect(logEvent).to.not.be.undefined();
|
expect(logEvent).to.not.be.undefined();
|
||||||
expect(logEvent.isRemoved).to.be.false();
|
expect(logEvent.isRemoved).to.be.false();
|
||||||
expect(logEvent.log.logIndex).to.be.equal(0);
|
expect(logEvent.log.logIndex).to.be.equal(0);
|
||||||
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
||||||
expect(logEvent.log.blockNumber).to.be.a('number');
|
expect(logEvent.log.blockNumber).to.be.a('number');
|
||||||
const args = logEvent.log.args;
|
const args = logEvent.log.args;
|
||||||
expect(args._from).to.be.equal(addressWithETH);
|
expect(args._from).to.be.equal(addressWithETH);
|
||||||
expect(args._to).to.be.equal(addressWithoutFunds);
|
expect(args._to).to.be.equal(addressWithoutFunds);
|
||||||
expect(args._value).to.be.bignumber.equal(transferAmount);
|
expect(args._value).to.be.bignumber.equal(transferAmount);
|
||||||
done();
|
},
|
||||||
};
|
);
|
||||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||||
zeroEx.etherToken.subscribe(
|
zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback);
|
||||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback);
|
|
||||||
await zeroEx.token.transferAsync(
|
await zeroEx.token.transferAsync(
|
||||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
etherTokenAddress,
|
||||||
|
addressWithETH,
|
||||||
|
addressWithoutFunds,
|
||||||
|
transferAmount,
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
const callback = reportNodeCallbackErrors(done)(
|
||||||
expect(err).to.be.null();
|
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||||
expect(logEvent).to.not.be.undefined();
|
expect(logEvent).to.not.be.undefined();
|
||||||
expect(logEvent.isRemoved).to.be.false();
|
expect(logEvent.isRemoved).to.be.false();
|
||||||
const args = logEvent.log.args;
|
const args = logEvent.log.args;
|
||||||
expect(args._owner).to.be.equal(addressWithETH);
|
expect(args._owner).to.be.equal(addressWithETH);
|
||||||
expect(args._spender).to.be.equal(addressWithoutFunds);
|
expect(args._spender).to.be.equal(addressWithoutFunds);
|
||||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||||
done();
|
},
|
||||||
};
|
);
|
||||||
zeroEx.etherToken.subscribe(
|
zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback);
|
||||||
etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback);
|
|
||||||
await zeroEx.token.setAllowanceAsync(
|
await zeroEx.token.setAllowanceAsync(
|
||||||
etherTokenAddress, addressWithETH, addressWithoutFunds, allowanceAmount,
|
etherTokenAddress,
|
||||||
|
addressWithETH,
|
||||||
|
addressWithoutFunds,
|
||||||
|
allowanceAmount,
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => {
|
it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callback = (err: Error, logEvent: DecodedLogEvent<DepositContractEventArgs>) => {
|
const callback = reportNodeCallbackErrors(done)(
|
||||||
expect(err).to.be.null();
|
(logEvent: DecodedLogEvent<DepositContractEventArgs>) => {
|
||||||
expect(logEvent).to.not.be.undefined();
|
expect(logEvent).to.not.be.undefined();
|
||||||
expect(logEvent.isRemoved).to.be.false();
|
expect(logEvent.isRemoved).to.be.false();
|
||||||
const args = logEvent.log.args;
|
const args = logEvent.log.args;
|
||||||
expect(args._owner).to.be.equal(addressWithETH);
|
expect(args._owner).to.be.equal(addressWithETH);
|
||||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||||
done();
|
},
|
||||||
};
|
|
||||||
zeroEx.etherToken.subscribe(
|
|
||||||
etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback);
|
|
||||||
await zeroEx.etherToken.depositAsync(
|
|
||||||
etherTokenAddress, depositAmount, addressWithETH,
|
|
||||||
);
|
);
|
||||||
|
zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback);
|
||||||
|
await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => {
|
it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callback = (err: Error, logEvent: DecodedLogEvent<WithdrawalContractEventArgs>) => {
|
const callback = reportNodeCallbackErrors(done)(
|
||||||
expect(err).to.be.null();
|
(logEvent: DecodedLogEvent<WithdrawalContractEventArgs>) => {
|
||||||
expect(logEvent).to.not.be.undefined();
|
expect(logEvent).to.not.be.undefined();
|
||||||
expect(logEvent.isRemoved).to.be.false();
|
expect(logEvent.isRemoved).to.be.false();
|
||||||
const args = logEvent.log.args;
|
const args = logEvent.log.args;
|
||||||
expect(args._owner).to.be.equal(addressWithETH);
|
expect(args._owner).to.be.equal(addressWithETH);
|
||||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||||
done();
|
},
|
||||||
};
|
|
||||||
await zeroEx.etherToken.depositAsync(
|
|
||||||
etherTokenAddress, depositAmount, addressWithETH,
|
|
||||||
);
|
);
|
||||||
|
await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||||
zeroEx.etherToken.subscribe(
|
zeroEx.etherToken.subscribe(
|
||||||
etherTokenAddress, EtherTokenEvents.Withdrawal, indexFilterValues, callback);
|
etherTokenAddress,
|
||||||
await zeroEx.etherToken.withdrawAsync(
|
EtherTokenEvents.Withdrawal,
|
||||||
etherTokenAddress, withdrawalAmount, addressWithETH,
|
indexFilterValues,
|
||||||
|
callback,
|
||||||
);
|
);
|
||||||
|
await zeroEx.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => {
|
it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
|
||||||
done(new Error('Expected this subscription to have been cancelled'));
|
(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>) => {
|
zeroEx.etherToken.subscribe(
|
||||||
done();
|
etherTokenAddress,
|
||||||
};
|
EtherTokenEvents.Transfer,
|
||||||
|
indexFilterValues,
|
||||||
|
callbackNeverToBeCalled,
|
||||||
|
);
|
||||||
|
const callbackToBeCalled = reportNodeCallbackErrors(done)();
|
||||||
const newProvider = web3Factory.getRpcProvider();
|
const newProvider = web3Factory.getRpcProvider();
|
||||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||||
zeroEx.etherToken.subscribe(
|
zeroEx.etherToken.subscribe(
|
||||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackToBeCalled,
|
etherTokenAddress,
|
||||||
|
EtherTokenEvents.Transfer,
|
||||||
|
indexFilterValues,
|
||||||
|
callbackToBeCalled,
|
||||||
);
|
);
|
||||||
await zeroEx.token.transferAsync(
|
await zeroEx.token.transferAsync(
|
||||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
etherTokenAddress,
|
||||||
|
addressWithETH,
|
||||||
|
addressWithoutFunds,
|
||||||
|
transferAmount,
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
|
||||||
done(new Error('Expected this subscription to have been cancelled'));
|
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||||
};
|
done(new Error('Expected this subscription to have been cancelled'));
|
||||||
|
},
|
||||||
|
);
|
||||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||||
const subscriptionToken = zeroEx.etherToken.subscribe(
|
const subscriptionToken = zeroEx.etherToken.subscribe(
|
||||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
etherTokenAddress,
|
||||||
|
EtherTokenEvents.Transfer,
|
||||||
|
indexFilterValues,
|
||||||
|
callbackNeverToBeCalled,
|
||||||
|
);
|
||||||
zeroEx.etherToken.unsubscribe(subscriptionToken);
|
zeroEx.etherToken.unsubscribe(subscriptionToken);
|
||||||
await zeroEx.token.transferAsync(
|
await zeroEx.token.transferAsync(
|
||||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
etherTokenAddress,
|
||||||
|
addressWithETH,
|
||||||
|
addressWithoutFunds,
|
||||||
|
transferAmount,
|
||||||
);
|
);
|
||||||
done();
|
done();
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
@@ -291,7 +324,10 @@ describe('EtherTokenWrapper', () => {
|
|||||||
const eventName = EtherTokenEvents.Approval;
|
const eventName = EtherTokenEvents.Approval;
|
||||||
const indexFilterValues = {};
|
const indexFilterValues = {};
|
||||||
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
||||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
etherTokenAddress,
|
||||||
|
eventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
);
|
);
|
||||||
expect(logs).to.have.length(1);
|
expect(logs).to.have.length(1);
|
||||||
const args = logs[0].args;
|
const args = logs[0].args;
|
||||||
@@ -305,7 +341,10 @@ describe('EtherTokenWrapper', () => {
|
|||||||
const eventName = EtherTokenEvents.Deposit;
|
const eventName = EtherTokenEvents.Deposit;
|
||||||
const indexFilterValues = {};
|
const indexFilterValues = {};
|
||||||
const logs = await zeroEx.etherToken.getLogsAsync<DepositContractEventArgs>(
|
const logs = await zeroEx.etherToken.getLogsAsync<DepositContractEventArgs>(
|
||||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
etherTokenAddress,
|
||||||
|
eventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
);
|
);
|
||||||
expect(logs).to.have.length(1);
|
expect(logs).to.have.length(1);
|
||||||
const args = logs[0].args;
|
const args = logs[0].args;
|
||||||
@@ -319,7 +358,10 @@ describe('EtherTokenWrapper', () => {
|
|||||||
const differentEventName = EtherTokenEvents.Transfer;
|
const differentEventName = EtherTokenEvents.Transfer;
|
||||||
const indexFilterValues = {};
|
const indexFilterValues = {};
|
||||||
const logs = await zeroEx.etherToken.getLogsAsync(
|
const logs = await zeroEx.etherToken.getLogsAsync(
|
||||||
etherTokenAddress, differentEventName, blockRange, indexFilterValues,
|
etherTokenAddress,
|
||||||
|
differentEventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
);
|
);
|
||||||
expect(logs).to.have.length(0);
|
expect(logs).to.have.length(0);
|
||||||
});
|
});
|
||||||
@@ -333,7 +375,10 @@ describe('EtherTokenWrapper', () => {
|
|||||||
_owner: addressWithETH,
|
_owner: addressWithETH,
|
||||||
};
|
};
|
||||||
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
||||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
etherTokenAddress,
|
||||||
|
eventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
);
|
);
|
||||||
expect(logs).to.have.length(1);
|
expect(logs).to.have.length(1);
|
||||||
const args = logs[0].args;
|
const args = logs[0].args;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { web3Factory } from '@0xproject/dev-utils';
|
||||||
|
import { LogEntry } from '@0xproject/types';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
import * as Sinon from 'sinon';
|
import * as Sinon from 'sinon';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import {
|
import { LogEvent } from '../src';
|
||||||
LogEvent,
|
import { EventWatcher } from '../src/order_watcher/event_watcher';
|
||||||
} from '../src';
|
import { DoneCallback } from '../src/types';
|
||||||
import {EventWatcher} from '../src/order_watcher/event_watcher';
|
|
||||||
import {DoneCallback} from '../src/types';
|
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { reportNodeCallbackErrors } from './utils/report_callback_errors';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -22,7 +22,7 @@ describe('EventWatcher', () => {
|
|||||||
let stubs: Sinon.SinonStub[] = [];
|
let stubs: Sinon.SinonStub[] = [];
|
||||||
let eventWatcher: EventWatcher;
|
let eventWatcher: EventWatcher;
|
||||||
let web3Wrapper: Web3Wrapper;
|
let web3Wrapper: Web3Wrapper;
|
||||||
const logA: Web3.LogEntry = {
|
const logA: LogEntry = {
|
||||||
address: '0x71d271f8b14adef568f8f28f1587ce7271ac4ca5',
|
address: '0x71d271f8b14adef568f8f28f1587ce7271ac4ca5',
|
||||||
blockHash: null,
|
blockHash: null,
|
||||||
blockNumber: null,
|
blockNumber: null,
|
||||||
@@ -32,23 +32,23 @@ describe('EventWatcher', () => {
|
|||||||
transactionHash: '0x004881d38cd4a8f72f1a0d68c8b9b8124504706041ff37019c1d1ed6bfda8e17',
|
transactionHash: '0x004881d38cd4a8f72f1a0d68c8b9b8124504706041ff37019c1d1ed6bfda8e17',
|
||||||
transactionIndex: 0,
|
transactionIndex: 0,
|
||||||
};
|
};
|
||||||
const logB: Web3.LogEntry = {
|
const logB: LogEntry = {
|
||||||
address: '0x8d12a197cb00d4747a1fe03395095ce2a5cc6819',
|
address: '0x8d12a197cb00d4747a1fe03395095ce2a5cc6819',
|
||||||
blockHash: null,
|
blockHash: null,
|
||||||
blockNumber: null,
|
blockNumber: null,
|
||||||
data: '',
|
data: '',
|
||||||
logIndex: null,
|
logIndex: null,
|
||||||
topics: [ '0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567' ],
|
topics: ['0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567'],
|
||||||
transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
|
transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
|
||||||
transactionIndex: 0,
|
transactionIndex: 0,
|
||||||
};
|
};
|
||||||
const logC: Web3.LogEntry = {
|
const logC: LogEntry = {
|
||||||
address: '0x1d271f8b174adef58f1587ce68f8f27271ac4ca5',
|
address: '0x1d271f8b174adef58f1587ce68f8f27271ac4ca5',
|
||||||
blockHash: null,
|
blockHash: null,
|
||||||
blockNumber: null,
|
blockNumber: null,
|
||||||
data: '',
|
data: '',
|
||||||
logIndex: null,
|
logIndex: null,
|
||||||
topics: [ '0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567' ],
|
topics: ['0xf341246adaac6f497bc2a656f546ab9e182111d630394f0c57c710a59a2cb567'],
|
||||||
transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
|
transactionHash: '0x01ef3c048b18d9b09ea195b4ed94cf8dd5f3d857a1905ff886b152cfb1166f25',
|
||||||
transactionIndex: 0,
|
transactionIndex: 0,
|
||||||
};
|
};
|
||||||
@@ -65,7 +65,7 @@ describe('EventWatcher', () => {
|
|||||||
eventWatcher.unsubscribe();
|
eventWatcher.unsubscribe();
|
||||||
});
|
});
|
||||||
it('correctly emits initial log events', (done: DoneCallback) => {
|
it('correctly emits initial log events', (done: DoneCallback) => {
|
||||||
const logs: Web3.LogEntry[] = [logA, logB];
|
const logs: LogEntry[] = [logA, logB];
|
||||||
const expectedLogEvents = [
|
const expectedLogEvents = [
|
||||||
{
|
{
|
||||||
removed: false,
|
removed: false,
|
||||||
@@ -79,18 +79,19 @@ describe('EventWatcher', () => {
|
|||||||
const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
|
const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync');
|
||||||
getLogsStub.onCall(0).returns(logs);
|
getLogsStub.onCall(0).returns(logs);
|
||||||
stubs.push(getLogsStub);
|
stubs.push(getLogsStub);
|
||||||
const callback = (event: LogEvent) => {
|
const expectedToBeCalledOnce = false;
|
||||||
|
const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => {
|
||||||
const expectedLogEvent = expectedLogEvents.shift();
|
const expectedLogEvent = expectedLogEvents.shift();
|
||||||
expect(event).to.be.deep.equal(expectedLogEvent);
|
expect(event).to.be.deep.equal(expectedLogEvent);
|
||||||
if (_.isEmpty(expectedLogEvents)) {
|
if (_.isEmpty(expectedLogEvents)) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
eventWatcher.subscribe(callback);
|
eventWatcher.subscribe(callback);
|
||||||
});
|
});
|
||||||
it('correctly computes the difference and emits only changes', (done: DoneCallback) => {
|
it('correctly computes the difference and emits only changes', (done: DoneCallback) => {
|
||||||
const initialLogs: Web3.LogEntry[] = [logA, logB];
|
const initialLogs: LogEntry[] = [logA, logB];
|
||||||
const changedLogs: Web3.LogEntry[] = [logA, logC];
|
const changedLogs: LogEntry[] = [logA, logC];
|
||||||
const expectedLogEvents = [
|
const expectedLogEvents = [
|
||||||
{
|
{
|
||||||
removed: false,
|
removed: false,
|
||||||
@@ -113,13 +114,14 @@ describe('EventWatcher', () => {
|
|||||||
getLogsStub.onCall(0).returns(initialLogs);
|
getLogsStub.onCall(0).returns(initialLogs);
|
||||||
getLogsStub.onCall(1).returns(changedLogs);
|
getLogsStub.onCall(1).returns(changedLogs);
|
||||||
stubs.push(getLogsStub);
|
stubs.push(getLogsStub);
|
||||||
const callback = (event: LogEvent) => {
|
const expectedToBeCalledOnce = false;
|
||||||
|
const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => {
|
||||||
const expectedLogEvent = expectedLogEvents.shift();
|
const expectedLogEvent = expectedLogEvents.shift();
|
||||||
expect(event).to.be.deep.equal(expectedLogEvent);
|
expect(event).to.be.deep.equal(expectedLogEvent);
|
||||||
if (_.isEmpty(expectedLogEvents)) {
|
if (_.isEmpty(expectedLogEvents)) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
eventWatcher.subscribe(callback);
|
eventWatcher.subscribe(callback);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { BlockParamLiteral } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
|
|
||||||
import {ExchangeContractErrs, Token, ZeroEx} from '../src';
|
import { ExchangeContractErrs, Token, ZeroEx } from '../src';
|
||||||
import {BlockParamLiteral, TradeSide, TransferType} from '../src/types';
|
import { TradeSide, TransferType } from '../src/types';
|
||||||
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
|
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
describe('ExchangeTransferSimulator', () => {
|
describe('ExchangeTransferSimulator', () => {
|
||||||
const web3 = web3Factory.create();
|
|
||||||
const config = {
|
const config = {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
@@ -45,17 +45,31 @@ describe('ExchangeTransferSimulator', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest);
|
exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest);
|
||||||
});
|
});
|
||||||
it('throws if the user doesn\'t have enough allowance', async () => {
|
it("throws if the user doesn't have enough allowance", async () => {
|
||||||
return expect(exchangeTransferSimulator.transferFromAsync(
|
return expect(
|
||||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
exchangeTransferSimulator.transferFromAsync(
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance);
|
exampleTokenAddress,
|
||||||
|
sender,
|
||||||
|
recipient,
|
||||||
|
transferAmount,
|
||||||
|
TradeSide.Taker,
|
||||||
|
TransferType.Trade,
|
||||||
|
),
|
||||||
|
).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance);
|
||||||
});
|
});
|
||||||
it('throws if the user doesn\'t have enough balance', async () => {
|
it("throws if the user doesn't have enough balance", async () => {
|
||||||
txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
|
txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
|
||||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
return expect(exchangeTransferSimulator.transferFromAsync(
|
return expect(
|
||||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Maker, TransferType.Trade,
|
exchangeTransferSimulator.transferFromAsync(
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
|
exampleTokenAddress,
|
||||||
|
sender,
|
||||||
|
recipient,
|
||||||
|
transferAmount,
|
||||||
|
TradeSide.Maker,
|
||||||
|
TransferType.Trade,
|
||||||
|
),
|
||||||
|
).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
|
||||||
});
|
});
|
||||||
it('updates balances and proxyAllowance after transfer', async () => {
|
it('updates balances and proxyAllowance after transfer', async () => {
|
||||||
txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
|
txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
|
||||||
@@ -63,7 +77,12 @@ describe('ExchangeTransferSimulator', () => {
|
|||||||
txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
|
txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
|
||||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
await exchangeTransferSimulator.transferFromAsync(
|
await exchangeTransferSimulator.transferFromAsync(
|
||||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
exampleTokenAddress,
|
||||||
|
sender,
|
||||||
|
recipient,
|
||||||
|
transferAmount,
|
||||||
|
TradeSide.Taker,
|
||||||
|
TransferType.Trade,
|
||||||
);
|
);
|
||||||
const store = (exchangeTransferSimulator as any)._store;
|
const store = (exchangeTransferSimulator as any)._store;
|
||||||
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
||||||
@@ -73,13 +92,18 @@ describe('ExchangeTransferSimulator', () => {
|
|||||||
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
|
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
|
||||||
expect(senderProxyAllowance).to.be.bignumber.equal(0);
|
expect(senderProxyAllowance).to.be.bignumber.equal(0);
|
||||||
});
|
});
|
||||||
it('doesn\'t update proxyAllowance after transfer if unlimited', async () => {
|
it("doesn't update proxyAllowance after transfer if unlimited", async () => {
|
||||||
txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
|
txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
|
||||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender);
|
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender);
|
||||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||||
await exchangeTransferSimulator.transferFromAsync(
|
await exchangeTransferSimulator.transferFromAsync(
|
||||||
exampleTokenAddress, sender, recipient, transferAmount, TradeSide.Taker, TransferType.Trade,
|
exampleTokenAddress,
|
||||||
|
sender,
|
||||||
|
recipient,
|
||||||
|
transferAmount,
|
||||||
|
TradeSide.Taker,
|
||||||
|
TransferType.Trade,
|
||||||
);
|
);
|
||||||
const store = (exchangeTransferSimulator as any)._store;
|
const store = (exchangeTransferSimulator as any)._store;
|
||||||
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,30 +1,28 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
import * as Sinon from 'sinon';
|
import * as Sinon from 'sinon';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import {ZeroEx} from '../src/0x';
|
import { ZeroEx } from '../src/0x';
|
||||||
import {ExpirationWatcher} from '../src/order_watcher/expiration_watcher';
|
import { ExpirationWatcher } from '../src/order_watcher/expiration_watcher';
|
||||||
import {DoneCallback, Token} from '../src/types';
|
import { DoneCallback, Token } from '../src/types';
|
||||||
import {constants} from '../src/utils/constants';
|
import { utils } from '../src/utils/utils';
|
||||||
import {utils} from '../src/utils/utils';
|
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants as testConstants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {FillScenarios} from './utils/fill_scenarios';
|
import { FillScenarios } from './utils/fill_scenarios';
|
||||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
import { reportNoErrorCallbackErrors } from './utils/report_callback_errors';
|
||||||
import {TokenUtils} from './utils/token_utils';
|
import { TokenUtils } from './utils/token_utils';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(testConstants.RPC_URL);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
describe('ExpirationWatcher', () => {
|
describe('ExpirationWatcher', () => {
|
||||||
let web3: Web3;
|
|
||||||
let zeroEx: ZeroEx;
|
let zeroEx: ZeroEx;
|
||||||
let tokenUtils: TokenUtils;
|
let tokenUtils: TokenUtils;
|
||||||
let tokens: Token[];
|
let tokens: Token[];
|
||||||
@@ -43,7 +41,6 @@ describe('ExpirationWatcher', () => {
|
|||||||
let timer: Sinon.SinonFakeTimers;
|
let timer: Sinon.SinonFakeTimers;
|
||||||
let expirationWatcher: ExpirationWatcher;
|
let expirationWatcher: ExpirationWatcher;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
web3 = web3Factory.create();
|
|
||||||
const config = {
|
const config = {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
@@ -62,7 +59,7 @@ describe('ExpirationWatcher', () => {
|
|||||||
});
|
});
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await blockchainLifecycle.startAsync();
|
await blockchainLifecycle.startAsync();
|
||||||
const sinonTimerConfig = {shouldAdvanceTime: true} as any;
|
const sinonTimerConfig = { shouldAdvanceTime: true } as any;
|
||||||
// This constructor has incorrect types
|
// This constructor has incorrect types
|
||||||
timer = Sinon.useFakeTimers(sinonTimerConfig);
|
timer = Sinon.useFakeTimers(sinonTimerConfig);
|
||||||
currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
|
currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
|
||||||
@@ -78,31 +75,38 @@ describe('ExpirationWatcher', () => {
|
|||||||
const orderLifetimeSec = 60;
|
const orderLifetimeSec = 60;
|
||||||
const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
|
const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
expirationUnixTimestampSec,
|
expirationUnixTimestampSec,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000));
|
expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000));
|
||||||
const callbackAsync = reportCallbackErrors(done)(async (hash: string) => {
|
const callbackAsync = reportNoErrorCallbackErrors(done)((hash: string) => {
|
||||||
expect(hash).to.be.equal(orderHash);
|
expect(hash).to.be.equal(orderHash);
|
||||||
expect(utils.getCurrentUnixTimestampSec()).to.be.bignumber.gte(expirationUnixTimestampSec);
|
expect(utils.getCurrentUnixTimestampSec()).to.be.bignumber.gte(expirationUnixTimestampSec);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
expirationWatcher.subscribe(callbackAsync);
|
expirationWatcher.subscribe(callbackAsync);
|
||||||
timer.tick(orderLifetimeSec * 1000);
|
timer.tick(orderLifetimeSec * 1000);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('doesn\'t emit events before order expires', (done: DoneCallback) => {
|
it("doesn't emit events before order expires", (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const orderLifetimeSec = 60;
|
const orderLifetimeSec = 60;
|
||||||
const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
|
const expirationUnixTimestampSec = currentUnixTimestampSec.plus(orderLifetimeSec);
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
expirationUnixTimestampSec,
|
expirationUnixTimestampSec,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000));
|
expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000));
|
||||||
const callbackAsync = reportCallbackErrors(done)(async (hash: string) => {
|
const callbackAsync = reportNoErrorCallbackErrors(done)(async (hash: string) => {
|
||||||
done(new Error('Emitted expiration went before the order actually expired'));
|
done(new Error('Emitted expiration went before the order actually expired'));
|
||||||
});
|
});
|
||||||
expirationWatcher.subscribe(callbackAsync);
|
expirationWatcher.subscribe(callbackAsync);
|
||||||
@@ -118,11 +122,19 @@ describe('ExpirationWatcher', () => {
|
|||||||
const order1ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order1Lifetime);
|
const order1ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order1Lifetime);
|
||||||
const order2ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order2Lifetime);
|
const order2ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order2Lifetime);
|
||||||
const signedOrder1 = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder1 = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
order1ExpirationUnixTimestampSec,
|
order1ExpirationUnixTimestampSec,
|
||||||
);
|
);
|
||||||
const signedOrder2 = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder2 = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
order2ExpirationUnixTimestampSec,
|
order2ExpirationUnixTimestampSec,
|
||||||
);
|
);
|
||||||
const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1);
|
const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1);
|
||||||
@@ -130,7 +142,8 @@ describe('ExpirationWatcher', () => {
|
|||||||
expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000));
|
expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000));
|
||||||
expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000));
|
expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000));
|
||||||
const expirationOrder = [orderHash1, orderHash2];
|
const expirationOrder = [orderHash1, orderHash2];
|
||||||
const callbackAsync = reportCallbackErrors(done)(async (hash: string) => {
|
const expectToBeCalledOnce = false;
|
||||||
|
const callbackAsync = reportNoErrorCallbackErrors(done, expectToBeCalledOnce)((hash: string) => {
|
||||||
const orderHash = expirationOrder.shift();
|
const orderHash = expirationOrder.shift();
|
||||||
expect(hash).to.be.equal(orderHash);
|
expect(hash).to.be.equal(orderHash);
|
||||||
if (_.isEmpty(expirationOrder)) {
|
if (_.isEmpty(expirationOrder)) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
@@ -15,23 +15,23 @@ import {
|
|||||||
ZeroEx,
|
ZeroEx,
|
||||||
ZeroExError,
|
ZeroExError,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
import {DoneCallback} from '../src/types';
|
import { OrderStateWatcher } from '../src/order_watcher/order_state_watcher';
|
||||||
|
import { DoneCallback } from '../src/types';
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {FillScenarios} from './utils/fill_scenarios';
|
import { FillScenarios } from './utils/fill_scenarios';
|
||||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
import { reportNodeCallbackErrors } from './utils/report_callback_errors';
|
||||||
import {TokenUtils} from './utils/token_utils';
|
import { TokenUtils } from './utils/token_utils';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
const TIMEOUT_MS = 150;
|
const TIMEOUT_MS = 150;
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
describe('OrderStateWatcher', () => {
|
describe('OrderStateWatcher', () => {
|
||||||
let web3: Web3;
|
|
||||||
let zeroEx: ZeroEx;
|
let zeroEx: ZeroEx;
|
||||||
let tokens: Token[];
|
let tokens: Token[];
|
||||||
let tokenUtils: TokenUtils;
|
let tokenUtils: TokenUtils;
|
||||||
@@ -44,14 +44,15 @@ describe('OrderStateWatcher', () => {
|
|||||||
let maker: string;
|
let maker: string;
|
||||||
let taker: string;
|
let taker: string;
|
||||||
let signedOrder: SignedOrder;
|
let signedOrder: SignedOrder;
|
||||||
|
let orderStateWatcher: OrderStateWatcher;
|
||||||
const config = {
|
const config = {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
const decimals = constants.ZRX_DECIMALS;
|
const decimals = constants.ZRX_DECIMALS;
|
||||||
const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||||
before(async () => {
|
before(async () => {
|
||||||
web3 = web3Factory.create();
|
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||||
|
orderStateWatcher = zeroEx.createOrderStateWatcher();
|
||||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
[, maker, taker] = userAddresses;
|
[, maker, taker] = userAddresses;
|
||||||
@@ -71,75 +72,93 @@ describe('OrderStateWatcher', () => {
|
|||||||
describe('#removeOrder', async () => {
|
describe('#removeOrder', async () => {
|
||||||
it('should successfully remove existing order', async () => {
|
it('should successfully remove existing order', async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.include({
|
expect((orderStateWatcher as any)._orderByOrderHash).to.include({
|
||||||
[orderHash]: signedOrder,
|
[orderHash]: signedOrder,
|
||||||
});
|
});
|
||||||
let dependentOrderHashes = (zeroEx.orderStateWatcher as any)._dependentOrderHashes;
|
let dependentOrderHashes = (orderStateWatcher as any)._dependentOrderHashes;
|
||||||
expect(dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress]).to.have.keys(orderHash);
|
expect(dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress]).to.have.keys(orderHash);
|
||||||
zeroEx.orderStateWatcher.removeOrder(orderHash);
|
orderStateWatcher.removeOrder(orderHash);
|
||||||
expect((zeroEx.orderStateWatcher as any)._orderByOrderHash).to.not.include({
|
expect((orderStateWatcher as any)._orderByOrderHash).to.not.include({
|
||||||
[orderHash]: signedOrder,
|
[orderHash]: signedOrder,
|
||||||
});
|
});
|
||||||
dependentOrderHashes = (zeroEx.orderStateWatcher as any)._dependentOrderHashes;
|
dependentOrderHashes = (orderStateWatcher as any)._dependentOrderHashes;
|
||||||
expect(dependentOrderHashes[signedOrder.maker]).to.be.undefined();
|
expect(dependentOrderHashes[signedOrder.maker]).to.be.undefined();
|
||||||
});
|
});
|
||||||
it('should no-op when removing a non-existing order', async () => {
|
it('should no-op when removing a non-existing order', async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
const nonExistentOrderHash = `0x${orderHash.substr(2).split('').reverse().join('')}`;
|
const nonExistentOrderHash = `0x${orderHash
|
||||||
zeroEx.orderStateWatcher.removeOrder(nonExistentOrderHash);
|
.substr(2)
|
||||||
|
.split('')
|
||||||
|
.reverse()
|
||||||
|
.join('')}`;
|
||||||
|
orderStateWatcher.removeOrder(nonExistentOrderHash);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#subscribe', async () => {
|
describe('#subscribe', async () => {
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
zeroEx.orderStateWatcher.unsubscribe();
|
orderStateWatcher.unsubscribe();
|
||||||
});
|
});
|
||||||
it('should fail when trying to subscribe twice', async () => {
|
it('should fail when trying to subscribe twice', async () => {
|
||||||
zeroEx.orderStateWatcher.subscribe(_.noop);
|
orderStateWatcher.subscribe(_.noop);
|
||||||
expect(() => zeroEx.orderStateWatcher.subscribe(_.noop))
|
expect(() => orderStateWatcher.subscribe(_.noop)).to.throw(ZeroExError.SubscriptionAlreadyPresent);
|
||||||
.to.throw(ZeroExError.SubscriptionAlreadyPresent);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('tests with cleanup', async () => {
|
describe('tests with cleanup', async () => {
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
zeroEx.orderStateWatcher.unsubscribe();
|
orderStateWatcher.unsubscribe();
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.removeOrder(orderHash);
|
orderStateWatcher.removeOrder(orderHash);
|
||||||
});
|
});
|
||||||
it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
|
it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
const invalidOrderState = orderState as OrderStateInvalid;
|
const invalidOrderState = orderState as OrderStateInvalid;
|
||||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance);
|
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0));
|
await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0));
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('should not emit an orderState event when irrelevant Transfer event received', (done: DoneCallback) => {
|
it('should not emit an orderState event when irrelevant Transfer event received', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
throw new Error('OrderState callback fired for irrelevant order');
|
throw new Error('OrderState callback fired for irrelevant order');
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
const notTheMaker = userAddresses[0];
|
const notTheMaker = userAddresses[0];
|
||||||
const anyRecipient = taker;
|
const anyRecipient = taker;
|
||||||
const transferAmount = new BigNumber(2);
|
const transferAmount = new BigNumber(2);
|
||||||
@@ -152,18 +171,21 @@ describe('OrderStateWatcher', () => {
|
|||||||
it('should emit orderStateInvalid when maker moves balance backing watched order', (done: DoneCallback) => {
|
it('should emit orderStateInvalid when maker moves balance backing watched order', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
const invalidOrderState = orderState as OrderStateInvalid;
|
const invalidOrderState = orderState as OrderStateInvalid;
|
||||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance);
|
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
const anyRecipient = taker;
|
const anyRecipient = taker;
|
||||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||||
await zeroEx.token.transferAsync(makerToken.address, maker, anyRecipient, makerBalance);
|
await zeroEx.token.transferAsync(makerToken.address, maker, anyRecipient, makerBalance);
|
||||||
@@ -172,38 +194,48 @@ describe('OrderStateWatcher', () => {
|
|||||||
it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => {
|
it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
const invalidOrderState = orderState as OrderStateInvalid;
|
const invalidOrderState = orderState as OrderStateInvalid;
|
||||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
|
|
||||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||||
await zeroEx.exchange.fillOrderAsync(
|
await zeroEx.exchange.fillOrderAsync(
|
||||||
signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
signedOrder,
|
||||||
|
fillableAmount,
|
||||||
|
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||||
|
taker,
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('should emit orderStateValid when watched order partially filled', (done: DoneCallback) => {
|
it('should emit orderStateValid when watched order partially filled', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
|
|
||||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||||
const fillAmountInBaseUnits = new BigNumber(2);
|
const fillAmountInBaseUnits = new BigNumber(2);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.true();
|
expect(orderState.isValid).to.be.true();
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
||||||
@@ -211,16 +243,20 @@ describe('OrderStateWatcher', () => {
|
|||||||
const remainingMakerBalance = makerBalance.sub(fillAmountInBaseUnits);
|
const remainingMakerBalance = makerBalance.sub(fillAmountInBaseUnits);
|
||||||
const remainingFillable = fillableAmount.minus(fillAmountInBaseUnits);
|
const remainingFillable = fillableAmount.minus(fillAmountInBaseUnits);
|
||||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||||
remainingFillable);
|
remainingFillable,
|
||||||
|
);
|
||||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||||
remainingFillable);
|
remainingFillable,
|
||||||
|
);
|
||||||
expect(orderRelevantState.makerBalance).to.be.bignumber.equal(remainingMakerBalance);
|
expect(orderRelevantState.makerBalance).to.be.bignumber.equal(remainingMakerBalance);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||||
await zeroEx.exchange.fillOrderAsync(
|
await zeroEx.exchange.fillOrderAsync(
|
||||||
signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
signedOrder,
|
||||||
|
fillAmountInBaseUnits,
|
||||||
|
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||||
|
taker,
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
@@ -229,13 +265,18 @@ describe('OrderStateWatcher', () => {
|
|||||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
|
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18);
|
||||||
const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), 18);
|
const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), 18);
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
makerToken.address, takerToken.address, makerFee, takerFee, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
taker);
|
takerToken.address,
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
makerFee,
|
||||||
done();
|
takerFee,
|
||||||
});
|
maker,
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
taker,
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
fillableAmount,
|
||||||
|
taker,
|
||||||
|
);
|
||||||
|
const callback = reportNodeCallbackErrors(done)();
|
||||||
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0));
|
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0));
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
@@ -245,77 +286,94 @@ describe('OrderStateWatcher', () => {
|
|||||||
const takerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(10), decimals);
|
const takerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(10), decimals);
|
||||||
const makerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(20), decimals);
|
const makerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(20), decimals);
|
||||||
signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, makerFillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
makerFillableAmount,
|
||||||
takerFillableAmount,
|
takerFillableAmount,
|
||||||
);
|
);
|
||||||
const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.true();
|
expect(orderState.isValid).to.be.true();
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
||||||
const orderRelevantState = validOrderState.orderRelevantState;
|
const orderRelevantState = validOrderState.orderRelevantState;
|
||||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(16), decimals));
|
ZeroEx.toBaseUnitAmount(new BigNumber(16), decimals),
|
||||||
|
);
|
||||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(8), decimals));
|
ZeroEx.toBaseUnitAmount(new BigNumber(8), decimals),
|
||||||
done();
|
);
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||||
await zeroEx.exchange.fillOrderAsync(
|
await zeroEx.exchange.fillOrderAsync(
|
||||||
signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, taker,
|
signedOrder,
|
||||||
|
fillAmountInBaseUnits,
|
||||||
|
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||||
|
taker,
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('should equal approved amount when approved amount is lowest', (done: DoneCallback) => {
|
it('should equal approved amount when approved amount is lowest', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
|
|
||||||
const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
const orderRelevantState = validOrderState.orderRelevantState;
|
const orderRelevantState = validOrderState.orderRelevantState;
|
||||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||||
changedMakerApprovalAmount);
|
changedMakerApprovalAmount,
|
||||||
|
);
|
||||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||||
changedMakerApprovalAmount);
|
changedMakerApprovalAmount,
|
||||||
done();
|
);
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, changedMakerApprovalAmount);
|
await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, changedMakerApprovalAmount);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('should equal balance amount when balance amount is lowest', (done: DoneCallback) => {
|
it('should equal balance amount when balance amount is lowest', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
|
|
||||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||||
|
|
||||||
const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
||||||
const transferAmount = makerBalance.sub(remainingAmount);
|
const transferAmount = makerBalance.sub(remainingAmount);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.true();
|
expect(orderState.isValid).to.be.true();
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
const orderRelevantState = validOrderState.orderRelevantState;
|
const orderRelevantState = validOrderState.orderRelevantState;
|
||||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||||
remainingAmount);
|
remainingAmount,
|
||||||
|
);
|
||||||
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal(
|
||||||
remainingAmount);
|
remainingAmount,
|
||||||
done();
|
);
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.token.transferAsync(
|
await zeroEx.token.transferAsync(makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount);
|
||||||
makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount);
|
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('should equal remaining amount when partially cancelled and order has fees', (done: DoneCallback) => {
|
it('should equal remaining amount when partially cancelled and order has fees', (done: DoneCallback) => {
|
||||||
@@ -324,22 +382,29 @@ describe('OrderStateWatcher', () => {
|
|||||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||||
const feeRecipient = taker;
|
const feeRecipient = taker;
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
makerToken.address,
|
||||||
taker, fillableAmount, feeRecipient);
|
takerToken.address,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
|
feeRecipient,
|
||||||
|
);
|
||||||
|
|
||||||
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
||||||
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.true();
|
expect(orderState.isValid).to.be.true();
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
const orderRelevantState = validOrderState.orderRelevantState;
|
const orderRelevantState = validOrderState.orderRelevantState;
|
||||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||||
remainingTokenAmount);
|
remainingTokenAmount,
|
||||||
done();
|
);
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, transferTokenAmount);
|
await zeroEx.exchange.cancelOrderAsync(signedOrder, transferTokenAmount);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
@@ -349,26 +414,37 @@ describe('OrderStateWatcher', () => {
|
|||||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||||
const feeRecipient = taker;
|
const feeRecipient = taker;
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
makerToken.address,
|
||||||
taker, fillableAmount, feeRecipient);
|
takerToken.address,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
|
feeRecipient,
|
||||||
|
);
|
||||||
|
|
||||||
const remainingFeeAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
const remainingFeeAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||||
|
|
||||||
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
||||||
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
const orderRelevantState = validOrderState.orderRelevantState;
|
const orderRelevantState = validOrderState.orderRelevantState;
|
||||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||||
remainingFeeAmount);
|
remainingFeeAmount,
|
||||||
done();
|
);
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, remainingFeeAmount);
|
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, remainingFeeAmount);
|
||||||
await zeroEx.token.transferAsync(
|
await zeroEx.token.transferAsync(
|
||||||
makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferTokenAmount);
|
makerToken.address,
|
||||||
|
maker,
|
||||||
|
ZeroEx.NULL_ADDRESS,
|
||||||
|
transferTokenAmount,
|
||||||
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('should calculate full amount when all available and non-divisible', (done: DoneCallback) => {
|
it('should calculate full amount when all available and non-divisible', (done: DoneCallback) => {
|
||||||
@@ -377,40 +453,53 @@ describe('OrderStateWatcher', () => {
|
|||||||
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||||
const feeRecipient = taker;
|
const feeRecipient = taker;
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
makerToken.address,
|
||||||
taker, fillableAmount, feeRecipient);
|
takerToken.address,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
|
feeRecipient,
|
||||||
|
);
|
||||||
|
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
const orderRelevantState = validOrderState.orderRelevantState;
|
const orderRelevantState = validOrderState.orderRelevantState;
|
||||||
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal(
|
||||||
fillableAmount);
|
fillableAmount,
|
||||||
done();
|
);
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.token.setProxyAllowanceAsync(
|
await zeroEx.token.setProxyAllowanceAsync(
|
||||||
makerToken.address, maker, ZeroEx.toBaseUnitAmount(new BigNumber(100), decimals));
|
makerToken.address,
|
||||||
|
maker,
|
||||||
|
ZeroEx.toBaseUnitAmount(new BigNumber(100), decimals),
|
||||||
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should emit orderStateInvalid when watched order cancelled', (done: DoneCallback) => {
|
it('should emit orderStateInvalid when watched order cancelled', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
const invalidOrderState = orderState as OrderStateInvalid;
|
const invalidOrderState = orderState as OrderStateInvalid;
|
||||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
|
|
||||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
@@ -419,43 +508,50 @@ describe('OrderStateWatcher', () => {
|
|||||||
(async () => {
|
(async () => {
|
||||||
const remainingFillableAmountInBaseUnits = new BigNumber(100);
|
const remainingFillableAmountInBaseUnits = new BigNumber(100);
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.false();
|
expect(orderState.isValid).to.be.false();
|
||||||
const invalidOrderState = orderState as OrderStateInvalid;
|
const invalidOrderState = orderState as OrderStateInvalid;
|
||||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError);
|
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.exchange.cancelOrderAsync(
|
await zeroEx.exchange.cancelOrderAsync(
|
||||||
signedOrder, fillableAmount.minus(remainingFillableAmountInBaseUnits),
|
signedOrder,
|
||||||
|
fillableAmount.minus(remainingFillableAmountInBaseUnits),
|
||||||
);
|
);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('should emit orderStateValid when watched order partially cancelled', (done: DoneCallback) => {
|
it('should emit orderStateValid when watched order partially cancelled', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
|
|
||||||
const cancelAmountInBaseUnits = new BigNumber(2);
|
const cancelAmountInBaseUnits = new BigNumber(2);
|
||||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
orderStateWatcher.addOrder(signedOrder);
|
||||||
|
|
||||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||||
expect(orderState.isValid).to.be.true();
|
expect(orderState.isValid).to.be.true();
|
||||||
const validOrderState = orderState as OrderStateValid;
|
const validOrderState = orderState as OrderStateValid;
|
||||||
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
expect(validOrderState.orderHash).to.be.equal(orderHash);
|
||||||
const orderRelevantState = validOrderState.orderRelevantState;
|
const orderRelevantState = validOrderState.orderRelevantState;
|
||||||
expect(orderRelevantState.cancelledTakerTokenAmount).to.be.bignumber.equal(cancelAmountInBaseUnits);
|
expect(orderRelevantState.cancelledTakerTokenAmount).to.be.bignumber.equal(cancelAmountInBaseUnits);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
zeroEx.orderStateWatcher.subscribe(callback);
|
orderStateWatcher.subscribe(callback);
|
||||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmountInBaseUnits);
|
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmountInBaseUnits);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { BlockParamLiteral } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as Sinon from 'sinon';
|
import * as Sinon from 'sinon';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import {ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError} from '../src';
|
import { ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError } from '../src';
|
||||||
import {BlockParamLiteral, TradeSide, TransferType} from '../src/types';
|
import { TradeSide, TransferType } from '../src/types';
|
||||||
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
|
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
|
||||||
import {OrderValidationUtils} from '../src/utils/order_validation_utils';
|
import { OrderValidationUtils } from '../src/utils/order_validation_utils';
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {FillScenarios} from './utils/fill_scenarios';
|
import { FillScenarios } from './utils/fill_scenarios';
|
||||||
import {TokenUtils} from './utils/token_utils';
|
import { TokenUtils } from './utils/token_utils';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
describe('OrderValidation', () => {
|
describe('OrderValidation', () => {
|
||||||
let web3: Web3;
|
|
||||||
let zeroEx: ZeroEx;
|
let zeroEx: ZeroEx;
|
||||||
let userAddresses: string[];
|
let userAddresses: string[];
|
||||||
let tokens: Token[];
|
let tokens: Token[];
|
||||||
@@ -40,7 +40,6 @@ describe('OrderValidation', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
web3 = web3Factory.create();
|
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
@@ -62,108 +61,152 @@ describe('OrderValidation', () => {
|
|||||||
describe('validateOrderFillableOrThrowAsync', () => {
|
describe('validateOrderFillableOrThrowAsync', () => {
|
||||||
it('should succeed if the order is fillable', async () => {
|
it('should succeed if the order is fillable', async () => {
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
);
|
takerTokenAddress,
|
||||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
makerAddress,
|
||||||
signedOrder,
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
|
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||||
});
|
});
|
||||||
it('should succeed if the order is asymmetric and fillable', async () => {
|
it('should succeed if the order is asymmetric and fillable', async () => {
|
||||||
const makerFillableAmount = fillableAmount;
|
const makerFillableAmount = fillableAmount;
|
||||||
const takerFillableAmount = fillableAmount.minus(4);
|
const takerFillableAmount = fillableAmount.minus(4);
|
||||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
makerFillableAmount, takerFillableAmount,
|
takerTokenAddress,
|
||||||
);
|
makerAddress,
|
||||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
takerAddress,
|
||||||
signedOrder,
|
makerFillableAmount,
|
||||||
|
takerFillableAmount,
|
||||||
);
|
);
|
||||||
|
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||||
});
|
});
|
||||||
it('should throw when the order is fully filled or cancelled', async () => {
|
it('should throw when the order is fully filled or cancelled', async () => {
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||||
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith(
|
||||||
signedOrder,
|
ExchangeContractErrs.OrderRemainingFillAmountZero,
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
);
|
||||||
});
|
});
|
||||||
it('should throw when order is expired', async () => {
|
it('should throw when order is expired', async () => {
|
||||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
fillableAmount, expirationInPast,
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
expirationInPast,
|
||||||
|
);
|
||||||
|
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith(
|
||||||
|
ExchangeContractErrs.OrderFillExpired,
|
||||||
);
|
);
|
||||||
return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(
|
|
||||||
signedOrder,
|
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('validateFillOrderAndThrowIfInvalidAsync', () => {
|
describe('validateFillOrderAndThrowIfInvalidAsync', () => {
|
||||||
it('should throw when the fill amount is zero', async () => {
|
it('should throw when the fill amount is zero', async () => {
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const zeroFillAmount = new BigNumber(0);
|
const zeroFillAmount = new BigNumber(0);
|
||||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
return expect(
|
||||||
signedOrder, zeroFillAmount, takerAddress,
|
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, zeroFillAmount, takerAddress),
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
|
||||||
});
|
});
|
||||||
it('should throw when the signature is invalid', async () => {
|
it('should throw when the signature is invalid', async () => {
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
// 27 <--> 28
|
// 27 <--> 28
|
||||||
signedOrder.ecSignature.v = (28 - signedOrder.ecSignature.v) + 27;
|
signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27;
|
||||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
return expect(
|
||||||
signedOrder, fillableAmount, takerAddress,
|
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
|
||||||
)).to.be.rejectedWith(ZeroExError.InvalidSignature);
|
).to.be.rejectedWith(ZeroExError.InvalidSignature);
|
||||||
});
|
});
|
||||||
it('should throw when the order is fully filled or cancelled', async () => {
|
it('should throw when the order is fully filled or cancelled', async () => {
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
return expect(
|
||||||
signedOrder, fillableAmount, takerAddress,
|
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||||
});
|
});
|
||||||
it('should throw when sender is not a taker', async () => {
|
it('should throw when sender is not a taker', async () => {
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const nonTakerAddress = userAddresses[6];
|
const nonTakerAddress = userAddresses[6];
|
||||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
return expect(
|
||||||
signedOrder, fillTakerAmount, nonTakerAddress,
|
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillTakerAmount, nonTakerAddress),
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
|
).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
|
||||||
});
|
});
|
||||||
it('should throw when order is expired', async () => {
|
it('should throw when order is expired', async () => {
|
||||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
fillableAmount, expirationInPast,
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
expirationInPast,
|
||||||
);
|
);
|
||||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
return expect(
|
||||||
signedOrder, fillTakerAmount, takerAddress,
|
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillTakerAmount, takerAddress),
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
|
).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
|
||||||
});
|
});
|
||||||
it('should throw when there a rounding error would have occurred', async () => {
|
it('should throw when there a rounding error would have occurred', async () => {
|
||||||
const makerAmount = new BigNumber(3);
|
const makerAmount = new BigNumber(3);
|
||||||
const takerAmount = new BigNumber(5);
|
const takerAmount = new BigNumber(5);
|
||||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
makerAmount, takerAmount,
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
makerAmount,
|
||||||
|
takerAmount,
|
||||||
);
|
);
|
||||||
const fillTakerAmountThatCausesRoundingError = new BigNumber(3);
|
const fillTakerAmountThatCausesRoundingError = new BigNumber(3);
|
||||||
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
return expect(
|
||||||
signedOrder, fillTakerAmountThatCausesRoundingError, takerAddress,
|
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.OrderFillRoundingError);
|
signedOrder,
|
||||||
|
fillTakerAmountThatCausesRoundingError,
|
||||||
|
takerAddress,
|
||||||
|
),
|
||||||
|
).to.be.rejectedWith(ExchangeContractErrs.OrderFillRoundingError);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#validateFillOrKillOrderAndThrowIfInvalidAsync', () => {
|
describe('#validateFillOrKillOrderAndThrowIfInvalidAsync', () => {
|
||||||
it('should throw if remaining fillAmount is less then the desired fillAmount', async () => {
|
it('should throw if remaining fillAmount is less then the desired fillAmount', async () => {
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const tooLargeFillAmount = new BigNumber(7);
|
const tooLargeFillAmount = new BigNumber(7);
|
||||||
const fillAmountDifference = tooLargeFillAmount.minus(fillableAmount);
|
const fillAmountDifference = tooLargeFillAmount.minus(fillableAmount);
|
||||||
@@ -172,9 +215,13 @@ describe('OrderValidation', () => {
|
|||||||
await zeroEx.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference);
|
await zeroEx.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference);
|
||||||
await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount);
|
await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount);
|
||||||
|
|
||||||
return expect(zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync(
|
return expect(
|
||||||
signedOrder, tooLargeFillAmount, takerAddress,
|
zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||||
)).to.be.rejectedWith(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
signedOrder,
|
||||||
|
tooLargeFillAmount,
|
||||||
|
takerAddress,
|
||||||
|
),
|
||||||
|
).to.be.rejectedWith(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('validateCancelOrderAndThrowIfInvalidAsync', () => {
|
describe('validateCancelOrderAndThrowIfInvalidAsync', () => {
|
||||||
@@ -186,27 +233,38 @@ describe('OrderValidation', () => {
|
|||||||
makerTokenAddress = makerToken.address;
|
makerTokenAddress = makerToken.address;
|
||||||
takerTokenAddress = takerToken.address;
|
takerTokenAddress = takerToken.address;
|
||||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should throw when cancel amount is zero', async () => {
|
it('should throw when cancel amount is zero', async () => {
|
||||||
const zeroCancelAmount = new BigNumber(0);
|
const zeroCancelAmount = new BigNumber(0);
|
||||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount))
|
return expect(
|
||||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount),
|
||||||
|
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
|
||||||
});
|
});
|
||||||
it('should throw when order is expired', async () => {
|
it('should throw when order is expired', async () => {
|
||||||
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
|
||||||
const expiredSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
const expiredSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
fillableAmount, expirationInPast,
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
expirationInPast,
|
||||||
);
|
);
|
||||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount))
|
return expect(
|
||||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
|
zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount),
|
||||||
|
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
|
||||||
});
|
});
|
||||||
it('should throw when order is already cancelled or filled', async () => {
|
it('should throw when order is already cancelled or filled', async () => {
|
||||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount))
|
return expect(
|
||||||
.to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
|
zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount),
|
||||||
|
).to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#validateFillOrderBalancesAllowancesThrowIfInvalidAsync', () => {
|
describe('#validateFillOrderBalancesAllowancesThrowIfInvalidAsync', () => {
|
||||||
@@ -224,82 +282,159 @@ describe('OrderValidation', () => {
|
|||||||
const makerFee = new BigNumber(2);
|
const makerFee = new BigNumber(2);
|
||||||
const takerFee = new BigNumber(2);
|
const takerFee = new BigNumber(2);
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
|
makerTokenAddress,
|
||||||
makerAddress, takerAddress, fillableAmount, feeRecipient,
|
takerTokenAddress,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
feeRecipient,
|
||||||
);
|
);
|
||||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||||
exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
|
exchangeTransferSimulator,
|
||||||
|
signedOrder,
|
||||||
|
fillableAmount,
|
||||||
|
takerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
);
|
);
|
||||||
expect(transferFromAsync.callCount).to.be.equal(4);
|
expect(transferFromAsync.callCount).to.be.equal(4);
|
||||||
expect(
|
expect(
|
||||||
transferFromAsync.getCall(0).calledWith(
|
transferFromAsync
|
||||||
makerTokenAddress, makerAddress, takerAddress, bigNumberMatch(fillableAmount),
|
.getCall(0)
|
||||||
TradeSide.Maker, TransferType.Trade,
|
.calledWith(
|
||||||
),
|
makerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
bigNumberMatch(fillableAmount),
|
||||||
|
TradeSide.Maker,
|
||||||
|
TransferType.Trade,
|
||||||
|
),
|
||||||
).to.be.true();
|
).to.be.true();
|
||||||
expect(
|
expect(
|
||||||
transferFromAsync.getCall(1).calledWith(
|
transferFromAsync
|
||||||
takerTokenAddress, takerAddress, makerAddress, bigNumberMatch(fillableAmount),
|
.getCall(1)
|
||||||
TradeSide.Taker, TransferType.Trade,
|
.calledWith(
|
||||||
),
|
takerTokenAddress,
|
||||||
|
takerAddress,
|
||||||
|
makerAddress,
|
||||||
|
bigNumberMatch(fillableAmount),
|
||||||
|
TradeSide.Taker,
|
||||||
|
TransferType.Trade,
|
||||||
|
),
|
||||||
).to.be.true();
|
).to.be.true();
|
||||||
expect(
|
expect(
|
||||||
transferFromAsync.getCall(2).calledWith(
|
transferFromAsync
|
||||||
zrxTokenAddress, makerAddress, feeRecipient, bigNumberMatch(makerFee),
|
.getCall(2)
|
||||||
TradeSide.Maker, TransferType.Fee,
|
.calledWith(
|
||||||
),
|
zrxTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
feeRecipient,
|
||||||
|
bigNumberMatch(makerFee),
|
||||||
|
TradeSide.Maker,
|
||||||
|
TransferType.Fee,
|
||||||
|
),
|
||||||
).to.be.true();
|
).to.be.true();
|
||||||
expect(
|
expect(
|
||||||
transferFromAsync.getCall(3).calledWith(
|
transferFromAsync
|
||||||
zrxTokenAddress, takerAddress, feeRecipient, bigNumberMatch(takerFee),
|
.getCall(3)
|
||||||
TradeSide.Taker, TransferType.Fee,
|
.calledWith(
|
||||||
),
|
zrxTokenAddress,
|
||||||
|
takerAddress,
|
||||||
|
feeRecipient,
|
||||||
|
bigNumberMatch(takerFee),
|
||||||
|
TradeSide.Taker,
|
||||||
|
TransferType.Fee,
|
||||||
|
),
|
||||||
).to.be.true();
|
).to.be.true();
|
||||||
});
|
});
|
||||||
it('should call exchangeTransferSimulator.transferFrom with correct values for an open order', async () => {
|
it('should call exchangeTransferSimulator.transferFrom with correct values for an open order', async () => {
|
||||||
const makerFee = new BigNumber(2);
|
const makerFee = new BigNumber(2);
|
||||||
const takerFee = new BigNumber(2);
|
const takerFee = new BigNumber(2);
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
|
makerTokenAddress,
|
||||||
makerAddress, ZeroEx.NULL_ADDRESS, fillableAmount, feeRecipient,
|
takerTokenAddress,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
makerAddress,
|
||||||
|
ZeroEx.NULL_ADDRESS,
|
||||||
|
fillableAmount,
|
||||||
|
feeRecipient,
|
||||||
);
|
);
|
||||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||||
exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
|
exchangeTransferSimulator,
|
||||||
|
signedOrder,
|
||||||
|
fillableAmount,
|
||||||
|
takerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
);
|
);
|
||||||
expect(transferFromAsync.callCount).to.be.equal(4);
|
expect(transferFromAsync.callCount).to.be.equal(4);
|
||||||
expect(
|
expect(
|
||||||
transferFromAsync.getCall(0).calledWith(
|
transferFromAsync
|
||||||
makerTokenAddress, makerAddress, takerAddress, bigNumberMatch(fillableAmount),
|
.getCall(0)
|
||||||
TradeSide.Maker, TransferType.Trade,
|
.calledWith(
|
||||||
),
|
makerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
bigNumberMatch(fillableAmount),
|
||||||
|
TradeSide.Maker,
|
||||||
|
TransferType.Trade,
|
||||||
|
),
|
||||||
).to.be.true();
|
).to.be.true();
|
||||||
expect(
|
expect(
|
||||||
transferFromAsync.getCall(1).calledWith(
|
transferFromAsync
|
||||||
takerTokenAddress, takerAddress, makerAddress, bigNumberMatch(fillableAmount),
|
.getCall(1)
|
||||||
TradeSide.Taker, TransferType.Trade,
|
.calledWith(
|
||||||
),
|
takerTokenAddress,
|
||||||
|
takerAddress,
|
||||||
|
makerAddress,
|
||||||
|
bigNumberMatch(fillableAmount),
|
||||||
|
TradeSide.Taker,
|
||||||
|
TransferType.Trade,
|
||||||
|
),
|
||||||
).to.be.true();
|
).to.be.true();
|
||||||
expect(
|
expect(
|
||||||
transferFromAsync.getCall(2).calledWith(
|
transferFromAsync
|
||||||
zrxTokenAddress, makerAddress, feeRecipient, bigNumberMatch(makerFee),
|
.getCall(2)
|
||||||
TradeSide.Maker, TransferType.Fee,
|
.calledWith(
|
||||||
),
|
zrxTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
feeRecipient,
|
||||||
|
bigNumberMatch(makerFee),
|
||||||
|
TradeSide.Maker,
|
||||||
|
TransferType.Fee,
|
||||||
|
),
|
||||||
).to.be.true();
|
).to.be.true();
|
||||||
expect(
|
expect(
|
||||||
transferFromAsync.getCall(3).calledWith(
|
transferFromAsync
|
||||||
zrxTokenAddress, takerAddress, feeRecipient, bigNumberMatch(takerFee),
|
.getCall(3)
|
||||||
TradeSide.Taker, TransferType.Fee,
|
.calledWith(
|
||||||
),
|
zrxTokenAddress,
|
||||||
|
takerAddress,
|
||||||
|
feeRecipient,
|
||||||
|
bigNumberMatch(takerFee),
|
||||||
|
TradeSide.Taker,
|
||||||
|
TransferType.Fee,
|
||||||
|
),
|
||||||
).to.be.true();
|
).to.be.true();
|
||||||
});
|
});
|
||||||
it('should correctly round the fillMakerTokenAmount', async () => {
|
it('should correctly round the fillMakerTokenAmount', async () => {
|
||||||
const makerTokenAmount = new BigNumber(3);
|
const makerTokenAmount = new BigNumber(3);
|
||||||
const takerTokenAmount = new BigNumber(1);
|
const takerTokenAmount = new BigNumber(1);
|
||||||
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, makerTokenAmount, takerTokenAmount,
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
makerTokenAmount,
|
||||||
|
takerTokenAmount,
|
||||||
);
|
);
|
||||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||||
exchangeTransferSimulator, signedOrder, takerTokenAmount, takerAddress, zrxTokenAddress,
|
exchangeTransferSimulator,
|
||||||
|
signedOrder,
|
||||||
|
takerTokenAmount,
|
||||||
|
takerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
);
|
);
|
||||||
expect(transferFromAsync.callCount).to.be.equal(4);
|
expect(transferFromAsync.callCount).to.be.equal(4);
|
||||||
const makerFillAmount = transferFromAsync.getCall(0).args[3];
|
const makerFillAmount = transferFromAsync.getCall(0).args[3];
|
||||||
@@ -309,12 +444,22 @@ describe('OrderValidation', () => {
|
|||||||
const makerFee = new BigNumber(2);
|
const makerFee = new BigNumber(2);
|
||||||
const takerFee = new BigNumber(4);
|
const takerFee = new BigNumber(4);
|
||||||
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
fillableAmount, ZeroEx.NULL_ADDRESS,
|
takerTokenAddress,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
ZeroEx.NULL_ADDRESS,
|
||||||
);
|
);
|
||||||
const fillTakerTokenAmount = fillableAmount.div(2).round(0);
|
const fillTakerTokenAmount = fillableAmount.div(2).round(0);
|
||||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||||
exchangeTransferSimulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress,
|
exchangeTransferSimulator,
|
||||||
|
signedOrder,
|
||||||
|
fillTakerTokenAmount,
|
||||||
|
takerAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
);
|
);
|
||||||
const makerPartialFee = makerFee.div(2);
|
const makerPartialFee = makerFee.div(2);
|
||||||
const takerPartialFee = takerFee.div(2);
|
const takerPartialFee = takerFee.div(2);
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import { ECSignature, SignedOrder } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
|
||||||
import {ZeroEx} from '../src/0x';
|
import { ZeroEx } from '../src/0x';
|
||||||
import {RemainingFillableCalculator} from '../src/order_watcher/remaining_fillable_calculator';
|
import { RemainingFillableCalculator } from '../src/order_watcher/remaining_fillable_calculator';
|
||||||
import {ECSignature, SignedOrder} from '../src/types';
|
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -26,29 +26,34 @@ describe('RemainingFillableCalculator', () => {
|
|||||||
const decimals: number = 4;
|
const decimals: number = 4;
|
||||||
const zero: BigNumber = new BigNumber(0);
|
const zero: BigNumber = new BigNumber(0);
|
||||||
const zeroAddress = '0x0';
|
const zeroAddress = '0x0';
|
||||||
const signature: ECSignature = {v: 27, r: '', s: ''};
|
const signature: ECSignature = { v: 27, r: '', s: '' };
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
[makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
[makerAmount, takerAmount, makerFeeAmount] = [
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
|
ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals)];
|
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
|
||||||
|
ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals),
|
||||||
|
];
|
||||||
[transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount] = [
|
[transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount] = [
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals)];
|
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
|
||||||
|
];
|
||||||
});
|
});
|
||||||
function buildSignedOrder(): SignedOrder {
|
function buildSignedOrder(): SignedOrder {
|
||||||
return { ecSignature: signature,
|
return {
|
||||||
exchangeContractAddress: zeroAddress,
|
ecSignature: signature,
|
||||||
feeRecipient: zeroAddress,
|
exchangeContractAddress: zeroAddress,
|
||||||
maker: zeroAddress,
|
feeRecipient: zeroAddress,
|
||||||
taker: zeroAddress,
|
maker: zeroAddress,
|
||||||
makerFee: makerFeeAmount,
|
taker: zeroAddress,
|
||||||
takerFee: zero,
|
makerFee: makerFeeAmount,
|
||||||
makerTokenAmount: makerAmount,
|
takerFee: zero,
|
||||||
takerTokenAmount: takerAmount,
|
makerTokenAmount: makerAmount,
|
||||||
makerTokenAddress: makerToken,
|
takerTokenAmount: takerAmount,
|
||||||
takerTokenAddress: takerToken,
|
makerTokenAddress: makerToken,
|
||||||
salt: zero,
|
takerTokenAddress: takerToken,
|
||||||
expirationUnixTimestampSec: zero };
|
salt: zero,
|
||||||
|
expirationUnixTimestampSec: zero,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
describe('Maker token is NOT ZRX', () => {
|
describe('Maker token is NOT ZRX', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
@@ -57,23 +62,38 @@ describe('RemainingFillableCalculator', () => {
|
|||||||
it('calculates the correct amount when unfilled and funds available', () => {
|
it('calculates the correct amount when unfilled and funds available', () => {
|
||||||
signedOrder = buildSignedOrder();
|
signedOrder = buildSignedOrder();
|
||||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
signedOrder,
|
||||||
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
||||||
});
|
});
|
||||||
it('calculates the correct amount when partially filled and funds available', () => {
|
it('calculates the correct amount when partially filled and funds available', () => {
|
||||||
signedOrder = buildSignedOrder();
|
signedOrder = buildSignedOrder();
|
||||||
remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
signedOrder,
|
||||||
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
||||||
});
|
});
|
||||||
it('calculates the amount to be 0 when all fee funds are transferred', () => {
|
it('calculates the amount to be 0 when all fee funds are transferred', () => {
|
||||||
signedOrder = buildSignedOrder();
|
signedOrder = buildSignedOrder();
|
||||||
transferrableMakerFeeTokenAmount = zero;
|
transferrableMakerFeeTokenAmount = zero;
|
||||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
signedOrder,
|
||||||
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
|
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
|
||||||
});
|
});
|
||||||
it('calculates the correct amount when balance is less than remaining fillable', () => {
|
it('calculates the correct amount when balance is less than remaining fillable', () => {
|
||||||
@@ -81,41 +101,58 @@ describe('RemainingFillableCalculator', () => {
|
|||||||
const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount);
|
remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount);
|
||||||
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount);
|
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount);
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
signedOrder,
|
||||||
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
|
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
|
||||||
});
|
});
|
||||||
describe('Order to Fee Ratio is < 1', () => {
|
describe('Order to Fee Ratio is < 1', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
[makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
|
[makerAmount, takerAmount, makerFeeAmount] = [
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
|
ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals)];
|
ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
|
||||||
|
ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals),
|
||||||
|
];
|
||||||
});
|
});
|
||||||
it('calculates the correct amount when funds unavailable', () => {
|
it('calculates the correct amount when funds unavailable', () => {
|
||||||
signedOrder = buildSignedOrder();
|
signedOrder = buildSignedOrder();
|
||||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||||
const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||||
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
|
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount,
|
signedOrder,
|
||||||
remainingMakerTokenAmount);
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
|
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(transferrableMakerTokenAmount);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('Ratio is not evenly divisble', () => {
|
describe('Ratio is not evenly divisble', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
[makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
|
[makerAmount, takerAmount, makerFeeAmount] = [
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
|
ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals),
|
||||||
ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals)];
|
ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
|
||||||
|
ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals),
|
||||||
|
];
|
||||||
});
|
});
|
||||||
it('calculates the correct amount when funds unavailable', () => {
|
it('calculates the correct amount when funds unavailable', () => {
|
||||||
signedOrder = buildSignedOrder();
|
signedOrder = buildSignedOrder();
|
||||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||||
const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||||
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
|
transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount);
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount,
|
signedOrder,
|
||||||
remainingMakerTokenAmount);
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
|
const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
|
||||||
expect(calculatedFillableAmount.lessThanOrEqualTo(transferrableMakerTokenAmount)).to.be.true();
|
expect(calculatedFillableAmount.lessThanOrEqualTo(transferrableMakerTokenAmount)).to.be.true();
|
||||||
expect(calculatedFillableAmount).to.be.bignumber.greaterThan(new BigNumber(0));
|
expect(calculatedFillableAmount).to.be.bignumber.greaterThan(new BigNumber(0));
|
||||||
@@ -134,15 +171,25 @@ describe('RemainingFillableCalculator', () => {
|
|||||||
transferrableMakerTokenAmount = makerAmount.plus(makerFeeAmount);
|
transferrableMakerTokenAmount = makerAmount.plus(makerFeeAmount);
|
||||||
transferrableMakerFeeTokenAmount = transferrableMakerTokenAmount;
|
transferrableMakerFeeTokenAmount = transferrableMakerTokenAmount;
|
||||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
signedOrder,
|
||||||
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
||||||
});
|
});
|
||||||
it('calculates the correct amount when partially filled and funds available', () => {
|
it('calculates the correct amount when partially filled and funds available', () => {
|
||||||
signedOrder = buildSignedOrder();
|
signedOrder = buildSignedOrder();
|
||||||
remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals);
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
signedOrder,
|
||||||
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(remainingMakerTokenAmount);
|
||||||
});
|
});
|
||||||
it('calculates the amount to be 0 when all fee funds are transferred', () => {
|
it('calculates the amount to be 0 when all fee funds are transferred', () => {
|
||||||
@@ -150,8 +197,13 @@ describe('RemainingFillableCalculator', () => {
|
|||||||
transferrableMakerTokenAmount = zero;
|
transferrableMakerTokenAmount = zero;
|
||||||
transferrableMakerFeeTokenAmount = zero;
|
transferrableMakerFeeTokenAmount = zero;
|
||||||
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
remainingMakerTokenAmount = signedOrder.makerTokenAmount;
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
signedOrder,
|
||||||
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
|
expect(calculator.computeRemainingMakerFillable()).to.be.bignumber.equal(zero);
|
||||||
});
|
});
|
||||||
it('calculates the correct amount when balance is less than remaining fillable', () => {
|
it('calculates the correct amount when balance is less than remaining fillable', () => {
|
||||||
@@ -163,8 +215,13 @@ describe('RemainingFillableCalculator', () => {
|
|||||||
|
|
||||||
const orderToFeeRatio = signedOrder.makerTokenAmount.dividedToIntegerBy(signedOrder.makerFee);
|
const orderToFeeRatio = signedOrder.makerTokenAmount.dividedToIntegerBy(signedOrder.makerFee);
|
||||||
const expectedFillableAmount = new BigNumber(450980);
|
const expectedFillableAmount = new BigNumber(450980);
|
||||||
calculator = new RemainingFillableCalculator(signedOrder, isMakerTokenZRX,
|
calculator = new RemainingFillableCalculator(
|
||||||
transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount, remainingMakerTokenAmount);
|
signedOrder,
|
||||||
|
isMakerTokenZRX,
|
||||||
|
transferrableMakerTokenAmount,
|
||||||
|
transferrableMakerFeeTokenAmount,
|
||||||
|
remainingMakerTokenAmount,
|
||||||
|
);
|
||||||
const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
|
const calculatedFillableAmount = calculator.computeRemainingMakerFillable();
|
||||||
const numberOfFillsInRatio = calculatedFillableAmount.dividedToIntegerBy(orderToFeeRatio);
|
const numberOfFillsInRatio = calculatedFillableAmount.dividedToIntegerBy(orderToFeeRatio);
|
||||||
const calculatedFillableAmountPlusFees = calculatedFillableAmount.plus(numberOfFillsInRatio);
|
const calculatedFillableAmountPlusFees = calculatedFillableAmount.plus(numberOfFillsInRatio);
|
||||||
|
|||||||
@@ -1,31 +1,22 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as chai from 'chai';
|
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
import * as Sinon from 'sinon';
|
import * as Sinon from 'sinon';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
import {
|
import { ApprovalContractEventArgs, DecodedLogEvent, Token, TokenEvents, ZeroEx } from '../src';
|
||||||
ApprovalContractEventArgs,
|
import { DoneCallback } from '../src/types';
|
||||||
DecodedLogEvent,
|
|
||||||
Token,
|
|
||||||
TokenEvents,
|
|
||||||
ZeroEx,
|
|
||||||
} from '../src';
|
|
||||||
import {DoneCallback} from '../src/types';
|
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
import { assertNodeCallbackError } from './utils/report_callback_errors';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
|
||||||
|
|
||||||
describe('SubscriptionTest', () => {
|
describe('SubscriptionTest', () => {
|
||||||
let web3: Web3;
|
|
||||||
let zeroEx: ZeroEx;
|
let zeroEx: ZeroEx;
|
||||||
let userAddresses: string[];
|
let userAddresses: string[];
|
||||||
let tokens: Token[];
|
let tokens: Token[];
|
||||||
@@ -35,7 +26,6 @@ describe('SubscriptionTest', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
web3 = web3Factory.create();
|
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
@@ -65,50 +55,26 @@ describe('SubscriptionTest', () => {
|
|||||||
it('Should receive the Error when an error occurs while fetching the block', (done: DoneCallback) => {
|
it('Should receive the Error when an error occurs while fetching the block', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const errMsg = 'Error fetching block';
|
const errMsg = 'Error fetching block';
|
||||||
const callback = reportCallbackErrors(done)(
|
const callback = assertNodeCallbackError(done, errMsg);
|
||||||
(err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error(errMsg))];
|
||||||
expect(err.message).to.be.equal(errMsg);
|
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||||
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);
|
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Should receive the Error when an error occurs while reconciling the new block', (done: DoneCallback) => {
|
it('Should receive the Error when an error occurs while reconciling the new block', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const errMsg = 'Error fetching logs';
|
const errMsg = 'Error fetching logs';
|
||||||
const callback = reportCallbackErrors(done)(
|
const callback = assertNodeCallbackError(done, errMsg);
|
||||||
(err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getLogsAsync').throws(new Error(errMsg))];
|
||||||
expect(err.message).to.be.equal(errMsg);
|
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||||
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);
|
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
|
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => _.noop;
|
const callback = (err: Error | null, logEvent?: DecodedLogEvent<ApprovalContractEventArgs>) => _.noop;
|
||||||
zeroEx.token.subscribe(
|
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error('JSON RPC error'))];
|
||||||
stubs = [
|
|
||||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync')
|
|
||||||
.throws(new Error('JSON RPC error')),
|
|
||||||
];
|
|
||||||
zeroEx.token.unsubscribeAll();
|
zeroEx.token.unsubscribeAll();
|
||||||
done();
|
done();
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||||
import {schemas, SchemaValidator} from '@0xproject/json-schemas';
|
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
|
||||||
import {Token, ZeroEx} from '../src';
|
import { Token, ZeroEx } from '../src';
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7;
|
const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7;
|
||||||
|
|
||||||
describe('TokenRegistryWrapper', () => {
|
describe('TokenRegistryWrapper', () => {
|
||||||
let zeroEx: ZeroEx;
|
let zeroEx: ZeroEx;
|
||||||
let tokens: Token[];
|
let tokens: Token[];
|
||||||
const tokenAddressBySymbol: {[symbol: string]: string} = {};
|
const tokenAddressBySymbol: { [symbol: string]: string } = {};
|
||||||
const tokenAddressByName: {[symbol: string]: string} = {};
|
const tokenAddressByName: { [symbol: string]: string } = {};
|
||||||
const tokenBySymbol: {[symbol: string]: Token} = {};
|
const tokenBySymbol: { [symbol: string]: Token } = {};
|
||||||
const tokenByName: {[symbol: string]: Token} = {};
|
const tokenByName: { [symbol: string]: Token } = {};
|
||||||
const registeredSymbol = 'ZRX';
|
const registeredSymbol = 'ZRX';
|
||||||
const registeredName = '0x Protocol Token';
|
const registeredName = '0x Protocol Token';
|
||||||
const unregisteredSymbol = 'MAL';
|
const unregisteredSymbol = 'MAL';
|
||||||
@@ -31,7 +31,6 @@ describe('TokenRegistryWrapper', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const web3 = web3Factory.create();
|
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
_.map(tokens, token => {
|
_.map(tokens, token => {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
|
import { web3Factory } from '@0xproject/dev-utils';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
|
|
||||||
import {ZeroEx} from '../src';
|
import { ZeroEx } from '../src';
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
const web3 = web3Factory.create();
|
||||||
|
|
||||||
describe('TokenTransferProxyWrapper', () => {
|
describe('TokenTransferProxyWrapper', () => {
|
||||||
let zeroEx: ZeroEx;
|
let zeroEx: ZeroEx;
|
||||||
@@ -15,7 +16,6 @@ describe('TokenTransferProxyWrapper', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const web3 = web3Factory.create();
|
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||||
});
|
});
|
||||||
describe('#isAuthorizedAsync', () => {
|
describe('#isAuthorizedAsync', () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
import * as Web3 from 'web3';
|
import * as Web3 from 'web3';
|
||||||
@@ -16,33 +16,30 @@ import {
|
|||||||
ZeroEx,
|
ZeroEx,
|
||||||
ZeroExError,
|
ZeroExError,
|
||||||
} from '../src';
|
} from '../src';
|
||||||
import {DoneCallback} from '../src/types';
|
import { DoneCallback } from '../src/types';
|
||||||
|
|
||||||
import {chaiSetup} from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import {constants} from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import {TokenUtils} from './utils/token_utils';
|
import { reportNodeCallbackErrors } from './utils/report_callback_errors';
|
||||||
import {web3Factory} from './utils/web3_factory';
|
import { TokenUtils } from './utils/token_utils';
|
||||||
|
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
describe('TokenWrapper', () => {
|
describe('TokenWrapper', () => {
|
||||||
let web3: Web3;
|
|
||||||
let zeroEx: ZeroEx;
|
let zeroEx: ZeroEx;
|
||||||
let userAddresses: string[];
|
let userAddresses: string[];
|
||||||
let tokens: Token[];
|
let tokens: Token[];
|
||||||
let tokenUtils: TokenUtils;
|
let tokenUtils: TokenUtils;
|
||||||
let coinbase: string;
|
let coinbase: string;
|
||||||
let addressWithoutFunds: string;
|
let addressWithoutFunds: string;
|
||||||
let web3Wrapper: Web3Wrapper;
|
|
||||||
const config = {
|
const config = {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
web3 = web3Factory.create();
|
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||||
web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
tokenUtils = new TokenUtils(tokens);
|
tokenUtils = new TokenUtils(tokens);
|
||||||
@@ -74,17 +71,17 @@ describe('TokenWrapper', () => {
|
|||||||
it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => {
|
it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => {
|
||||||
const fromAddress = addressWithoutFunds;
|
const fromAddress = addressWithoutFunds;
|
||||||
const toAddress = coinbase;
|
const toAddress = coinbase;
|
||||||
return expect(zeroEx.token.transferAsync(
|
return expect(
|
||||||
token.address, fromAddress, toAddress, transferAmount,
|
zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount),
|
||||||
)).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
||||||
});
|
});
|
||||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||||
const fromAddress = coinbase;
|
const fromAddress = coinbase;
|
||||||
const toAddress = coinbase;
|
const toAddress = coinbase;
|
||||||
return expect(zeroEx.token.transferAsync(
|
return expect(
|
||||||
nonExistentTokenAddress, fromAddress, toAddress, transferAmount,
|
zeroEx.token.transferAsync(nonExistentTokenAddress, fromAddress, toAddress, transferAmount),
|
||||||
)).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#transferFromAsync', () => {
|
describe('#transferFromAsync', () => {
|
||||||
@@ -103,24 +100,22 @@ describe('TokenWrapper', () => {
|
|||||||
const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
|
const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress);
|
||||||
expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount);
|
expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount);
|
||||||
|
|
||||||
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress,
|
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress, toAddress);
|
||||||
toAddress);
|
|
||||||
expect(fromAddressAllowance).to.be.bignumber.equal(0);
|
expect(fromAddressAllowance).to.be.bignumber.equal(0);
|
||||||
|
|
||||||
return expect(zeroEx.token.transferFromAsync(
|
return expect(
|
||||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
|
||||||
)).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
||||||
});
|
});
|
||||||
it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress',
|
it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress', async () => {
|
||||||
async () => {
|
|
||||||
const fromAddress = coinbase;
|
const fromAddress = coinbase;
|
||||||
const transferAmount = new BigNumber(42);
|
const transferAmount = new BigNumber(42);
|
||||||
|
|
||||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount);
|
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount);
|
||||||
|
|
||||||
return expect(zeroEx.token.transferFromAsync(
|
return expect(
|
||||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
|
||||||
)).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer);
|
||||||
});
|
});
|
||||||
it('should fail to transfer tokens if fromAddress has insufficient balance', async () => {
|
it('should fail to transfer tokens if fromAddress has insufficient balance', async () => {
|
||||||
const fromAddress = addressWithoutFunds;
|
const fromAddress = addressWithoutFunds;
|
||||||
@@ -130,13 +125,16 @@ describe('TokenWrapper', () => {
|
|||||||
expect(fromAddressBalance).to.be.bignumber.equal(0);
|
expect(fromAddressBalance).to.be.bignumber.equal(0);
|
||||||
|
|
||||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
|
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
|
||||||
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress,
|
const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(
|
||||||
senderAddress);
|
token.address,
|
||||||
|
fromAddress,
|
||||||
|
senderAddress,
|
||||||
|
);
|
||||||
expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount);
|
expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount);
|
||||||
|
|
||||||
return expect(zeroEx.token.transferFromAsync(
|
return expect(
|
||||||
token.address, fromAddress, toAddress, senderAddress, transferAmount,
|
zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount),
|
||||||
)).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer);
|
||||||
});
|
});
|
||||||
it('should successfully transfer tokens', async () => {
|
it('should successfully transfer tokens', async () => {
|
||||||
const fromAddress = coinbase;
|
const fromAddress = coinbase;
|
||||||
@@ -147,17 +145,22 @@ describe('TokenWrapper', () => {
|
|||||||
const transferAmount = new BigNumber(42);
|
const transferAmount = new BigNumber(42);
|
||||||
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
|
await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
|
||||||
|
|
||||||
await zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress,
|
await zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount);
|
||||||
transferAmount);
|
|
||||||
const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||||
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
||||||
});
|
});
|
||||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||||
const fromAddress = coinbase;
|
const fromAddress = coinbase;
|
||||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||||
return expect(zeroEx.token.transferFromAsync(
|
return expect(
|
||||||
nonExistentTokenAddress, fromAddress, toAddress, senderAddress, new BigNumber(42),
|
zeroEx.token.transferFromAsync(
|
||||||
)).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
nonExistentTokenAddress,
|
||||||
|
fromAddress,
|
||||||
|
toAddress,
|
||||||
|
senderAddress,
|
||||||
|
new BigNumber(42),
|
||||||
|
),
|
||||||
|
).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getBalanceAsync', () => {
|
describe('#getBalanceAsync', () => {
|
||||||
@@ -172,8 +175,9 @@ describe('TokenWrapper', () => {
|
|||||||
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
|
||||||
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
|
||||||
const ownerAddress = coinbase;
|
const ownerAddress = coinbase;
|
||||||
return expect(zeroEx.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress))
|
return expect(zeroEx.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress)).to.be.rejectedWith(
|
||||||
.to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist);
|
ZeroExError.TokenContractDoesNotExist,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
it('should return a balance of 0 for a non-existent owner address', async () => {
|
it('should return a balance of 0 for a non-existent owner address', async () => {
|
||||||
const token = tokens[0];
|
const token = tokens[0];
|
||||||
@@ -187,26 +191,29 @@ describe('TokenWrapper', () => {
|
|||||||
let zeroExWithoutAccounts: ZeroEx;
|
let zeroExWithoutAccounts: ZeroEx;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const hasAddresses = false;
|
const hasAddresses = false;
|
||||||
const web3WithoutAccounts = web3Factory.create(hasAddresses);
|
const web3WithoutAccounts = web3Factory.create({ hasAddresses });
|
||||||
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
||||||
});
|
});
|
||||||
it('should return balance even when called with Web3 provider instance without addresses', async () => {
|
it('should return balance even when called with Web3 provider instance without addresses', async () => {
|
||||||
const token = tokens[0];
|
const token = tokens[0];
|
||||||
const ownerAddress = coinbase;
|
const ownerAddress = coinbase;
|
||||||
const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress);
|
const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress);
|
||||||
const expectedBalance = new BigNumber('1000000000000000000000000000');
|
const expectedBalance = new BigNumber('1000000000000000000000000000');
|
||||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#setAllowanceAsync', () => {
|
describe('#setAllowanceAsync', () => {
|
||||||
it('should set the spender\'s allowance', async () => {
|
it("should set the spender's allowance", async () => {
|
||||||
const token = tokens[0];
|
const token = tokens[0];
|
||||||
const ownerAddress = coinbase;
|
const ownerAddress = coinbase;
|
||||||
const spenderAddress = addressWithoutFunds;
|
const spenderAddress = addressWithoutFunds;
|
||||||
|
|
||||||
const allowanceBeforeSet = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress,
|
const allowanceBeforeSet = await zeroEx.token.getAllowanceAsync(
|
||||||
spenderAddress);
|
token.address,
|
||||||
|
ownerAddress,
|
||||||
|
spenderAddress,
|
||||||
|
);
|
||||||
const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
|
const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
|
||||||
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
|
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
|
||||||
|
|
||||||
@@ -219,7 +226,7 @@ describe('TokenWrapper', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#setUnlimitedAllowanceAsync', () => {
|
describe('#setUnlimitedAllowanceAsync', () => {
|
||||||
it('should set the unlimited spender\'s allowance', async () => {
|
it("should set the unlimited spender's allowance", async () => {
|
||||||
const token = tokens[0];
|
const token = tokens[0];
|
||||||
const ownerAddress = coinbase;
|
const ownerAddress = coinbase;
|
||||||
const spenderAddress = addressWithoutFunds;
|
const spenderAddress = addressWithoutFunds;
|
||||||
@@ -241,10 +248,18 @@ describe('TokenWrapper', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await zeroEx.token.transferFromAsync(
|
await zeroEx.token.transferFromAsync(
|
||||||
zrx.address, coinbase, userWithNormalAllowance, userWithNormalAllowance, transferAmount,
|
zrx.address,
|
||||||
|
coinbase,
|
||||||
|
userWithNormalAllowance,
|
||||||
|
userWithNormalAllowance,
|
||||||
|
transferAmount,
|
||||||
);
|
);
|
||||||
await zeroEx.token.transferFromAsync(
|
await zeroEx.token.transferFromAsync(
|
||||||
zrx.address, coinbase, userWithUnlimitedAllowance, userWithUnlimitedAllowance, transferAmount,
|
zrx.address,
|
||||||
|
coinbase,
|
||||||
|
userWithUnlimitedAllowance,
|
||||||
|
userWithUnlimitedAllowance,
|
||||||
|
transferAmount,
|
||||||
);
|
);
|
||||||
|
|
||||||
const finalBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
const finalBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
||||||
@@ -288,7 +303,7 @@ describe('TokenWrapper', () => {
|
|||||||
let zeroExWithoutAccounts: ZeroEx;
|
let zeroExWithoutAccounts: ZeroEx;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const hasAddresses = false;
|
const hasAddresses = false;
|
||||||
const web3WithoutAccounts = web3Factory.create(hasAddresses);
|
const web3WithoutAccounts = web3Factory.create({ hasAddresses });
|
||||||
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
||||||
});
|
});
|
||||||
it('should get the proxy allowance', async () => {
|
it('should get the proxy allowance', async () => {
|
||||||
@@ -300,7 +315,9 @@ describe('TokenWrapper', () => {
|
|||||||
await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
|
await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits);
|
||||||
|
|
||||||
const allowance = await zeroExWithoutAccounts.token.getAllowanceAsync(
|
const allowance = await zeroExWithoutAccounts.token.getAllowanceAsync(
|
||||||
token.address, ownerAddress, spenderAddress,
|
token.address,
|
||||||
|
ownerAddress,
|
||||||
|
spenderAddress,
|
||||||
);
|
);
|
||||||
const expectedAllowance = amountInBaseUnits;
|
const expectedAllowance = amountInBaseUnits;
|
||||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||||
@@ -366,65 +383,66 @@ describe('TokenWrapper', () => {
|
|||||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callback = (err: Error, logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
|
const callback = reportNodeCallbackErrors(done)(
|
||||||
expect(logEvent).to.not.be.undefined();
|
(logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
|
||||||
expect(logEvent.isRemoved).to.be.false();
|
expect(logEvent.isRemoved).to.be.false();
|
||||||
expect(logEvent.log.logIndex).to.be.equal(0);
|
expect(logEvent.log.logIndex).to.be.equal(0);
|
||||||
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
||||||
expect(logEvent.log.blockNumber).to.be.a('number');
|
expect(logEvent.log.blockNumber).to.be.a('number');
|
||||||
const args = logEvent.log.args;
|
const args = logEvent.log.args;
|
||||||
expect(args._from).to.be.equal(coinbase);
|
expect(args._from).to.be.equal(coinbase);
|
||||||
expect(args._to).to.be.equal(addressWithoutFunds);
|
expect(args._to).to.be.equal(addressWithoutFunds);
|
||||||
expect(args._value).to.be.bignumber.equal(transferAmount);
|
expect(args._value).to.be.bignumber.equal(transferAmount);
|
||||||
done();
|
},
|
||||||
};
|
);
|
||||||
zeroEx.token.subscribe(
|
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callback);
|
||||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callback);
|
|
||||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
const callback = reportNodeCallbackErrors(done)(
|
||||||
expect(logEvent).to.not.be.undefined();
|
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||||
expect(logEvent.isRemoved).to.be.false();
|
expect(logEvent).to.not.be.undefined();
|
||||||
const args = logEvent.log.args;
|
expect(logEvent.isRemoved).to.be.false();
|
||||||
expect(args._owner).to.be.equal(coinbase);
|
const args = logEvent.log.args;
|
||||||
expect(args._spender).to.be.equal(addressWithoutFunds);
|
expect(args._owner).to.be.equal(coinbase);
|
||||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
expect(args._spender).to.be.equal(addressWithoutFunds);
|
||||||
done();
|
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||||
};
|
},
|
||||||
zeroEx.token.subscribe(
|
);
|
||||||
tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||||
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => {
|
it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
|
||||||
done(new Error('Expected this subscription to have been cancelled'));
|
(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>) => {
|
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
||||||
done();
|
const callbackToBeCalled = reportNodeCallbackErrors(done)();
|
||||||
};
|
|
||||||
const newProvider = web3Factory.getRpcProvider();
|
const newProvider = web3Factory.getRpcProvider();
|
||||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||||
zeroEx.token.subscribe(
|
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled);
|
||||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled,
|
|
||||||
);
|
|
||||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
const callbackNeverToBeCalled = reportNodeCallbackErrors(done)(
|
||||||
done(new Error('Expected this subscription to have been cancelled'));
|
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||||
};
|
done(new Error('Expected this subscription to have been cancelled'));
|
||||||
|
},
|
||||||
|
);
|
||||||
const subscriptionToken = zeroEx.token.subscribe(
|
const subscriptionToken = zeroEx.token.subscribe(
|
||||||
tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
tokenAddress,
|
||||||
|
TokenEvents.Transfer,
|
||||||
|
indexFilterValues,
|
||||||
|
callbackNeverToBeCalled,
|
||||||
|
);
|
||||||
zeroEx.token.unsubscribe(subscriptionToken);
|
zeroEx.token.unsubscribe(subscriptionToken);
|
||||||
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
|
||||||
done();
|
done();
|
||||||
@@ -450,7 +468,10 @@ describe('TokenWrapper', () => {
|
|||||||
const eventName = TokenEvents.Approval;
|
const eventName = TokenEvents.Approval;
|
||||||
const indexFilterValues = {};
|
const indexFilterValues = {};
|
||||||
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
||||||
tokenAddress, eventName, blockRange, indexFilterValues,
|
tokenAddress,
|
||||||
|
eventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
);
|
);
|
||||||
expect(logs).to.have.length(1);
|
expect(logs).to.have.length(1);
|
||||||
const args = logs[0].args;
|
const args = logs[0].args;
|
||||||
@@ -465,7 +486,10 @@ describe('TokenWrapper', () => {
|
|||||||
const differentEventName = TokenEvents.Transfer;
|
const differentEventName = TokenEvents.Transfer;
|
||||||
const indexFilterValues = {};
|
const indexFilterValues = {};
|
||||||
const logs = await zeroEx.token.getLogsAsync(
|
const logs = await zeroEx.token.getLogsAsync(
|
||||||
tokenAddress, differentEventName, blockRange, indexFilterValues,
|
tokenAddress,
|
||||||
|
differentEventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
);
|
);
|
||||||
expect(logs).to.have.length(0);
|
expect(logs).to.have.length(0);
|
||||||
});
|
});
|
||||||
@@ -479,7 +503,10 @@ describe('TokenWrapper', () => {
|
|||||||
_owner: coinbase,
|
_owner: coinbase,
|
||||||
};
|
};
|
||||||
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
||||||
tokenAddress, eventName, blockRange, indexFilterValues,
|
tokenAddress,
|
||||||
|
eventName,
|
||||||
|
blockRange,
|
||||||
|
indexFilterValues,
|
||||||
);
|
);
|
||||||
expect(logs).to.have.length(1);
|
expect(logs).to.have.length(1);
|
||||||
const args = logs[0].args;
|
const args = logs[0].args;
|
||||||
@@ -487,3 +514,4 @@ describe('TokenWrapper', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// tslint:disable:max-file-line-count
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
export const constants = {
|
export const constants = {
|
||||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||||
RPC_URL: 'http://localhost:8545/',
|
|
||||||
ROPSTEN_NETWORK_ID: 3,
|
ROPSTEN_NETWORK_ID: 3,
|
||||||
KOVAN_NETWORK_ID: 42,
|
KOVAN_NETWORK_ID: 42,
|
||||||
TESTRPC_NETWORK_ID: 50,
|
TESTRPC_NETWORK_ID: 50,
|
||||||
KOVAN_RPC_URL: 'https://kovan.infura.io/',
|
KOVAN_RPC_URL: 'https://kovan.infura.io/',
|
||||||
ROPSTEN_RPC_URL: 'https://ropsten.infura.io/',
|
ROPSTEN_RPC_URL: 'https://ropsten.infura.io/',
|
||||||
ZRX_DECIMALS: 18,
|
ZRX_DECIMALS: 18,
|
||||||
GAS_ESTIMATE: 500000,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import BigNumber from 'bignumber.js';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
|
|
||||||
import {SignedOrder, Token, ZeroEx} from '../../src';
|
import { SignedOrder, Token, ZeroEx } from '../../src';
|
||||||
import {artifacts} from '../../src/artifacts';
|
import { artifacts } from '../../src/artifacts';
|
||||||
import {DummyTokenContract} from '../../src/contract_wrappers/generated/dummy_token';
|
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
|
||||||
import {orderFactory} from '../utils/order_factory';
|
import { orderFactory } from '../utils/order_factory';
|
||||||
|
|
||||||
import {constants} from './constants';
|
import { constants } from './constants';
|
||||||
|
|
||||||
const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100);
|
const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100);
|
||||||
|
|
||||||
@@ -17,8 +17,13 @@ export class FillScenarios {
|
|||||||
private _coinbase: string;
|
private _coinbase: string;
|
||||||
private _zrxTokenAddress: string;
|
private _zrxTokenAddress: string;
|
||||||
private _exchangeContractAddress: string;
|
private _exchangeContractAddress: string;
|
||||||
constructor(zeroEx: ZeroEx, userAddresses: string[],
|
constructor(
|
||||||
tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) {
|
zeroEx: ZeroEx,
|
||||||
|
userAddresses: string[],
|
||||||
|
tokens: Token[],
|
||||||
|
zrxTokenAddress: string,
|
||||||
|
exchangeContractAddress: string,
|
||||||
|
) {
|
||||||
this._zeroEx = zeroEx;
|
this._zeroEx = zeroEx;
|
||||||
this._userAddresses = userAddresses;
|
this._userAddresses = userAddresses;
|
||||||
this._tokens = tokens;
|
this._tokens = tokens;
|
||||||
@@ -30,11 +35,13 @@ export class FillScenarios {
|
|||||||
const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
|
const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
|
||||||
for (const token of this._tokens) {
|
for (const token of this._tokens) {
|
||||||
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
|
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
|
||||||
const contractInstance = web3Wrapper.getContractInstance(
|
|
||||||
artifacts.DummyTokenArtifact.abi, token.address,
|
|
||||||
);
|
|
||||||
const defaults = {};
|
const defaults = {};
|
||||||
const dummyToken = new DummyTokenContract(contractInstance, defaults);
|
const dummyToken = new DummyTokenContract(
|
||||||
|
artifacts.DummyTokenArtifact.abi,
|
||||||
|
token.address,
|
||||||
|
web3Wrapper.getProvider(),
|
||||||
|
web3Wrapper.getContractDefaults(),
|
||||||
|
);
|
||||||
const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
|
const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
|
||||||
const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
|
const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
|
||||||
from: this._coinbase,
|
from: this._coinbase,
|
||||||
@@ -43,61 +50,110 @@ export class FillScenarios {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
|
public async createFillableSignedOrderAsync(
|
||||||
makerAddress: string, takerAddress: string,
|
makerTokenAddress: string,
|
||||||
fillableAmount: BigNumber,
|
takerTokenAddress: string,
|
||||||
expirationUnixTimestampSec?: BigNumber):
|
makerAddress: string,
|
||||||
Promise<SignedOrder> {
|
takerAddress: string,
|
||||||
|
fillableAmount: BigNumber,
|
||||||
|
expirationUnixTimestampSec?: BigNumber,
|
||||||
|
): Promise<SignedOrder> {
|
||||||
return this.createAsymmetricFillableSignedOrderAsync(
|
return this.createAsymmetricFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
fillableAmount, fillableAmount, expirationUnixTimestampSec,
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
fillableAmount,
|
||||||
|
expirationUnixTimestampSec,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public async createFillableSignedOrderWithFeesAsync(
|
public async createFillableSignedOrderWithFeesAsync(
|
||||||
makerTokenAddress: string, takerTokenAddress: string,
|
makerTokenAddress: string,
|
||||||
makerFee: BigNumber, takerFee: BigNumber,
|
takerTokenAddress: string,
|
||||||
makerAddress: string, takerAddress: string,
|
makerFee: BigNumber,
|
||||||
|
takerFee: BigNumber,
|
||||||
|
makerAddress: string,
|
||||||
|
takerAddress: string,
|
||||||
fillableAmount: BigNumber,
|
fillableAmount: BigNumber,
|
||||||
feeRecepient: string, expirationUnixTimestampSec?: BigNumber,
|
feeRecepient: string,
|
||||||
|
expirationUnixTimestampSec?: BigNumber,
|
||||||
): Promise<SignedOrder> {
|
): Promise<SignedOrder> {
|
||||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
fillableAmount, fillableAmount, feeRecepient, expirationUnixTimestampSec,
|
takerTokenAddress,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
fillableAmount,
|
||||||
|
feeRecepient,
|
||||||
|
expirationUnixTimestampSec,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public async createAsymmetricFillableSignedOrderAsync(
|
public async createAsymmetricFillableSignedOrderAsync(
|
||||||
makerTokenAddress: string, takerTokenAddress: string, makerAddress: string, takerAddress: string,
|
makerTokenAddress: string,
|
||||||
makerFillableAmount: BigNumber, takerFillableAmount: BigNumber,
|
takerTokenAddress: string,
|
||||||
expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
|
makerAddress: string,
|
||||||
|
takerAddress: string,
|
||||||
|
makerFillableAmount: BigNumber,
|
||||||
|
takerFillableAmount: BigNumber,
|
||||||
|
expirationUnixTimestampSec?: BigNumber,
|
||||||
|
): Promise<SignedOrder> {
|
||||||
const makerFee = new BigNumber(0);
|
const makerFee = new BigNumber(0);
|
||||||
const takerFee = new BigNumber(0);
|
const takerFee = new BigNumber(0);
|
||||||
const feeRecepient = constants.NULL_ADDRESS;
|
const feeRecepient = constants.NULL_ADDRESS;
|
||||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerFee, takerFee, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
makerFillableAmount, takerFillableAmount, feeRecepient, expirationUnixTimestampSec,
|
takerTokenAddress,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
makerFillableAmount,
|
||||||
|
takerFillableAmount,
|
||||||
|
feeRecepient,
|
||||||
|
expirationUnixTimestampSec,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public async createPartiallyFilledSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
|
public async createPartiallyFilledSignedOrderAsync(
|
||||||
takerAddress: string, fillableAmount: BigNumber,
|
makerTokenAddress: string,
|
||||||
partialFillAmount: BigNumber) {
|
takerTokenAddress: string,
|
||||||
|
takerAddress: string,
|
||||||
|
fillableAmount: BigNumber,
|
||||||
|
partialFillAmount: BigNumber,
|
||||||
|
) {
|
||||||
const [makerAddress] = this._userAddresses;
|
const [makerAddress] = this._userAddresses;
|
||||||
const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
|
const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
|
||||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
makerTokenAddress,
|
||||||
fillableAmount, fillableAmount,
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
fillableAmount,
|
||||||
);
|
);
|
||||||
const shouldThrowOnInsufficientBalanceOrAllowance = false;
|
const shouldThrowOnInsufficientBalanceOrAllowance = false;
|
||||||
await this._zeroEx.exchange.fillOrderAsync(
|
await this._zeroEx.exchange.fillOrderAsync(
|
||||||
signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress,
|
signedOrder,
|
||||||
|
partialFillAmount,
|
||||||
|
shouldThrowOnInsufficientBalanceOrAllowance,
|
||||||
|
takerAddress,
|
||||||
);
|
);
|
||||||
return signedOrder;
|
return signedOrder;
|
||||||
}
|
}
|
||||||
private async _createAsymmetricFillableSignedOrderWithFeesAsync(
|
private async _createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||||
makerTokenAddress: string, takerTokenAddress: string,
|
makerTokenAddress: string,
|
||||||
makerFee: BigNumber, takerFee: BigNumber,
|
takerTokenAddress: string,
|
||||||
makerAddress: string, takerAddress: string,
|
makerFee: BigNumber,
|
||||||
makerFillableAmount: BigNumber, takerFillableAmount: BigNumber,
|
takerFee: BigNumber,
|
||||||
feeRecepient: string, expirationUnixTimestampSec?: BigNumber): Promise<SignedOrder> {
|
makerAddress: string,
|
||||||
|
takerAddress: string,
|
||||||
|
makerFillableAmount: BigNumber,
|
||||||
|
takerFillableAmount: BigNumber,
|
||||||
|
feeRecepient: string,
|
||||||
|
expirationUnixTimestampSec?: BigNumber,
|
||||||
|
): Promise<SignedOrder> {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
|
this._increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
|
||||||
this._increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
|
this._increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
|
||||||
@@ -107,14 +163,27 @@ export class FillScenarios {
|
|||||||
this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
|
this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const signedOrder = await orderFactory.createSignedOrderAsync(this._zeroEx,
|
const signedOrder = await orderFactory.createSignedOrderAsync(
|
||||||
makerAddress, takerAddress, makerFee, takerFee,
|
this._zeroEx,
|
||||||
makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress,
|
makerAddress,
|
||||||
this._exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
|
takerAddress,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
makerFillableAmount,
|
||||||
|
makerTokenAddress,
|
||||||
|
takerFillableAmount,
|
||||||
|
takerTokenAddress,
|
||||||
|
this._exchangeContractAddress,
|
||||||
|
feeRecepient,
|
||||||
|
expirationUnixTimestampSec,
|
||||||
|
);
|
||||||
return signedOrder;
|
return signedOrder;
|
||||||
}
|
}
|
||||||
private async _increaseBalanceAndAllowanceAsync(
|
private async _increaseBalanceAndAllowanceAsync(
|
||||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
tokenAddress: string,
|
||||||
|
address: string,
|
||||||
|
amount: BigNumber,
|
||||||
|
): Promise<void> {
|
||||||
if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
|
if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) {
|
||||||
return; // noop
|
return; // noop
|
||||||
}
|
}
|
||||||
@@ -123,16 +192,12 @@ export class FillScenarios {
|
|||||||
this._increaseAllowanceAsync(tokenAddress, address, amount),
|
this._increaseAllowanceAsync(tokenAddress, address, amount),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
private async _increaseBalanceAsync(
|
private async _increaseBalanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
|
||||||
await this._zeroEx.token.transferAsync(tokenAddress, this._coinbase, address, amount);
|
await this._zeroEx.token.transferAsync(tokenAddress, this._coinbase, address, amount);
|
||||||
}
|
}
|
||||||
private async _increaseAllowanceAsync(
|
private async _increaseAllowanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||||
tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
|
||||||
const oldMakerAllowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, address);
|
const oldMakerAllowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, address);
|
||||||
const newMakerAllowance = oldMakerAllowance.plus(amount);
|
const newMakerAllowance = oldMakerAllowance.plus(amount);
|
||||||
await this._zeroEx.token.setProxyAllowanceAsync(
|
await this._zeroEx.token.setProxyAllowanceAsync(tokenAddress, address, newMakerAllowance);
|
||||||
tokenAddress, address, newMakerAllowance,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {SignedOrder, ZeroEx} from '../../src';
|
import { SignedOrder, ZeroEx } from '../../src';
|
||||||
|
|
||||||
|
const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false;
|
||||||
|
|
||||||
export const orderFactory = {
|
export const orderFactory = {
|
||||||
async createSignedOrderAsync(
|
async createSignedOrderAsync(
|
||||||
@@ -16,11 +18,12 @@ export const orderFactory = {
|
|||||||
takerTokenAddress: string,
|
takerTokenAddress: string,
|
||||||
exchangeContractAddress: string,
|
exchangeContractAddress: string,
|
||||||
feeRecipient: string,
|
feeRecipient: string,
|
||||||
expirationUnixTimestampSecIfExists?: BigNumber): Promise<SignedOrder> {
|
expirationUnixTimestampSecIfExists?: BigNumber,
|
||||||
|
): Promise<SignedOrder> {
|
||||||
const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite
|
const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite
|
||||||
const expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSecIfExists) ?
|
const expirationUnixTimestampSec = _.isUndefined(expirationUnixTimestampSecIfExists)
|
||||||
defaultExpirationUnixTimestampSec :
|
? defaultExpirationUnixTimestampSec
|
||||||
expirationUnixTimestampSecIfExists;
|
: expirationUnixTimestampSecIfExists;
|
||||||
const order = {
|
const order = {
|
||||||
maker,
|
maker,
|
||||||
taker,
|
taker,
|
||||||
@@ -36,8 +39,8 @@ export const orderFactory = {
|
|||||||
expirationUnixTimestampSec,
|
expirationUnixTimestampSec,
|
||||||
};
|
};
|
||||||
const orderHash = ZeroEx.getOrderHashHex(order);
|
const orderHash = ZeroEx.getOrderHashHex(order);
|
||||||
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker);
|
const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker, SHOULD_ADD_PERSONAL_MESSAGE_PREFIX);
|
||||||
const signedOrder: SignedOrder = _.assign(order, {ecSignature});
|
const signedOrder: SignedOrder = _.assign(order, { ecSignature });
|
||||||
return signedOrder;
|
return signedOrder;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
import {DoneCallback} from '../../src/types';
|
import * as chai from 'chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
export const reportCallbackErrors = (done: DoneCallback) => {
|
import { DoneCallback } from '../../src/types';
|
||||||
return (f: (...args: any[]) => void) => {
|
|
||||||
const wrapped = async (...args: any[]) => {
|
const expect = chai.expect;
|
||||||
|
|
||||||
|
export const reportNoErrorCallbackErrors = (done: DoneCallback, expectToBeCalledOnce = true) => {
|
||||||
|
return <T>(f?: (value: T) => void) => {
|
||||||
|
const wrapped = (value: T) => {
|
||||||
|
if (_.isUndefined(f)) {
|
||||||
|
done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
f(...args);
|
f(value);
|
||||||
|
if (expectToBeCalledOnce) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
done(err);
|
done(err);
|
||||||
}
|
}
|
||||||
@@ -12,3 +24,43 @@ export const reportCallbackErrors = (done: DoneCallback) => {
|
|||||||
return wrapped;
|
return wrapped;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const reportNodeCallbackErrors = (done: DoneCallback, expectToBeCalledOnce = true) => {
|
||||||
|
return <T>(f?: (value: T) => void) => {
|
||||||
|
const wrapped = (error: Error | null, value: T | undefined) => {
|
||||||
|
if (!_.isNull(error)) {
|
||||||
|
done(error);
|
||||||
|
} else {
|
||||||
|
if (_.isUndefined(f)) {
|
||||||
|
done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
f(value as T);
|
||||||
|
if (expectToBeCalledOnce) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return wrapped;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const assertNodeCallbackError = (done: DoneCallback, errMsg: string) => {
|
||||||
|
const wrapped = <T>(error: Error | null, value: T | undefined) => {
|
||||||
|
if (_.isNull(error)) {
|
||||||
|
done(new Error('Expected callback to receive an error'));
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
expect(error.message).to.be.equal(errMsg);
|
||||||
|
done();
|
||||||
|
} 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,6 @@
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import {InternalZeroExError, Token} from '../../src/types';
|
import { InternalZeroExError, Token } from '../../src/types';
|
||||||
|
|
||||||
const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
|
const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
|
||||||
const WETH_TOKEN_SYMBOL = 'WETH';
|
const WETH_TOKEN_SYMBOL = 'WETH';
|
||||||
@@ -11,14 +11,14 @@ export class TokenUtils {
|
|||||||
this._tokens = tokens;
|
this._tokens = tokens;
|
||||||
}
|
}
|
||||||
public getProtocolTokenOrThrow(): Token {
|
public getProtocolTokenOrThrow(): Token {
|
||||||
const zrxToken = _.find(this._tokens, {symbol: PROTOCOL_TOKEN_SYMBOL});
|
const zrxToken = _.find(this._tokens, { symbol: PROTOCOL_TOKEN_SYMBOL });
|
||||||
if (_.isUndefined(zrxToken)) {
|
if (_.isUndefined(zrxToken)) {
|
||||||
throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
|
throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
|
||||||
}
|
}
|
||||||
return zrxToken;
|
return zrxToken;
|
||||||
}
|
}
|
||||||
public getWethTokenOrThrow(): Token {
|
public getWethTokenOrThrow(): Token {
|
||||||
const wethToken = _.find(this._tokens, {symbol: WETH_TOKEN_SYMBOL});
|
const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL });
|
||||||
if (_.isUndefined(wethToken)) {
|
if (_.isUndefined(wethToken)) {
|
||||||
throw new Error(InternalZeroExError.WethNotInTokenRegistry);
|
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;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
6
packages/0x.js/test/utils/web3_wrapper.ts
Normal file
6
packages/0x.js/test/utils/web3_wrapper.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { web3Factory } from '@0xproject/dev-utils';
|
||||||
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
|
import * as Web3 from 'web3';
|
||||||
|
|
||||||
|
export const web3 = web3Factory.create();
|
||||||
|
export const web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
||||||
@@ -1,22 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"extends": "../../tsconfig",
|
||||||
"module": "commonjs",
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"outDir": "lib"
|
||||||
"lib": [ "es2015", "dom" ],
|
},
|
||||||
"outDir": "lib",
|
"include": ["./src/**/*", "./test/**/*"]
|
||||||
"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"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
{
|
{
|
||||||
"extends": [
|
"extends": ["@0xproject/tslint-config"]
|
||||||
"@0xproject/tslint-config"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ const path = require('path');
|
|||||||
const production = process.env.NODE_ENV === 'production';
|
const production = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
let entry = {
|
let entry = {
|
||||||
'index': './src/index.ts',
|
index: './src/index.ts',
|
||||||
};
|
};
|
||||||
if (production) {
|
if (production) {
|
||||||
entry = _.assign({}, entry, {'index.min': './src/index.ts'});
|
entry = _.assign({}, entry, { 'index.min': './src/index.ts' });
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
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/
|
||||||
102
packages/abi-gen/CHANGELOG.json
Normal file
102
packages/abi-gen/CHANGELOG.json
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"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,43 @@
|
|||||||
# 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.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,114 @@ 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.
|
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.
|
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.
|
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.js/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files.
|
[Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
`yarn add -g @0xproject/abi-gen`
|
`yarn add -g @0xproject/abi-gen`
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
abi-gen
|
abi-gen
|
||||||
Options:
|
Options:
|
||||||
--help Show help [boolean]
|
--help Show help [boolean]
|
||||||
--version Show version number [boolean]
|
--version Show version number [boolean]
|
||||||
--abiGlob Glob pattern to search for ABI JSON files [string] [required]
|
--abis Glob pattern to search for ABI JSON files
|
||||||
--templates Folder where to search for templates [string] [required]
|
[string] [required]
|
||||||
--output Folder where to put the output 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.
|
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.
|
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?
|
## 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.
|
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.
|
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?
|
## 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.
|
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
|
||||||
|
|
||||||
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.
|
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
|
||||||
|
|
||||||
|
If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn lerna:rebuild
|
||||||
|
```
|
||||||
|
|
||||||
|
Or continuously rebuild on change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also build this specific package by running the following from within its directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn build
|
||||||
|
```
|
||||||
|
|
||||||
|
or continuously rebuild on change:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn build:watch
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clean
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn clean
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lint
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn lint
|
||||||
|
```
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user