Compare commits
211 Commits
@0xproject
...
@0xproject
Author | SHA1 | Date | |
---|---|---|---|
|
3fc99dbad5 | ||
|
01dd84dced | ||
|
6b92ef733c | ||
|
fe0f4ae257 | ||
|
cf9555debc | ||
|
528008b1a9 | ||
|
5e3576ed69 | ||
|
28ee9e247e | ||
|
a054b485d0 | ||
|
3585326d7e | ||
|
a6046af024 | ||
|
adaff92c92 | ||
|
0499541e11 | ||
|
f08738e133 | ||
|
1fbdc14734 | ||
|
3e683162e9 | ||
|
8e7937bdb6 | ||
|
b36587fac8 | ||
|
3a1f9d01e8 | ||
|
1131d66b3d | ||
|
7104ae4752 | ||
|
2403323463 | ||
|
feb7dfffa1 | ||
|
005e633e2a | ||
|
127fe971e9 | ||
|
3c4bde6ea1 | ||
|
dc19690863 | ||
|
47604384d4 | ||
|
c69984e309 | ||
|
5682cd0048 | ||
|
2896110d4d | ||
|
d05b175e04 | ||
|
10a379077c | ||
|
ffd9b79100 | ||
|
04c07d9006 | ||
|
a3cc5c1dd7 | ||
|
941342cc24 | ||
|
cc471dd127 | ||
|
9b535e3cec | ||
|
9656895726 | ||
|
121b6949a1 | ||
|
fb31c49317 | ||
|
e51f9b3593 | ||
|
d08bfbf705 | ||
|
a10e466fed | ||
|
35bb010c35 | ||
|
0046a0762c | ||
|
c453012a8e | ||
|
1f82c7eadf | ||
|
b6fb8dbb52 | ||
|
30256cbe51 | ||
|
7f46e9af2c | ||
|
417cec9e04 | ||
|
62a55c0135 | ||
|
72336eb393 | ||
|
12d8c0b6af | ||
|
5c232b6a8d | ||
|
f6fd4281a4 | ||
|
4bee63afc6 | ||
|
d186f6148b | ||
|
2b15c03b9a | ||
|
60d879e045 | ||
|
858d1768ce | ||
|
fc2b7f747b | ||
|
207019c7f3 | ||
|
b264bbea84 | ||
|
32efb3e280 | ||
|
1a0d68d49a | ||
|
7dd3b2d38b | ||
|
4bc65faf1a | ||
|
8634551f53 | ||
|
089663ccc1 | ||
|
d1d26f8bf6 | ||
|
1ca86730fa | ||
|
12ae7c009d | ||
|
51b2fce8c1 | ||
|
62fcb51e1a | ||
|
cbc55f2ef8 | ||
|
679f828e4e | ||
|
4a8b4e7398 | ||
|
b6a11ca31e | ||
|
a30ccf2b25 | ||
|
2574405699 | ||
|
3ba78553f0 | ||
|
4d485fc424 | ||
|
85f28ade86 | ||
|
f6f2991a44 | ||
|
4ea222bbff | ||
|
f9f5e04b41 | ||
|
ea6706a2af | ||
|
64c5c5eb40 | ||
|
823f2db09f | ||
|
a71e511f82 | ||
|
39c0064ffb | ||
|
12d5c35d14 | ||
|
1a161cc02e | ||
|
96f19ba8da | ||
|
a63dfb7995 | ||
|
97ea1e300a | ||
|
d87d93dfac | ||
|
3ffcb03d87 | ||
|
33b08b90a3 | ||
|
cbca2061f7 | ||
|
bf4873e519 | ||
|
8fc1b38ff2 | ||
|
7d957538b4 | ||
|
7a8edb5018 | ||
|
2193d9ae6e | ||
|
79d01fe2d7 | ||
|
0d02037a12 | ||
|
d263f7783f | ||
|
d8ef76fd5e | ||
|
bc3c7a30c4 | ||
|
7b318b3cc2 | ||
|
e5cf41b313 | ||
|
74012ad584 | ||
|
06b4f007f8 | ||
|
a9cf425410 | ||
|
5355da6cad | ||
|
38f7c4a0d2 | ||
|
1fcf3c5dc4 | ||
|
20b0afacf5 | ||
|
6dbe8dbc50 | ||
|
73e23996a6 | ||
|
e40bce253c | ||
|
74c279ea3a | ||
|
6c13b792f9 | ||
|
6be7466c4a | ||
|
1dbdd7ee1f | ||
|
eb89926cee | ||
|
7923ff4ac6 | ||
|
783314c037 | ||
|
15cf64318c | ||
|
442017f93a | ||
|
4dd9f29769 | ||
|
f2f9bd2e7a | ||
|
d95b8ef3e1 | ||
|
ed0c64fdcf | ||
|
9a91e39b3f | ||
|
ce3f25d48f | ||
|
b669508c34 | ||
|
364d8824af | ||
|
749354b1c0 | ||
|
be73084e04 | ||
|
5eb90697c8 | ||
|
faedd2fa0b | ||
|
c47fb8f9a8 | ||
|
27b915789e | ||
|
ddc6dca98c | ||
|
72aa3d3005 | ||
|
e8d4f6d532 | ||
|
3c84ce2050 | ||
|
9db1ce7ceb | ||
|
e472f7899f | ||
|
b053781453 | ||
|
f892b7dbf6 | ||
|
b146acc69e | ||
|
63b941fbaf | ||
|
29dc22e208 | ||
|
41bd0e30d6 | ||
|
40f4dd91e9 | ||
|
5bf43a3560 | ||
|
f0afc0ae45 | ||
|
916b4d3a26 | ||
|
6d1a587c5c | ||
|
bce97c2543 | ||
|
34446cf569 | ||
|
1e13e927d0 | ||
|
3c0fa0b7e6 | ||
|
ad894fbdbb | ||
|
7d9c6eafbf | ||
|
de6f757ec8 | ||
|
3eeb8f4d6d | ||
|
f44ef7ce59 | ||
|
b08c616713 | ||
|
3ad693d334 | ||
|
4aa67e2925 | ||
|
260ab2d413 | ||
|
a824957de7 | ||
|
4017c172a2 | ||
|
65b2c936ab | ||
|
eee190826a | ||
|
20a1deb187 | ||
|
9169913a2c | ||
|
bf0ef055fb | ||
|
4e4842a62f | ||
|
a34c9095c3 | ||
|
84a4b7d1c1 | ||
|
5b69cd4a22 | ||
|
c80b42712a | ||
|
8d76d74a17 | ||
|
6f72fed8b5 | ||
|
27575e9866 | ||
|
986ba175ce | ||
|
919b327fc5 | ||
|
e05b55d4a5 | ||
|
6f24337a53 | ||
|
0e8f5004d6 | ||
|
22fa5a57a5 | ||
|
e30c76b743 | ||
|
75a51af006 | ||
|
24454938e5 | ||
|
89a72ebf0d | ||
|
20aaab0847 | ||
|
3e648cfb7e | ||
|
2106d7476d | ||
|
43e07e7ce3 | ||
|
5e4e27fed5 | ||
|
6c02722f56 | ||
|
5cfebd2680 | ||
|
bd20b1747d |
@@ -124,6 +124,10 @@ jobs:
|
|||||||
key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
paths:
|
paths:
|
||||||
- ~/repo/packages/sol-cov/coverage/lcov.info
|
- ~/repo/packages/sol-cov/coverage/lcov.info
|
||||||
|
- save_cache:
|
||||||
|
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
paths:
|
||||||
|
- ~/repo/packages/metacoin/coverage/lcov.info
|
||||||
lint:
|
lint:
|
||||||
working_directory: ~/repo
|
working_directory: ~/repo
|
||||||
docker:
|
docker:
|
||||||
@@ -177,15 +181,18 @@ jobs:
|
|||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
|
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
- run: yarn report_coverage
|
- run: yarn report_coverage
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
main:
|
main:
|
||||||
jobs:
|
jobs:
|
||||||
- build
|
- build
|
||||||
# - test-installation:
|
- test-installation:
|
||||||
# requires:
|
requires:
|
||||||
# - build
|
- build
|
||||||
- test-0xjs:
|
- test-0xjs:
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -74,7 +74,10 @@ packages/react-docs/example/public/bundle*
|
|||||||
bin/
|
bin/
|
||||||
|
|
||||||
# generated contract artifacts
|
# generated contract artifacts
|
||||||
packages/contracts/src/artifacts
|
packages/sol-cov/test/fixtures/artifacts
|
||||||
|
packages/metacoin/artifacts
|
||||||
|
packages/0x.js/test/artifacts
|
||||||
|
packages/migrations/src/artifacts
|
||||||
|
|
||||||
# generated contract wrappers
|
# generated contract wrappers
|
||||||
packages/0x.js/src/contract_wrappers/generated/
|
packages/0x.js/src/contract_wrappers/generated/
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
lib
|
lib
|
||||||
.nyc_output
|
.nyc_output
|
||||||
/packages/contracts/src/artifacts
|
/packages/contracts/src/artifacts
|
||||||
|
/packages/metacoin/artifacts
|
||||||
|
/packages/migrations/src/artifacts
|
||||||
package.json
|
package.json
|
||||||
scripts/postpublish_utils.js
|
scripts/postpublish_utils.js
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
* @abandeali1 @BMillman19 @dekz @fabioberger @LogvinovLeon @Recmo
|
|
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at team@0xproject.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
@@ -36,7 +36,6 @@
|
|||||||
|
|
||||||
* [ ] Change requires a change to the documentation.
|
* [ ] Change requires a change to the documentation.
|
||||||
* [ ] Added tests to cover my changes.
|
* [ ] Added tests to cover my changes.
|
||||||
* [ ] Added new entries to the relevant CHANGELOGs.
|
* [ ] Added new entries to the relevant CHANGELOG.jsons.
|
||||||
* [ ] 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 'WIP' label if it is a work in progress.
|
||||||
* [ ] Labeled this PR with the labels corresponding to the changed package.
|
* [ ] Labeled this PR with the labels corresponding to the changed package.
|
||||||
|
25
README.md
25
README.md
@@ -14,7 +14,6 @@ This repository is a monorepo including the 0x protocol smart contracts and nume
|
|||||||
[](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/)
|
|
||||||
|
|
||||||
### Published Packages
|
### Published Packages
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ This repository is a monorepo including the 0x protocol smart contracts and nume
|
|||||||
| [`@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-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/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/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/sol-cov`](/packages/sol-cov) | [](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
|
||||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
| [`@0xproject/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/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/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||||
@@ -74,7 +73,7 @@ You can include those by prepending @0xproject/typescript-typings package to you
|
|||||||
|
|
||||||
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.
|
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||||
|
|
||||||
Please read our [contribution guidelines](./CONTRIBUTING.md) before getting started.
|
#### Read our [contribution guidelines](./CONTRIBUTING.md).
|
||||||
|
|
||||||
### Install dependencies
|
### Install dependencies
|
||||||
|
|
||||||
@@ -118,24 +117,6 @@ yarn lerna:run lint
|
|||||||
|
|
||||||
### Run Tests
|
### Run Tests
|
||||||
|
|
||||||
Before running the tests, you will need to spin up a [TestRPC](https://www.npmjs.com/package/ethereumjs-testrpc) instance and deploy all the 0x smart contracts.
|
|
||||||
|
|
||||||
In a separate terminal, start TestRPC (a convenience command is provided as part of this repo)
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn testrpc
|
yarn lerna:test
|
||||||
```
|
|
||||||
|
|
||||||
Then in your main terminal run
|
|
||||||
|
|
||||||
```
|
|
||||||
cd packages/contracts
|
|
||||||
yarn migrate
|
|
||||||
cd ..
|
|
||||||
```
|
|
||||||
|
|
||||||
And finally from the root project directory run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn lerna:run test
|
|
||||||
```
|
```
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
"test:installation": "node ./packages/monorepo-scripts/lib/test_installation.js",
|
"test:installation": "node ./packages/monorepo-scripts/lib/test_installation.js",
|
||||||
"lerna:install": "yarn install",
|
"lerna:install": "yarn install",
|
||||||
"lerna:run": "lerna run",
|
"lerna:run": "lerna run",
|
||||||
|
"lerna:test": "lerna run test",
|
||||||
"lerna:clean": "lerna run clean",
|
"lerna:clean": "lerna run clean",
|
||||||
"lerna:build": "lerna run build",
|
"lerna:build": "lerna run build",
|
||||||
"lerna:rebuild": "run-s lerna:clean lerna:build",
|
"lerna:rebuild": "run-s lerna:clean lerna:build",
|
||||||
|
@@ -1,10 +1,68 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "0.37.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Fixed expiration watcher comparator to handle orders with equal expiration times",
|
||||||
|
"pr": 526
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Update Web3 Provider Engine to 14.0.4",
|
||||||
|
"pr": 555
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add `zeroEx.getProvider()`",
|
||||||
|
"pr": 559
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Move `ZeroExError.InvalidSignature` to `@0xproject/order-utils` `OrderError.InvalidSignature`",
|
||||||
|
"pr": 559
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1525428773
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.36.3",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Move @0xproject/migrations to devDependencies"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1524079658
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1524073495,
|
||||||
|
"version": "0.36.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.36.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Internal changes and refactoring"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fix redundant expired order removal bug",
|
||||||
|
"pr": 527
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1524044013
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "0.36.0",
|
"version": "0.36.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
{
|
{
|
||||||
"note": "Moved Web3.Provider to `@0xproject/types:Provider`",
|
"note": "Moved Web3.Provider to `@0xproject/types:Provider`",
|
||||||
"pr": 501
|
"pr": 501
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note":
|
||||||
|
"Add `zeroEx.exchange.getOrderStateAsync` to allow obtaining current OrderState for a signedOrder",
|
||||||
|
"pr": 510
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"timestamp": 1523462196
|
"timestamp": 1523462196
|
||||||
@@ -14,7 +72,7 @@
|
|||||||
"changes": [
|
"changes": [
|
||||||
{
|
{
|
||||||
"note":
|
"note":
|
||||||
"Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3_wrapper' `Web3WrapperErrors.TransactionMiningTimeout`",
|
"Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3-wrapper' `Web3WrapperErrors.TransactionMiningTimeout`",
|
||||||
"pr": 485
|
"pr": 485
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@@ -5,13 +5,34 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v0.37.0 - _May 4, 2018_
|
||||||
|
|
||||||
|
* Fixed expiration watcher comparator to handle orders with equal expiration times (#526)
|
||||||
|
* Update Web3 Provider Engine to 14.0.4 (#555)
|
||||||
|
* Add `zeroEx.getProvider()` (#559)
|
||||||
|
* Move `ZeroExError.InvalidSignature` to `@0xproject/order-utils` `OrderError.InvalidSignature` (#559)
|
||||||
|
|
||||||
|
## v0.36.3 - _April 18, 2018_
|
||||||
|
|
||||||
|
* Move @0xproject/migrations to devDependencies
|
||||||
|
|
||||||
|
## v0.36.2 - _April 18, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v0.36.1 - _April 18, 2018_
|
||||||
|
|
||||||
|
* Internal changes and refactoring
|
||||||
|
* Fix redundant expired order removal bug (#527)
|
||||||
|
|
||||||
## v0.36.0 - _April 11, 2018_
|
## v0.36.0 - _April 11, 2018_
|
||||||
|
|
||||||
* Moved Web3.Provider to `@0xproject/types:Provider` (#501)
|
* Moved Web3.Provider to `@0xproject/types:Provider` (#501)
|
||||||
|
* Add `zeroEx.exchange.getOrderStateAsync` to allow obtaining current OrderState for a signedOrder (#510)
|
||||||
|
|
||||||
## v0.35.0 - _April 2, 2018_
|
## v0.35.0 - _April 2, 2018_
|
||||||
|
|
||||||
* Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3_wrapper' `Web3WrapperErrors.TransactionMiningTimeout` (#485)
|
* Removed `ZeroExError.TransactionMiningTimeout` and moved it to '@0xproject/web3-wrapper' `Web3WrapperErrors.TransactionMiningTimeout` (#485)
|
||||||
|
|
||||||
## v0.34.0 - _April 2, 2018_
|
## v0.34.0 - _April 2, 2018_
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
A TypeScript/Javascript library for interacting with the 0x protocol.
|
A TypeScript/Javascript library for interacting with the 0x protocol.
|
||||||
|
|
||||||
### Read the [Documentation](https://0xproject.com/docs/0xjs).
|
### Read the [Documentation](https://0xproject.com/docs/0x.js).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "0x.js",
|
"name": "0x.js",
|
||||||
"version": "0.35.0",
|
"version": "0.36.3",
|
||||||
"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",
|
||||||
@@ -15,25 +15,26 @@
|
|||||||
"build:watch": "tsc -w",
|
"build:watch": "tsc -w",
|
||||||
"prebuild": "run-s clean generate_contract_wrappers",
|
"prebuild": "run-s clean generate_contract_wrappers",
|
||||||
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
||||||
"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 --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
|
||||||
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
||||||
"test:circleci": "run-s test:coverage",
|
"test:circleci": "run-s test:coverage",
|
||||||
"test": "run-s clean test:commonjs",
|
"test": "run-s clean test:commonjs",
|
||||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||||
"update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../0x.js/src/artifacts; done;",
|
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/src/artifacts/$i.json test/artifacts; done;",
|
||||||
"clean": "shx rm -rf _bundles lib test_temp scripts",
|
"clean": "shx rm -rf _bundles lib test_temp scripts",
|
||||||
"build:umd:prod": "NODE_ENV=production webpack",
|
"build:umd:prod": "NODE_ENV=production webpack",
|
||||||
"build:commonjs": "tsc && copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
"build:commonjs": "tsc && yarn update_artifacts && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
||||||
"test:commonjs": "run-s build:commonjs run_mocha",
|
"test:commonjs": "run-s build:commonjs run_mocha",
|
||||||
"run_mocha": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit",
|
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
|
||||||
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
|
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
|
||||||
"docs:stage": "yarn build && node ./scripts/stage_docs.js",
|
"docs:stage": "yarn build && node ./scripts/stage_docs.js",
|
||||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
|
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
|
||||||
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
|
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"artifacts": "TokenTransferProxy Exchange TokenRegistry Token EtherToken",
|
"compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry",
|
||||||
|
"contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels",
|
||||||
"postpublish": {
|
"postpublish": {
|
||||||
"assets": [
|
"assets": [
|
||||||
"packages/0x.js/_bundles/index.js",
|
"packages/0x.js/_bundles/index.js",
|
||||||
@@ -60,9 +61,12 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0xproject/dev-utils": "^0.3.4",
|
"@0xproject/deployer": "^0.4.1",
|
||||||
"@0xproject/monorepo-scripts": "^0.1.16",
|
"@0xproject/dev-utils": "^0.3.6",
|
||||||
"@0xproject/tslint-config": "^0.4.14",
|
"@0xproject/migrations": "^0.0.3",
|
||||||
|
"@0xproject/monorepo-scripts": "^0.1.18",
|
||||||
|
"@0xproject/subproviders": "^0.9.0",
|
||||||
|
"@0xproject/tslint-config": "^0.4.16",
|
||||||
"@types/bintrees": "^1.0.2",
|
"@types/bintrees": "^1.0.2",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"@types/mocha": "^2.2.42",
|
"@types/mocha": "^2.2.42",
|
||||||
@@ -86,26 +90,27 @@
|
|||||||
"shx": "^0.2.2",
|
"shx": "^0.2.2",
|
||||||
"sinon": "^4.0.0",
|
"sinon": "^4.0.0",
|
||||||
"source-map-support": "^0.5.0",
|
"source-map-support": "^0.5.0",
|
||||||
"truffle-hdwallet-provider": "^0.0.3",
|
|
||||||
"tslint": "5.8.0",
|
"tslint": "5.8.0",
|
||||||
"typedoc": "0xProject/typedoc",
|
"typedoc": "0xProject/typedoc",
|
||||||
"typescript": "2.7.1",
|
"typescript": "2.7.1",
|
||||||
|
"web3-provider-engine": "^14.0.4",
|
||||||
"webpack": "^3.1.0"
|
"webpack": "^3.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/assert": "^0.2.5",
|
"@0xproject/assert": "^0.2.7",
|
||||||
"@0xproject/base-contract": "^0.1.0",
|
"@0xproject/base-contract": "^0.2.1",
|
||||||
"@0xproject/json-schemas": "^0.7.19",
|
"@0xproject/json-schemas": "^0.7.21",
|
||||||
"@0xproject/types": "^0.5.0",
|
"@0xproject/types": "^0.6.1",
|
||||||
"@0xproject/typescript-typings": "^0.0.3",
|
"@0xproject/typescript-typings": "^0.2.0",
|
||||||
"@0xproject/utils": "^0.5.0",
|
"@0xproject/utils": "^0.5.2",
|
||||||
"@0xproject/web3-wrapper": "^0.5.0",
|
"@0xproject/order-utils": "^0.0.1",
|
||||||
|
"@0xproject/web3-wrapper": "^0.6.1",
|
||||||
"bintrees": "^1.0.2",
|
"bintrees": "^1.0.2",
|
||||||
"bn.js": "^4.11.8",
|
"bn.js": "^4.11.8",
|
||||||
"ethereumjs-abi": "^0.6.4",
|
"ethereumjs-abi": "^0.6.4",
|
||||||
"ethereumjs-blockstream": "^2.0.6",
|
"ethereumjs-blockstream": "^2.0.6",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
"ethers-contracts": "^2.2.1",
|
"ethers": "^3.0.15",
|
||||||
"js-sha3": "^0.7.0",
|
"js-sha3": "^0.7.0",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"uuid": "^3.1.0",
|
"uuid": "^3.1.0",
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
|
||||||
|
import {
|
||||||
|
generatePseudoRandomSalt,
|
||||||
|
getOrderHashHex,
|
||||||
|
isValidOrderHash,
|
||||||
|
isValidSignature,
|
||||||
|
signOrderHashAsync,
|
||||||
|
} from '@0xproject/order-utils';
|
||||||
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
|
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
|
||||||
import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils';
|
import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
@@ -19,7 +26,6 @@ import { OrderStateWatcherConfig, ZeroExConfig, ZeroExError } from './types';
|
|||||||
import { assert } from './utils/assert';
|
import { assert } from './utils/assert';
|
||||||
import { constants } from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import { decorators } from './utils/decorators';
|
import { decorators } from './utils/decorators';
|
||||||
import { signatureUtils } from './utils/signature_utils';
|
|
||||||
import { utils } from './utils/utils';
|
import { utils } from './utils/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +39,6 @@ export class ZeroEx {
|
|||||||
* this constant for your convenience.
|
* this constant for your convenience.
|
||||||
*/
|
*/
|
||||||
public static NULL_ADDRESS = constants.NULL_ADDRESS;
|
public static NULL_ADDRESS = constants.NULL_ADDRESS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract.
|
* An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract.
|
||||||
*/
|
*/
|
||||||
@@ -58,6 +63,15 @@ export class ZeroEx {
|
|||||||
*/
|
*/
|
||||||
public proxy: TokenTransferProxyWrapper;
|
public proxy: TokenTransferProxyWrapper;
|
||||||
private _web3Wrapper: Web3Wrapper;
|
private _web3Wrapper: Web3Wrapper;
|
||||||
|
/**
|
||||||
|
* Generates a pseudo-random 256-bit salt.
|
||||||
|
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
|
||||||
|
* and will not collide with other outstanding orders that are identical in all other parameters.
|
||||||
|
* @return A pseudo-random 256-bit number that can be used as a salt.
|
||||||
|
*/
|
||||||
|
public static generatePseudoRandomSalt(): BigNumber {
|
||||||
|
return generatePseudoRandomSalt();
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@@ -67,27 +81,15 @@ export class ZeroEx {
|
|||||||
* @return Whether the signature is valid for the supplied signerAddress and data.
|
* @return Whether the signature is valid for the supplied signerAddress and data.
|
||||||
*/
|
*/
|
||||||
public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
||||||
assert.isHexString('data', data);
|
return isValidSignature(data, signature, signerAddress);
|
||||||
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
|
|
||||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
|
||||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
|
||||||
|
|
||||||
const isValidSignature = signatureUtils.isValidSignature(data, signature, normalizedSignerAddress);
|
|
||||||
return isValidSignature;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Generates a pseudo-random 256-bit salt.
|
* Computes the orderHash for a supplied order.
|
||||||
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
|
* @param order An object that conforms to the Order or SignedOrder interface definitions.
|
||||||
* and will not collide with other outstanding orders that are identical in all other parameters.
|
* @return The resulting orderHash from hashing the supplied order.
|
||||||
* @return A pseudo-random 256-bit number that can be used as a salt.
|
|
||||||
*/
|
*/
|
||||||
public static generatePseudoRandomSalt(): BigNumber {
|
public static getOrderHashHex(order: Order | SignedOrder): string {
|
||||||
// BigNumber.random returns a pseudo-random number between 0 & 1 with a passed in number of decimal places.
|
return getOrderHashHex(order);
|
||||||
// Source: https://mikemcl.github.io/bignumber.js/#random
|
|
||||||
const randomNumber = BigNumber.random(constants.MAX_DIGITS_IN_UNSIGNED_256_INT);
|
|
||||||
const factor = new BigNumber(10).pow(constants.MAX_DIGITS_IN_UNSIGNED_256_INT - 1);
|
|
||||||
const salt = randomNumber.times(factor).round();
|
|
||||||
return salt;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Checks if the supplied hex encoded order hash is valid.
|
* Checks if the supplied hex encoded order hash is valid.
|
||||||
@@ -97,12 +99,7 @@ export class ZeroEx {
|
|||||||
* @return Whether the supplied orderHash has the expected format.
|
* @return Whether the supplied orderHash has the expected format.
|
||||||
*/
|
*/
|
||||||
public static isValidOrderHash(orderHash: string): boolean {
|
public static isValidOrderHash(orderHash: string): boolean {
|
||||||
// Since this method can be called to check if any arbitrary string conforms to an orderHash's
|
return isValidOrderHash(orderHash);
|
||||||
// format, we only assert that we were indeed passed a string.
|
|
||||||
assert.isString('orderHash', orderHash);
|
|
||||||
const schemaValidator = new SchemaValidator();
|
|
||||||
const isValidOrderHash = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid;
|
|
||||||
return isValidOrderHash;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* A unit amount is defined as the amount of a token above the specified decimal places (integer part).
|
* A unit amount is defined as the amount of a token above the specified decimal places (integer part).
|
||||||
@@ -132,17 +129,6 @@ export class ZeroEx {
|
|||||||
const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, decimals);
|
const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, decimals);
|
||||||
return baseUnitAmount;
|
return baseUnitAmount;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Computes the orderHash for a supplied order.
|
|
||||||
* @param order An object that conforms to the Order or SignedOrder interface definitions.
|
|
||||||
* @return The resulting orderHash from hashing the supplied order.
|
|
||||||
*/
|
|
||||||
@decorators.syncZeroExErrorHandler
|
|
||||||
public static getOrderHashHex(order: Order | SignedOrder): string {
|
|
||||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
|
||||||
const orderHashHex = utils.getOrderHashHex(order);
|
|
||||||
return orderHashHex;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library.
|
* Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library.
|
||||||
* @param provider The 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
|
||||||
@@ -204,6 +190,13 @@ export class ZeroEx {
|
|||||||
(this.etherToken as any)._invalidateContractInstance();
|
(this.etherToken as any)._invalidateContractInstance();
|
||||||
(this.etherToken as any)._setNetworkId(networkId);
|
(this.etherToken as any)._setNetworkId(networkId);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Get the provider instance currently used by 0x.js
|
||||||
|
* @return Web3 provider instance
|
||||||
|
*/
|
||||||
|
public getProvider(): Provider {
|
||||||
|
return this._web3Wrapper.getProvider();
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
* @return An array of available user Ethereum addresses.
|
* @return An array of available user Ethereum addresses.
|
||||||
@@ -229,41 +222,12 @@ export class ZeroEx {
|
|||||||
signerAddress: string,
|
signerAddress: string,
|
||||||
shouldAddPersonalMessagePrefix: boolean,
|
shouldAddPersonalMessagePrefix: boolean,
|
||||||
): Promise<ECSignature> {
|
): Promise<ECSignature> {
|
||||||
assert.isHexString('orderHash', orderHash);
|
return signOrderHashAsync(
|
||||||
await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper);
|
this._web3Wrapper.getProvider(),
|
||||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
orderHash,
|
||||||
|
signerAddress,
|
||||||
let msgHashHex = orderHash;
|
shouldAddPersonalMessagePrefix,
|
||||||
if (shouldAddPersonalMessagePrefix) {
|
);
|
||||||
const orderHashBuff = ethUtil.toBuffer(orderHash);
|
|
||||||
const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff);
|
|
||||||
msgHashHex = ethUtil.bufferToHex(msgHashBuff);
|
|
||||||
}
|
|
||||||
|
|
||||||
const signature = await this._web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
|
|
||||||
|
|
||||||
// HACK: There is no consensus on whether the signatureHex string should be formatted as
|
|
||||||
// v + r + s OR r + s + v, and different clients (even different versions of the same client)
|
|
||||||
// return the signature params in different orders. In order to support all client implementations,
|
|
||||||
// we parse the signature in both ways, and evaluate if either one is a valid signature.
|
|
||||||
const validVParamValues = [27, 28];
|
|
||||||
const ecSignatureVRS = signatureUtils.parseSignatureHexAsVRS(signature);
|
|
||||||
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
|
|
||||||
const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, normalizedSignerAddress);
|
|
||||||
if (isValidVRSSignature) {
|
|
||||||
return ecSignatureVRS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ecSignatureRSV = signatureUtils.parseSignatureHexAsRSV(signature);
|
|
||||||
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
|
|
||||||
const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, normalizedSignerAddress);
|
|
||||||
if (isValidRSVSignature) {
|
|
||||||
return ecSignatureRSV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(ZeroExError.InvalidSignature);
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Waits for a transaction to be mined and returns the transaction receipt.
|
* Waits for a transaction to be mined and returns the transaction receipt.
|
||||||
|
@@ -0,0 +1,6 @@
|
|||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
|
export abstract class BalanceAndProxyAllowanceFetcher {
|
||||||
|
public abstract async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>;
|
||||||
|
public abstract async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>;
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
|
export abstract class OrderFilledCancelledFetcher {
|
||||||
|
public abstract async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>;
|
||||||
|
public abstract async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber>;
|
||||||
|
}
|
@@ -1,10 +1,10 @@
|
|||||||
import * as DummyTokenArtifact from './artifacts/DummyToken.json';
|
import * as DummyTokenArtifact from './compact_artifacts/DummyToken.json';
|
||||||
import * as EtherTokenArtifact from './artifacts/EtherToken.json';
|
import * as EtherTokenArtifact from './compact_artifacts/EtherToken.json';
|
||||||
import * as ExchangeArtifact from './artifacts/Exchange.json';
|
import * as ExchangeArtifact from './compact_artifacts/Exchange.json';
|
||||||
import * as TokenArtifact from './artifacts/Token.json';
|
import * as TokenArtifact from './compact_artifacts/Token.json';
|
||||||
import * as TokenRegistryArtifact from './artifacts/TokenRegistry.json';
|
import * as TokenRegistryArtifact from './compact_artifacts/TokenRegistry.json';
|
||||||
import * as TokenTransferProxyArtifact from './artifacts/TokenTransferProxy.json';
|
import * as TokenTransferProxyArtifact from './compact_artifacts/TokenTransferProxy.json';
|
||||||
import * as ZRXArtifact from './artifacts/ZRX.json';
|
import * as ZRXArtifact from './compact_artifacts/ZRX.json';
|
||||||
import { Artifact } from './types';
|
import { Artifact } from './types';
|
||||||
|
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { schemas } from '@0xproject/json-schemas';
|
import { schemas } from '@0xproject/json-schemas';
|
||||||
|
import { getOrderHashHex } from '@0xproject/order-utils';
|
||||||
import {
|
import {
|
||||||
BlockParamLiteral,
|
BlockParamLiteral,
|
||||||
DecodedLogArgs,
|
DecodedLogArgs,
|
||||||
@@ -13,6 +14,8 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { artifacts } from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
|
import { SimpleBalanceAndProxyAllowanceFetcher } from '../fetchers/simple_balance_and_proxy_allowance_fetcher';
|
||||||
|
import { SimpleOrderFilledCancelledFetcher } from '../fetchers/simple_order_filled_cancelled_fetcher';
|
||||||
import {
|
import {
|
||||||
BlockRange,
|
BlockRange,
|
||||||
EventCallback,
|
EventCallback,
|
||||||
@@ -23,6 +26,7 @@ import {
|
|||||||
OrderAddresses,
|
OrderAddresses,
|
||||||
OrderCancellationRequest,
|
OrderCancellationRequest,
|
||||||
OrderFillRequest,
|
OrderFillRequest,
|
||||||
|
OrderState,
|
||||||
OrderTransactionOpts,
|
OrderTransactionOpts,
|
||||||
OrderValues,
|
OrderValues,
|
||||||
ValidateOrderFillableOpts,
|
ValidateOrderFillableOpts,
|
||||||
@@ -30,6 +34,7 @@ import {
|
|||||||
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 { OrderStateUtils } from '../utils/order_state_utils';
|
||||||
import { OrderValidationUtils } from '../utils/order_validation_utils';
|
import { OrderValidationUtils } from '../utils/order_validation_utils';
|
||||||
import { utils } from '../utils/utils';
|
import { utils } from '../utils/utils';
|
||||||
|
|
||||||
@@ -41,7 +46,6 @@ import {
|
|||||||
LogErrorContractEventArgs,
|
LogErrorContractEventArgs,
|
||||||
} from './generated/exchange';
|
} from './generated/exchange';
|
||||||
import { TokenWrapper } from './token_wrapper';
|
import { TokenWrapper } from './token_wrapper';
|
||||||
|
|
||||||
const SHOULD_VALIDATE_BY_DEFAULT = true;
|
const SHOULD_VALIDATE_BY_DEFAULT = true;
|
||||||
|
|
||||||
interface ExchangeContractErrCodesToMsgs {
|
interface ExchangeContractErrCodesToMsgs {
|
||||||
@@ -567,7 +571,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
? SHOULD_VALIDATE_BY_DEFAULT
|
? SHOULD_VALIDATE_BY_DEFAULT
|
||||||
: orderTransactionOpts.shouldValidate;
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
const orderHash = utils.getOrderHashHex(order);
|
const orderHash = getOrderHashHex(order);
|
||||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||||
order,
|
order,
|
||||||
@@ -626,7 +630,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
: orderTransactionOpts.shouldValidate;
|
: orderTransactionOpts.shouldValidate;
|
||||||
if (shouldValidate) {
|
if (shouldValidate) {
|
||||||
for (const orderCancellationRequest of orderCancellationRequests) {
|
for (const orderCancellationRequest of orderCancellationRequests) {
|
||||||
const orderHash = utils.getOrderHashHex(orderCancellationRequest.order);
|
const orderHash = getOrderHashHex(orderCancellationRequest.order);
|
||||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||||
orderCancellationRequest.order,
|
orderCancellationRequest.order,
|
||||||
@@ -798,7 +802,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
): Promise<void> {
|
): 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 = getOrderHashHex(order);
|
||||||
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
OrderValidationUtils.validateCancelOrderThrowIfInvalid(
|
||||||
order,
|
order,
|
||||||
@@ -873,6 +877,28 @@ export class ExchangeWrapper extends ContractWrapper {
|
|||||||
throw new Error(errMessage);
|
throw new Error(errMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Gets the latest OrderState of a signedOrder
|
||||||
|
* @param signedOrder The signedOrder
|
||||||
|
* @param stateLayer Optional, desired blockchain state layer (defaults to latest).
|
||||||
|
* @return OrderState of the signedOrder
|
||||||
|
*/
|
||||||
|
public async getOrderStateAsync(
|
||||||
|
signedOrder: SignedOrder,
|
||||||
|
stateLayer: BlockParamLiteral = BlockParamLiteral.Latest,
|
||||||
|
): Promise<OrderState> {
|
||||||
|
const simpleBalanceAndProxyAllowanceFetcher = new SimpleBalanceAndProxyAllowanceFetcher(
|
||||||
|
this._tokenWrapper,
|
||||||
|
stateLayer,
|
||||||
|
);
|
||||||
|
const simpleOrderFilledCancelledFetcher = new SimpleOrderFilledCancelledFetcher(this, stateLayer);
|
||||||
|
const orderStateUtils = new OrderStateUtils(
|
||||||
|
simpleBalanceAndProxyAllowanceFetcher,
|
||||||
|
simpleOrderFilledCancelledFetcher,
|
||||||
|
);
|
||||||
|
const orderState = orderStateUtils.getOrderStateAsync(signedOrder);
|
||||||
|
return orderState;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns the ZRX token address used by the exchange contract.
|
* Returns the ZRX token address used by the exchange contract.
|
||||||
* @return Address of ZRX token
|
* @return Address of ZRX token
|
||||||
|
@@ -0,0 +1,28 @@
|
|||||||
|
import { BlockParamLiteral } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
|
import { BalanceAndProxyAllowanceFetcher } from '../abstract/balance_and_proxy_allowance_fetcher';
|
||||||
|
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||||
|
|
||||||
|
export class SimpleBalanceAndProxyAllowanceFetcher implements BalanceAndProxyAllowanceFetcher {
|
||||||
|
private _tokenWrapper: TokenWrapper;
|
||||||
|
private _defaultBlock: BlockParamLiteral;
|
||||||
|
constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
|
||||||
|
this._tokenWrapper = token;
|
||||||
|
this._defaultBlock = defaultBlock;
|
||||||
|
}
|
||||||
|
public async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
|
||||||
|
const methodOpts = {
|
||||||
|
defaultBlock: this._defaultBlock,
|
||||||
|
};
|
||||||
|
const balance = this._tokenWrapper.getBalanceAsync(tokenAddress, userAddress, methodOpts);
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
public async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
|
||||||
|
const methodOpts = {
|
||||||
|
defaultBlock: this._defaultBlock,
|
||||||
|
};
|
||||||
|
const proxyAllowance = this._tokenWrapper.getProxyAllowanceAsync(tokenAddress, userAddress, methodOpts);
|
||||||
|
return proxyAllowance;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
import { BlockParamLiteral } from '@0xproject/types';
|
||||||
|
import { BigNumber } from '@0xproject/utils';
|
||||||
|
|
||||||
|
import { OrderFilledCancelledFetcher } from '../abstract/order_filled_cancelled_fetcher';
|
||||||
|
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||||
|
|
||||||
|
export class SimpleOrderFilledCancelledFetcher implements OrderFilledCancelledFetcher {
|
||||||
|
private _exchangeWrapper: ExchangeWrapper;
|
||||||
|
private _defaultBlock: BlockParamLiteral;
|
||||||
|
constructor(exchange: ExchangeWrapper, defaultBlock: BlockParamLiteral) {
|
||||||
|
this._exchangeWrapper = exchange;
|
||||||
|
this._defaultBlock = defaultBlock;
|
||||||
|
}
|
||||||
|
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
|
||||||
|
const methodOpts = {
|
||||||
|
defaultBlock: this._defaultBlock,
|
||||||
|
};
|
||||||
|
const filledTakerAmount = this._exchangeWrapper.getFilledTakerAmountAsync(orderHash, methodOpts);
|
||||||
|
return filledTakerAmount;
|
||||||
|
}
|
||||||
|
public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
|
||||||
|
const methodOpts = {
|
||||||
|
defaultBlock: this._defaultBlock,
|
||||||
|
};
|
||||||
|
const cancelledTakerAmount = this._exchangeWrapper.getCancelledTakerAmountAsync(orderHash, methodOpts);
|
||||||
|
return cancelledTakerAmount;
|
||||||
|
}
|
||||||
|
}
|
@@ -13,7 +13,7 @@ enum LogEventState {
|
|||||||
Added,
|
Added,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* The EventWatcher watches for blockchain events at the specified block confirmation
|
* The EventWatcher watches for blockchain events at the specified block confirmation
|
||||||
* depth.
|
* depth.
|
||||||
*/
|
*/
|
||||||
|
@@ -22,8 +22,17 @@ export class ExpirationWatcher {
|
|||||||
this._expirationMarginMs = expirationMarginIfExistsMs || DEFAULT_EXPIRATION_MARGIN_MS;
|
this._expirationMarginMs = expirationMarginIfExistsMs || DEFAULT_EXPIRATION_MARGIN_MS;
|
||||||
this._orderExpirationCheckingIntervalMs =
|
this._orderExpirationCheckingIntervalMs =
|
||||||
expirationMarginIfExistsMs || DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS;
|
expirationMarginIfExistsMs || DEFAULT_ORDER_EXPIRATION_CHECKING_INTERVAL_MS;
|
||||||
const scoreFunction = (orderHash: string) => this._expiration[orderHash].toNumber();
|
const comparator = (lhsOrderHash: string, rhsOrderHash: string) => {
|
||||||
const comparator = (lhs: string, rhs: string) => scoreFunction(lhs) - scoreFunction(rhs);
|
const lhsExpiration = this._expiration[lhsOrderHash].toNumber();
|
||||||
|
const rhsExpiration = this._expiration[rhsOrderHash].toNumber();
|
||||||
|
if (lhsExpiration !== rhsExpiration) {
|
||||||
|
return lhsExpiration - rhsExpiration;
|
||||||
|
} else {
|
||||||
|
// HACK: If two orders have identical expirations, the order in which they are emitted by the
|
||||||
|
// ExpirationWatcher does not matter, so we emit them in alphabetical order by orderHash.
|
||||||
|
return lhsOrderHash.localeCompare(rhsOrderHash);
|
||||||
|
}
|
||||||
|
};
|
||||||
this._orderHashByExpirationRBTree = new RBTree(comparator);
|
this._orderHashByExpirationRBTree = new RBTree(comparator);
|
||||||
}
|
}
|
||||||
public subscribe(callback: (orderHash: string) => void): void {
|
public subscribe(callback: (orderHash: string) => void): void {
|
||||||
@@ -48,6 +57,9 @@ export class ExpirationWatcher {
|
|||||||
this._orderHashByExpirationRBTree.insert(orderHash);
|
this._orderHashByExpirationRBTree.insert(orderHash);
|
||||||
}
|
}
|
||||||
public removeOrder(orderHash: string): void {
|
public removeOrder(orderHash: string): void {
|
||||||
|
if (_.isUndefined(this._expiration[orderHash])) {
|
||||||
|
return; // noop since order already removed
|
||||||
|
}
|
||||||
this._orderHashByExpirationRBTree.remove(orderHash);
|
this._orderHashByExpirationRBTree.remove(orderHash);
|
||||||
delete this._expiration[orderHash];
|
delete this._expiration[orderHash];
|
||||||
}
|
}
|
||||||
|
@@ -87,7 +87,7 @@ export class OrderStateWatcher {
|
|||||||
_.isUndefined(config) || _.isUndefined(config.stateLayer) ? BlockParamLiteral.Latest : config.stateLayer;
|
_.isUndefined(config) || _.isUndefined(config.stateLayer) ? BlockParamLiteral.Latest : config.stateLayer;
|
||||||
this._eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalIfExistsMs, stateLayer);
|
this._eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalIfExistsMs, stateLayer);
|
||||||
this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(token, stateLayer);
|
this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(token, stateLayer);
|
||||||
this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(exchange);
|
this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(exchange, stateLayer);
|
||||||
this._orderStateUtils = new OrderStateUtils(
|
this._orderStateUtils = new OrderStateUtils(
|
||||||
this._balanceAndProxyAllowanceLazyStore,
|
this._balanceAndProxyAllowanceLazyStore,
|
||||||
this._orderFilledCancelledLazyStore,
|
this._orderFilledCancelledLazyStore,
|
||||||
@@ -131,7 +131,7 @@ export class OrderStateWatcher {
|
|||||||
}
|
}
|
||||||
delete this._orderByOrderHash[orderHash];
|
delete this._orderByOrderHash[orderHash];
|
||||||
delete this._orderStateByOrderHashCache[orderHash];
|
delete this._orderStateByOrderHashCache[orderHash];
|
||||||
const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
|
const exchange = (this._orderFilledCancelledLazyStore as any)._exchangeWrapper as ExchangeWrapper;
|
||||||
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
||||||
|
|
||||||
this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
|
this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash);
|
||||||
@@ -374,7 +374,7 @@ export class OrderStateWatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private _getZRXTokenAddress(): string {
|
private _getZRXTokenAddress(): string {
|
||||||
const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
|
const exchange = (this._orderFilledCancelledLazyStore as any)._exchangeWrapper as ExchangeWrapper;
|
||||||
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
const zrxTokenAddress = exchange.getZRXTokenAddress();
|
||||||
return zrxTokenAddress;
|
return zrxTokenAddress;
|
||||||
}
|
}
|
||||||
|
@@ -2,13 +2,14 @@ import { BlockParamLiteral } from '@0xproject/types';
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { BalanceAndProxyAllowanceFetcher } from '../abstract/balance_and_proxy_allowance_fetcher';
|
||||||
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy on read store for balances/proxyAllowances of tokens/accounts
|
* Copy on read store for balances/proxyAllowances of tokens/accounts
|
||||||
*/
|
*/
|
||||||
export class BalanceAndProxyAllowanceLazyStore {
|
export class BalanceAndProxyAllowanceLazyStore implements BalanceAndProxyAllowanceFetcher {
|
||||||
private _token: TokenWrapper;
|
private _tokenWrapper: TokenWrapper;
|
||||||
private _defaultBlock: BlockParamLiteral;
|
private _defaultBlock: BlockParamLiteral;
|
||||||
private _balance: {
|
private _balance: {
|
||||||
[tokenAddress: string]: {
|
[tokenAddress: string]: {
|
||||||
@@ -21,7 +22,7 @@ export class BalanceAndProxyAllowanceLazyStore {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
|
constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
|
||||||
this._token = token;
|
this._tokenWrapper = token;
|
||||||
this._defaultBlock = defaultBlock;
|
this._defaultBlock = defaultBlock;
|
||||||
this._balance = {};
|
this._balance = {};
|
||||||
this._proxyAllowance = {};
|
this._proxyAllowance = {};
|
||||||
@@ -31,7 +32,7 @@ export class BalanceAndProxyAllowanceLazyStore {
|
|||||||
const methodOpts = {
|
const methodOpts = {
|
||||||
defaultBlock: this._defaultBlock,
|
defaultBlock: this._defaultBlock,
|
||||||
};
|
};
|
||||||
const balance = await this._token.getBalanceAsync(tokenAddress, userAddress, methodOpts);
|
const balance = await this._tokenWrapper.getBalanceAsync(tokenAddress, userAddress, methodOpts);
|
||||||
this.setBalance(tokenAddress, userAddress, balance);
|
this.setBalance(tokenAddress, userAddress, balance);
|
||||||
}
|
}
|
||||||
const cachedBalance = this._balance[tokenAddress][userAddress];
|
const cachedBalance = this._balance[tokenAddress][userAddress];
|
||||||
@@ -59,7 +60,11 @@ export class BalanceAndProxyAllowanceLazyStore {
|
|||||||
const methodOpts = {
|
const methodOpts = {
|
||||||
defaultBlock: this._defaultBlock,
|
defaultBlock: this._defaultBlock,
|
||||||
};
|
};
|
||||||
const proxyAllowance = await this._token.getProxyAllowanceAsync(tokenAddress, userAddress, methodOpts);
|
const proxyAllowance = await this._tokenWrapper.getProxyAllowanceAsync(
|
||||||
|
tokenAddress,
|
||||||
|
userAddress,
|
||||||
|
methodOpts,
|
||||||
|
);
|
||||||
this.setProxyAllowance(tokenAddress, userAddress, proxyAllowance);
|
this.setProxyAllowance(tokenAddress, userAddress, proxyAllowance);
|
||||||
}
|
}
|
||||||
const cachedProxyAllowance = this._proxyAllowance[tokenAddress][userAddress];
|
const cachedProxyAllowance = this._proxyAllowance[tokenAddress][userAddress];
|
||||||
|
@@ -2,30 +2,33 @@ import { BlockParamLiteral } from '@0xproject/types';
|
|||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { OrderFilledCancelledFetcher } from '../abstract/order_filled_cancelled_fetcher';
|
||||||
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy on read store for filled/cancelled taker amounts
|
* Copy on read store for filled/cancelled taker amounts
|
||||||
*/
|
*/
|
||||||
export class OrderFilledCancelledLazyStore {
|
export class OrderFilledCancelledLazyStore implements OrderFilledCancelledFetcher {
|
||||||
private _exchange: ExchangeWrapper;
|
private _exchangeWrapper: ExchangeWrapper;
|
||||||
|
private _defaultBlock: BlockParamLiteral;
|
||||||
private _filledTakerAmount: {
|
private _filledTakerAmount: {
|
||||||
[orderHash: string]: BigNumber;
|
[orderHash: string]: BigNumber;
|
||||||
};
|
};
|
||||||
private _cancelledTakerAmount: {
|
private _cancelledTakerAmount: {
|
||||||
[orderHash: string]: BigNumber;
|
[orderHash: string]: BigNumber;
|
||||||
};
|
};
|
||||||
constructor(exchange: ExchangeWrapper) {
|
constructor(exchange: ExchangeWrapper, defaultBlock: BlockParamLiteral) {
|
||||||
this._exchange = exchange;
|
this._exchangeWrapper = exchange;
|
||||||
|
this._defaultBlock = defaultBlock;
|
||||||
this._filledTakerAmount = {};
|
this._filledTakerAmount = {};
|
||||||
this._cancelledTakerAmount = {};
|
this._cancelledTakerAmount = {};
|
||||||
}
|
}
|
||||||
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
|
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
|
||||||
if (_.isUndefined(this._filledTakerAmount[orderHash])) {
|
if (_.isUndefined(this._filledTakerAmount[orderHash])) {
|
||||||
const methodOpts = {
|
const methodOpts = {
|
||||||
defaultBlock: BlockParamLiteral.Pending,
|
defaultBlock: this._defaultBlock,
|
||||||
};
|
};
|
||||||
const filledTakerAmount = await this._exchange.getFilledTakerAmountAsync(orderHash, methodOpts);
|
const filledTakerAmount = await this._exchangeWrapper.getFilledTakerAmountAsync(orderHash, methodOpts);
|
||||||
this.setFilledTakerAmount(orderHash, filledTakerAmount);
|
this.setFilledTakerAmount(orderHash, filledTakerAmount);
|
||||||
}
|
}
|
||||||
const cachedFilled = this._filledTakerAmount[orderHash];
|
const cachedFilled = this._filledTakerAmount[orderHash];
|
||||||
@@ -40,9 +43,12 @@ export class OrderFilledCancelledLazyStore {
|
|||||||
public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
|
public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
|
||||||
if (_.isUndefined(this._cancelledTakerAmount[orderHash])) {
|
if (_.isUndefined(this._cancelledTakerAmount[orderHash])) {
|
||||||
const methodOpts = {
|
const methodOpts = {
|
||||||
defaultBlock: BlockParamLiteral.Pending,
|
defaultBlock: this._defaultBlock,
|
||||||
};
|
};
|
||||||
const cancelledTakerAmount = await this._exchange.getCancelledTakerAmountAsync(orderHash, methodOpts);
|
const cancelledTakerAmount = await this._exchangeWrapper.getCancelledTakerAmountAsync(
|
||||||
|
orderHash,
|
||||||
|
methodOpts,
|
||||||
|
);
|
||||||
this.setCancelledTakerAmount(orderHash, cancelledTakerAmount);
|
this.setCancelledTakerAmount(orderHash, cancelledTakerAmount);
|
||||||
}
|
}
|
||||||
const cachedCancelled = this._cancelledTakerAmount[orderHash];
|
const cachedCancelled = this._cancelledTakerAmount[orderHash];
|
||||||
|
@@ -27,7 +27,6 @@ export enum ZeroExError {
|
|||||||
TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST',
|
TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST',
|
||||||
UnhandledError = 'UNHANDLED_ERROR',
|
UnhandledError = 'UNHANDLED_ERROR',
|
||||||
UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES',
|
UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES',
|
||||||
InvalidSignature = 'INVALID_SIGNATURE',
|
|
||||||
ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
|
ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
|
||||||
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
|
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
|
||||||
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
|
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
|
||||||
@@ -154,13 +153,13 @@ 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;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* 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. Default: 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. Default: 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. Default=1hr.
|
||||||
* stateLayer: Optional blockchain state layer OrderWatcher will monitor for new events. Default: latest
|
* stateLayer: Optional blockchain state layer OrderWatcher will monitor for new events. Default=latest.
|
||||||
*/
|
*/
|
||||||
export interface OrderStateWatcherConfig {
|
export interface OrderStateWatcherConfig {
|
||||||
orderExpirationCheckingIntervalMs?: number;
|
orderExpirationCheckingIntervalMs?: number;
|
||||||
@@ -170,7 +169,7 @@ export interface OrderStateWatcherConfig {
|
|||||||
stateLayer: BlockParamLiteral;
|
stateLayer: BlockParamLiteral;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 3-ropsten, 4-rinkeby, 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
|
||||||
@@ -201,7 +200,7 @@ export interface Artifact {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* expectedFillTakerTokenAmount: If specified, the validation method will ensure that the
|
* expectedFillTakerTokenAmount: If specified, the validation method will ensure that the
|
||||||
* supplied order maker has a sufficient allowance/balance to fill this amount of the order's
|
* supplied order maker has a sufficient allowance/balance to fill this amount of the order's
|
||||||
* takerTokenAmount. If not specified, the validation method ensures that the maker has a sufficient
|
* takerTokenAmount. If not specified, the validation method ensures that the maker has a sufficient
|
||||||
@@ -211,7 +210,7 @@ export interface ValidateOrderFillableOpts {
|
|||||||
expectedFillTakerTokenAmount?: BigNumber;
|
expectedFillTakerTokenAmount?: BigNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* defaultBlock: The block up to which to query the blockchain state. Setting this to a historical block number
|
* defaultBlock: The block up to which to query the blockchain state. Setting this to a historical block number
|
||||||
* let's the user query the blockchain's state at an arbitrary point in time. In order for this to work, the
|
* let's the user query the blockchain's state at an arbitrary point in time. In order for this to work, the
|
||||||
* backing Ethereum node must keep the entire historical state of the chain (e.g setting `--pruning=archive`
|
* backing Ethereum node must keep the entire historical state of the chain (e.g setting `--pruning=archive`
|
||||||
@@ -221,7 +220,7 @@ export interface MethodOpts {
|
|||||||
defaultBlock?: BlockParam;
|
defaultBlock?: BlockParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* gasPrice: Gas price in Wei to use for a transaction
|
* gasPrice: Gas price in Wei to use for a transaction
|
||||||
* gasLimit: The amount of gas to send with a transaction
|
* gasLimit: The amount of gas to send with a transaction
|
||||||
*/
|
*/
|
||||||
@@ -230,9 +229,9 @@ export interface TransactionOpts {
|
|||||||
gasLimit?: number;
|
gasLimit?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before
|
* shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before
|
||||||
* broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default: true
|
* broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default=true.
|
||||||
*/
|
*/
|
||||||
export interface OrderTransactionOpts extends TransactionOpts {
|
export interface OrderTransactionOpts extends TransactionOpts {
|
||||||
shouldValidate?: boolean;
|
shouldValidate?: boolean;
|
||||||
|
@@ -8,13 +8,13 @@ import { BigNumber } from '@0xproject/utils';
|
|||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { signatureUtils } from '../utils/signature_utils';
|
import { isValidSignature } from '@0xproject/order-utils';
|
||||||
|
|
||||||
export const assert = {
|
export const assert = {
|
||||||
...sharedAssert,
|
...sharedAssert,
|
||||||
isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string) {
|
isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string) {
|
||||||
const isValidSignature = signatureUtils.isValidSignature(orderHash, ecSignature, signerAddress);
|
const isValid = isValidSignature(orderHash, ecSignature, signerAddress);
|
||||||
this.assert(isValidSignature, `Expected order with hash '${orderHash}' to have a valid signature`);
|
this.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
|
||||||
},
|
},
|
||||||
async isSenderAddressAsync(
|
async isSenderAddressAsync(
|
||||||
variableName: string,
|
variableName: string,
|
||||||
@@ -28,8 +28,4 @@ export const assert = {
|
|||||||
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
async isUserAddressAvailableAsync(web3Wrapper: Web3Wrapper): Promise<void> {
|
|
||||||
const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
|
||||||
this.assert(!_.isEmpty(availableAddresses), 'No addresses were available on the provided web3 provider');
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@@ -3,7 +3,6 @@ import { BigNumber } from '@0xproject/utils';
|
|||||||
export const constants = {
|
export const constants = {
|
||||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||||
TESTRPC_NETWORK_ID: 50,
|
TESTRPC_NETWORK_ID: 50,
|
||||||
MAX_DIGITS_IN_UNSIGNED_256_INT: 78,
|
|
||||||
INVALID_JUMP_PATTERN: 'invalid JUMP at',
|
INVALID_JUMP_PATTERN: 'invalid JUMP at',
|
||||||
OUT_OF_GAS_PATTERN: 'out of gas',
|
OUT_OF_GAS_PATTERN: 'out of gas',
|
||||||
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
|
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
|
||||||
|
@@ -5,6 +5,7 @@ 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 { ExchangeContractErrs, TradeSide, TransferType } from '../types';
|
import { ExchangeContractErrs, TradeSide, TransferType } from '../types';
|
||||||
|
import { constants } from '../utils/constants';
|
||||||
|
|
||||||
enum FailureReason {
|
enum FailureReason {
|
||||||
Balance = 'balance',
|
Balance = 'balance',
|
||||||
@@ -66,6 +67,13 @@ export class ExchangeTransferSimulator {
|
|||||||
tradeSide: TradeSide,
|
tradeSide: TradeSide,
|
||||||
transferType: TransferType,
|
transferType: TransferType,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
// HACK: When simulating an open order (e.g taker is NULL_ADDRESS), we don't want to adjust balances/
|
||||||
|
// allowances for the taker. We do however, want to increase the balance of the maker since the maker
|
||||||
|
// might be relying on those funds to fill subsequent orders or pay the order's fees.
|
||||||
|
if (from === constants.NULL_ADDRESS && tradeSide === TradeSide.Taker) {
|
||||||
|
await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits);
|
||||||
|
return;
|
||||||
|
}
|
||||||
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)) {
|
||||||
|
@@ -3,17 +3,17 @@ import { BigNumber } from '@0xproject/utils';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { ZeroEx } from '../0x';
|
import { ZeroEx } from '../0x';
|
||||||
|
import { BalanceAndProxyAllowanceFetcher } from '../abstract/balance_and_proxy_allowance_fetcher';
|
||||||
|
import { OrderFilledCancelledFetcher } from '../abstract/order_filled_cancelled_fetcher';
|
||||||
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 { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
|
|
||||||
import { ExchangeContractErrs, OrderRelevantState, OrderState, OrderStateInvalid, OrderStateValid } from '../types';
|
import { ExchangeContractErrs, OrderRelevantState, OrderState, OrderStateInvalid, OrderStateValid } from '../types';
|
||||||
|
|
||||||
const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
|
const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
|
||||||
|
|
||||||
export class OrderStateUtils {
|
export class OrderStateUtils {
|
||||||
private _balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore;
|
private _balanceAndProxyAllowanceFetcher: BalanceAndProxyAllowanceFetcher;
|
||||||
private _orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
|
private _orderFilledCancelledFetcher: OrderFilledCancelledFetcher;
|
||||||
private static _validateIfOrderIsValid(signedOrder: SignedOrder, orderRelevantState: OrderRelevantState): void {
|
private static _validateIfOrderIsValid(signedOrder: SignedOrder, orderRelevantState: OrderRelevantState): void {
|
||||||
const unavailableTakerTokenAmount = orderRelevantState.cancelledTakerTokenAmount.add(
|
const unavailableTakerTokenAmount = orderRelevantState.cancelledTakerTokenAmount.add(
|
||||||
orderRelevantState.filledTakerTokenAmount,
|
orderRelevantState.filledTakerTokenAmount,
|
||||||
@@ -49,11 +49,11 @@ export class OrderStateUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
constructor(
|
constructor(
|
||||||
balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore,
|
balanceAndProxyAllowanceFetcher: BalanceAndProxyAllowanceFetcher,
|
||||||
orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore,
|
orderFilledCancelledFetcher: OrderFilledCancelledFetcher,
|
||||||
) {
|
) {
|
||||||
this._balanceAndProxyAllowanceLazyStore = balanceAndProxyAllowanceLazyStore;
|
this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher;
|
||||||
this._orderFilledCancelledLazyStore = orderFilledCancelledLazyStore;
|
this._orderFilledCancelledFetcher = orderFilledCancelledFetcher;
|
||||||
}
|
}
|
||||||
public async getOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> {
|
public async getOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> {
|
||||||
const orderRelevantState = await this.getOrderRelevantStateAsync(signedOrder);
|
const orderRelevantState = await this.getOrderRelevantStateAsync(signedOrder);
|
||||||
@@ -80,27 +80,27 @@ export class OrderStateUtils {
|
|||||||
// If we pass it from the instantiator - there is no opportunity to get it there
|
// If we pass it from the instantiator - there is no opportunity to get it there
|
||||||
// because JS doesn't support async constructors.
|
// because JS doesn't support async constructors.
|
||||||
// Moreover - it's cached under the hood so it's equivalent to an async constructor.
|
// Moreover - it's cached under the hood so it's equivalent to an async constructor.
|
||||||
const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper;
|
const exchange = (this._orderFilledCancelledFetcher as any)._exchangeWrapper as ExchangeWrapper;
|
||||||
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._balanceAndProxyAllowanceFetcher.getBalanceAsync(
|
||||||
signedOrder.makerTokenAddress,
|
signedOrder.makerTokenAddress,
|
||||||
signedOrder.maker,
|
signedOrder.maker,
|
||||||
);
|
);
|
||||||
const makerProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
|
const makerProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
|
||||||
signedOrder.makerTokenAddress,
|
signedOrder.makerTokenAddress,
|
||||||
signedOrder.maker,
|
signedOrder.maker,
|
||||||
);
|
);
|
||||||
const makerFeeBalance = await this._balanceAndProxyAllowanceLazyStore.getBalanceAsync(
|
const makerFeeBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(
|
||||||
zrxTokenAddress,
|
zrxTokenAddress,
|
||||||
signedOrder.maker,
|
signedOrder.maker,
|
||||||
);
|
);
|
||||||
const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceLazyStore.getProxyAllowanceAsync(
|
const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
|
||||||
zrxTokenAddress,
|
zrxTokenAddress,
|
||||||
signedOrder.maker,
|
signedOrder.maker,
|
||||||
);
|
);
|
||||||
const filledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getFilledTakerAmountAsync(orderHash);
|
const filledTakerTokenAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash);
|
||||||
const cancelledTakerTokenAmount = await this._orderFilledCancelledLazyStore.getCancelledTakerAmountAsync(
|
const cancelledTakerTokenAmount = await this._orderFilledCancelledFetcher.getCancelledTakerAmountAsync(
|
||||||
orderHash,
|
orderHash,
|
||||||
);
|
);
|
||||||
const unavailableTakerTokenAmount = await exchange.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await exchange.getUnavailableTakerAmountAsync(orderHash);
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { getOrderHashHex, OrderError } from '@0xproject/order-utils';
|
||||||
import { Order, SignedOrder } from '@0xproject/types';
|
import { Order, SignedOrder } from '@0xproject/types';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
@@ -113,7 +114,7 @@ export class OrderValidationUtils {
|
|||||||
zrxTokenAddress: string,
|
zrxTokenAddress: string,
|
||||||
expectedFillTakerTokenAmount?: BigNumber,
|
expectedFillTakerTokenAmount?: BigNumber,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const orderHash = utils.getOrderHashHex(signedOrder);
|
const orderHash = getOrderHashHex(signedOrder);
|
||||||
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||||
signedOrder.takerTokenAmount,
|
signedOrder.takerTokenAmount,
|
||||||
@@ -124,31 +125,12 @@ export class OrderValidationUtils {
|
|||||||
if (!_.isUndefined(expectedFillTakerTokenAmount)) {
|
if (!_.isUndefined(expectedFillTakerTokenAmount)) {
|
||||||
fillTakerTokenAmount = expectedFillTakerTokenAmount;
|
fillTakerTokenAmount = expectedFillTakerTokenAmount;
|
||||||
}
|
}
|
||||||
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
|
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||||
|
exchangeTradeEmulator,
|
||||||
|
signedOrder,
|
||||||
fillTakerTokenAmount,
|
fillTakerTokenAmount,
|
||||||
signedOrder.takerTokenAmount,
|
|
||||||
signedOrder.makerTokenAmount,
|
|
||||||
);
|
|
||||||
await exchangeTradeEmulator.transferFromAsync(
|
|
||||||
signedOrder.makerTokenAddress,
|
|
||||||
signedOrder.maker,
|
|
||||||
signedOrder.taker,
|
signedOrder.taker,
|
||||||
fillMakerTokenAmount,
|
|
||||||
TradeSide.Maker,
|
|
||||||
TransferType.Trade,
|
|
||||||
);
|
|
||||||
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
|
||||||
fillTakerTokenAmount,
|
|
||||||
signedOrder.takerTokenAmount,
|
|
||||||
signedOrder.makerFee,
|
|
||||||
);
|
|
||||||
await exchangeTradeEmulator.transferFromAsync(
|
|
||||||
zrxTokenAddress,
|
zrxTokenAddress,
|
||||||
signedOrder.maker,
|
|
||||||
signedOrder.feeRecipient,
|
|
||||||
makerFeeAmount,
|
|
||||||
TradeSide.Maker,
|
|
||||||
TransferType.Fee,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public async validateFillOrderThrowIfInvalidAsync(
|
public async validateFillOrderThrowIfInvalidAsync(
|
||||||
@@ -161,9 +143,9 @@ export class OrderValidationUtils {
|
|||||||
if (fillTakerTokenAmount.eq(0)) {
|
if (fillTakerTokenAmount.eq(0)) {
|
||||||
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
|
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
|
||||||
}
|
}
|
||||||
const orderHash = utils.getOrderHashHex(signedOrder);
|
const orderHash = getOrderHashHex(signedOrder);
|
||||||
if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) {
|
if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) {
|
||||||
throw new Error(ZeroExError.InvalidSignature);
|
throw new Error(OrderError.InvalidSignature);
|
||||||
}
|
}
|
||||||
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
|
||||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||||
|
@@ -1,45 +0,0 @@
|
|||||||
import { ECSignature } from '@0xproject/types';
|
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
|
||||||
|
|
||||||
export const signatureUtils = {
|
|
||||||
isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
|
|
||||||
const dataBuff = ethUtil.toBuffer(data);
|
|
||||||
const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
|
|
||||||
try {
|
|
||||||
const pubKey = ethUtil.ecrecover(
|
|
||||||
msgHashBuff,
|
|
||||||
signature.v,
|
|
||||||
ethUtil.toBuffer(signature.r),
|
|
||||||
ethUtil.toBuffer(signature.s),
|
|
||||||
);
|
|
||||||
const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
|
|
||||||
return retrievedAddress === signerAddress;
|
|
||||||
} catch (err) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
parseSignatureHexAsVRS(signatureHex: string): ECSignature {
|
|
||||||
const signatureBuffer = ethUtil.toBuffer(signatureHex);
|
|
||||||
let v = signatureBuffer[0];
|
|
||||||
if (v < 27) {
|
|
||||||
v += 27;
|
|
||||||
}
|
|
||||||
const r = signatureBuffer.slice(1, 33);
|
|
||||||
const s = signatureBuffer.slice(33, 65);
|
|
||||||
const ecSignature: ECSignature = {
|
|
||||||
v,
|
|
||||||
r: ethUtil.bufferToHex(r),
|
|
||||||
s: ethUtil.bufferToHex(s),
|
|
||||||
};
|
|
||||||
return ecSignature;
|
|
||||||
},
|
|
||||||
parseSignatureHexAsRSV(signatureHex: string): ECSignature {
|
|
||||||
const { v, r, s } = ethUtil.fromRpcSig(signatureHex);
|
|
||||||
const ecSignature: ECSignature = {
|
|
||||||
v,
|
|
||||||
r: ethUtil.bufferToHex(r),
|
|
||||||
s: ethUtil.bufferToHex(s),
|
|
||||||
};
|
|
||||||
return ecSignature;
|
|
||||||
},
|
|
||||||
};
|
|
@@ -1,59 +1,9 @@
|
|||||||
import { Order, SignedOrder, SolidityTypes } from '@0xproject/types';
|
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import BN = require('bn.js');
|
|
||||||
import * as ethABI from 'ethereumjs-abi';
|
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
|
||||||
import * as _ from 'lodash';
|
|
||||||
|
|
||||||
export const utils = {
|
export const utils = {
|
||||||
/**
|
|
||||||
* Converts BigNumber instance to BN
|
|
||||||
* The only reason we convert to BN is to remain compatible with `ethABI. soliditySHA3` that
|
|
||||||
* expects values of Solidity type `uint` to be passed as type `BN`.
|
|
||||||
* We do not use BN anywhere else in the codebase.
|
|
||||||
*/
|
|
||||||
bigNumberToBN(value: BigNumber) {
|
|
||||||
return new BN(value.toString(), 10);
|
|
||||||
},
|
|
||||||
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 {
|
|
||||||
const orderParts = [
|
|
||||||
{ value: order.exchangeContractAddress, type: SolidityTypes.Address },
|
|
||||||
{ value: order.maker, type: SolidityTypes.Address },
|
|
||||||
{ value: order.taker, type: SolidityTypes.Address },
|
|
||||||
{ value: order.makerTokenAddress, type: SolidityTypes.Address },
|
|
||||||
{ value: order.takerTokenAddress, type: SolidityTypes.Address },
|
|
||||||
{ value: order.feeRecipient, type: SolidityTypes.Address },
|
|
||||||
{
|
|
||||||
value: utils.bigNumberToBN(order.makerTokenAmount),
|
|
||||||
type: SolidityTypes.Uint256,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: utils.bigNumberToBN(order.takerTokenAmount),
|
|
||||||
type: SolidityTypes.Uint256,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: utils.bigNumberToBN(order.makerFee),
|
|
||||||
type: SolidityTypes.Uint256,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: utils.bigNumberToBN(order.takerFee),
|
|
||||||
type: SolidityTypes.Uint256,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: utils.bigNumberToBN(order.expirationUnixTimestampSec),
|
|
||||||
type: SolidityTypes.Uint256,
|
|
||||||
},
|
|
||||||
{ value: utils.bigNumberToBN(order.salt), type: SolidityTypes.Uint256 },
|
|
||||||
];
|
|
||||||
const types = _.map(orderParts, o => o.type);
|
|
||||||
const values = _.map(orderParts, o => o.value);
|
|
||||||
const hashBuff = ethABI.soliditySHA3(types, values);
|
|
||||||
const hashHex = ethUtil.bufferToHex(hashBuff);
|
|
||||||
return hashHex;
|
|
||||||
},
|
|
||||||
getCurrentUnixTimestampSec(): BigNumber {
|
getCurrentUnixTimestampSec(): BigNumber {
|
||||||
return new BigNumber(Date.now() / 1000).round();
|
return new BigNumber(Date.now() / 1000).round();
|
||||||
},
|
},
|
||||||
|
@@ -3,6 +3,7 @@ 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 path from 'path';
|
||||||
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';
|
||||||
@@ -10,19 +11,20 @@ import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, Zero
|
|||||||
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 { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
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', () => {
|
||||||
|
let zeroEx: ZeroEx;
|
||||||
|
before(async () => {
|
||||||
const config = {
|
const config = {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
const zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
|
});
|
||||||
describe('#setProvider', () => {
|
describe('#setProvider', () => {
|
||||||
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
|
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
|
||||||
// Instantiate the contract instances with the current provider
|
// Instantiate the contract instances with the current provider
|
||||||
@@ -31,10 +33,9 @@ describe('ZeroEx library', () => {
|
|||||||
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
|
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
|
||||||
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
|
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
|
||||||
|
|
||||||
const newProvider = web3Factory.getRpcProvider();
|
|
||||||
// Add property to newProvider so that we can differentiate it from old provider
|
// Add property to newProvider so that we can differentiate it from old provider
|
||||||
(newProvider as any).zeroExTestId = 1;
|
(provider as any).zeroExTestId = 1;
|
||||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID);
|
||||||
|
|
||||||
// Check that contractInstances with old provider are removed after provider update
|
// Check that contractInstances with old provider are removed after provider update
|
||||||
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined();
|
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined();
|
||||||
@@ -60,14 +61,12 @@ describe('ZeroEx library', () => {
|
|||||||
};
|
};
|
||||||
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();
|
|
||||||
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();
|
|
||||||
return expect(
|
return expect(
|
||||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
|
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
|
||||||
dataHex,
|
dataHex,
|
||||||
@@ -78,45 +77,16 @@ describe('ZeroEx library', () => {
|
|||||||
});
|
});
|
||||||
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();
|
|
||||||
return expect(
|
return expect(
|
||||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
|
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
|
||||||
).to.become(false);
|
).to.become(false);
|
||||||
});
|
});
|
||||||
it('should return true if the signature does pertain to the dataHex & address', async () => {
|
it('should return true if the signature does pertain to the dataHex & address', async () => {
|
||||||
const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address);
|
|
||||||
expect(isValidSignatureLocal).to.be.true();
|
|
||||||
return expect(
|
return expect(
|
||||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address),
|
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address),
|
||||||
).to.become(true);
|
).to.become(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#generateSalt', () => {
|
|
||||||
it('generates different salts', () => {
|
|
||||||
const equal = ZeroEx.generatePseudoRandomSalt().eq(ZeroEx.generatePseudoRandomSalt());
|
|
||||||
expect(equal).to.be.false();
|
|
||||||
});
|
|
||||||
it('generates salt in range [0..2^256)', () => {
|
|
||||||
const salt = ZeroEx.generatePseudoRandomSalt();
|
|
||||||
expect(salt.greaterThanOrEqualTo(0)).to.be.true();
|
|
||||||
const twoPow256 = new BigNumber(2).pow(256);
|
|
||||||
expect(salt.lessThan(twoPow256)).to.be.true();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('#isValidOrderHash', () => {
|
|
||||||
it('returns false if the value is not a hex string', () => {
|
|
||||||
const isValid = ZeroEx.isValidOrderHash('not a hex');
|
|
||||||
expect(isValid).to.be.false();
|
|
||||||
});
|
|
||||||
it('returns false if the length is wrong', () => {
|
|
||||||
const isValid = ZeroEx.isValidOrderHash('0xdeadbeef');
|
|
||||||
expect(isValid).to.be.false();
|
|
||||||
});
|
|
||||||
it('returns true if order hash is correct', () => {
|
|
||||||
const isValid = ZeroEx.isValidOrderHash('0x' + Array(65).join('0'));
|
|
||||||
expect(isValid).to.be.true();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('#toUnitAmount', () => {
|
describe('#toUnitAmount', () => {
|
||||||
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);
|
||||||
@@ -149,106 +119,6 @@ describe('ZeroEx library', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getOrderHashHex', () => {
|
|
||||||
const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';
|
|
||||||
const fakeExchangeContractAddress = '0xb69e673309512a9d726f87304c6984054f87a93b';
|
|
||||||
const order: Order = {
|
|
||||||
maker: constants.NULL_ADDRESS,
|
|
||||||
taker: constants.NULL_ADDRESS,
|
|
||||||
feeRecipient: constants.NULL_ADDRESS,
|
|
||||||
makerTokenAddress: constants.NULL_ADDRESS,
|
|
||||||
takerTokenAddress: constants.NULL_ADDRESS,
|
|
||||||
exchangeContractAddress: fakeExchangeContractAddress,
|
|
||||||
salt: new BigNumber(0),
|
|
||||||
makerFee: new BigNumber(0),
|
|
||||||
takerFee: new BigNumber(0),
|
|
||||||
makerTokenAmount: new BigNumber(0),
|
|
||||||
takerTokenAmount: new BigNumber(0),
|
|
||||||
expirationUnixTimestampSec: new BigNumber(0),
|
|
||||||
};
|
|
||||||
it('calculates the order hash', async () => {
|
|
||||||
const orderHash = ZeroEx.getOrderHashHex(order);
|
|
||||||
expect(orderHash).to.be.equal(expectedOrderHash);
|
|
||||||
});
|
|
||||||
it('throws a readable error message if taker format is invalid', async () => {
|
|
||||||
const orderWithInvalidtakerFormat = {
|
|
||||||
...order,
|
|
||||||
taker: (null as any) as string,
|
|
||||||
};
|
|
||||||
const expectedErrorMessage =
|
|
||||||
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
|
||||||
expect(() => ZeroEx.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('#signOrderHashAsync', () => {
|
|
||||||
let stubs: Sinon.SinonStub[] = [];
|
|
||||||
let makerAddress: string;
|
|
||||||
before(async () => {
|
|
||||||
const availableAddreses = await zeroEx.getAvailableAddressesAsync();
|
|
||||||
makerAddress = availableAddreses[0];
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
// clean up any stubs after the test has completed
|
|
||||||
_.each(stubs, s => s.restore());
|
|
||||||
stubs = [];
|
|
||||||
});
|
|
||||||
it('Should return the correct ECSignature', async () => {
|
|
||||||
const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
|
|
||||||
const expectedECSignature = {
|
|
||||||
v: 27,
|
|
||||||
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
|
|
||||||
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
|
|
||||||
};
|
|
||||||
const ecSignature = await zeroEx.signOrderHashAsync(
|
|
||||||
orderHash,
|
|
||||||
makerAddress,
|
|
||||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
|
||||||
);
|
|
||||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
|
||||||
});
|
|
||||||
it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => {
|
|
||||||
const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
|
|
||||||
const signature =
|
|
||||||
'0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb021b';
|
|
||||||
const expectedECSignature = {
|
|
||||||
v: 27,
|
|
||||||
r: '0x22109d11d79cb8bf96ed88625e1cd9558800c4073332a9a02857499883ee5ce3',
|
|
||||||
s: '0x050aa3cc1f2c435e67e114cdce54b9527b4f50548342401bc5d2b77adbdacb02',
|
|
||||||
};
|
|
||||||
stubs = [
|
|
||||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signMessageAsync').returns(Promise.resolve(signature)),
|
|
||||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
|
||||||
];
|
|
||||||
|
|
||||||
const ecSignature = await zeroEx.signOrderHashAsync(
|
|
||||||
orderHash,
|
|
||||||
makerAddress,
|
|
||||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
|
||||||
);
|
|
||||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
|
||||||
});
|
|
||||||
it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => {
|
|
||||||
const orderHash = '0xc793e33ffded933b76f2f48d9aa3339fc090399d5e7f5dec8d3660f5480793f7';
|
|
||||||
const signature =
|
|
||||||
'0x1bc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee02dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960';
|
|
||||||
const expectedECSignature = {
|
|
||||||
v: 27,
|
|
||||||
r: '0xc80bedc6756722672753413efdd749b5adbd4fd552595f59c13427407ee9aee0',
|
|
||||||
s: '0x2dea66f25a608bbae457e020fb6decb763deb8b7192abab624997242da248960',
|
|
||||||
};
|
|
||||||
stubs = [
|
|
||||||
Sinon.stub((zeroEx as any)._web3Wrapper, 'signMessageAsync').returns(Promise.resolve(signature)),
|
|
||||||
Sinon.stub(ZeroEx, 'isValidSignature').returns(true),
|
|
||||||
];
|
|
||||||
|
|
||||||
const ecSignature = await zeroEx.signOrderHashAsync(
|
|
||||||
orderHash,
|
|
||||||
makerAddress,
|
|
||||||
SHOULD_ADD_PERSONAL_MESSAGE_PREFIX,
|
|
||||||
);
|
|
||||||
expect(ecSignature).to.deep.equal(expectedECSignature);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('#awaitTransactionMinedAsync', () => {
|
describe('#awaitTransactionMinedAsync', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await blockchainLifecycle.startAsync();
|
await blockchainLifecycle.startAsync();
|
||||||
@@ -278,7 +148,7 @@ describe('ZeroEx library', () => {
|
|||||||
exchangeContractAddress: ZeroEx.NULL_ADDRESS,
|
exchangeContractAddress: ZeroEx.NULL_ADDRESS,
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
const zeroExWithWrongExchangeAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig);
|
||||||
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
|
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
|
||||||
});
|
});
|
||||||
it('allows to specify token registry token contract address', async () => {
|
it('allows to specify token registry token contract address', async () => {
|
||||||
@@ -286,7 +156,7 @@ describe('ZeroEx library', () => {
|
|||||||
tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS,
|
tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS,
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(provider, zeroExConfig);
|
||||||
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal(
|
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal(
|
||||||
ZeroEx.NULL_ADDRESS,
|
ZeroEx.NULL_ADDRESS,
|
||||||
);
|
);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
|
import { web3Factory } from '@0xproject/dev-utils';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import HDWalletProvider = require('truffle-hdwallet-provider');
|
|
||||||
|
|
||||||
import { ZeroEx } from '../src';
|
import { ZeroEx } from '../src';
|
||||||
|
|
||||||
@@ -14,14 +14,11 @@ const TIMEOUT = 10000;
|
|||||||
describe('Artifacts', () => {
|
describe('Artifacts', () => {
|
||||||
describe('contracts are deployed on kovan', () => {
|
describe('contracts are deployed on kovan', () => {
|
||||||
const kovanRpcUrl = constants.KOVAN_RPC_URL;
|
const kovanRpcUrl = constants.KOVAN_RPC_URL;
|
||||||
const packageJSONContent = fs.readFileSync('package.json', 'utf-8');
|
const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider;
|
||||||
const packageJSON = JSON.parse(packageJSONContent);
|
|
||||||
const mnemonic = packageJSON.config.mnemonic;
|
|
||||||
const web3Provider = new HDWalletProvider(mnemonic, kovanRpcUrl);
|
|
||||||
const config = {
|
const config = {
|
||||||
networkId: constants.KOVAN_NETWORK_ID,
|
networkId: constants.KOVAN_NETWORK_ID,
|
||||||
};
|
};
|
||||||
const zeroEx = new ZeroEx(web3Provider, config);
|
const zeroEx = new ZeroEx(provider, config);
|
||||||
it('token registry contract is deployed', async () => {
|
it('token registry contract is deployed', async () => {
|
||||||
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
|
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
|
||||||
}).timeout(TIMEOUT);
|
}).timeout(TIMEOUT);
|
||||||
@@ -34,14 +31,11 @@ describe('Artifacts', () => {
|
|||||||
});
|
});
|
||||||
describe('contracts are deployed on ropsten', () => {
|
describe('contracts are deployed on ropsten', () => {
|
||||||
const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
|
const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
|
||||||
const packageJSONContent = fs.readFileSync('package.json', 'utf-8');
|
const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider;
|
||||||
const packageJSON = JSON.parse(packageJSONContent);
|
|
||||||
const mnemonic = packageJSON.config.mnemonic;
|
|
||||||
const web3Provider = new HDWalletProvider(mnemonic, ropstenRpcUrl);
|
|
||||||
const config = {
|
const config = {
|
||||||
networkId: constants.ROPSTEN_NETWORK_ID,
|
networkId: constants.ROPSTEN_NETWORK_ID,
|
||||||
};
|
};
|
||||||
const zeroEx = new ZeroEx(web3Provider, config);
|
const zeroEx = new ZeroEx(provider, config);
|
||||||
it('token registry contract is deployed', async () => {
|
it('token registry contract is deployed', async () => {
|
||||||
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
|
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
|
||||||
}).timeout(TIMEOUT);
|
}).timeout(TIMEOUT);
|
||||||
|
@@ -1,43 +0,0 @@
|
|||||||
import { web3Factory } from '@0xproject/dev-utils';
|
|
||||||
import * as chai from 'chai';
|
|
||||||
import 'mocha';
|
|
||||||
|
|
||||||
import { ZeroEx } from '../src';
|
|
||||||
import { assert } from '../src/utils/assert';
|
|
||||||
|
|
||||||
import { constants } from './utils/constants';
|
|
||||||
|
|
||||||
const expect = chai.expect;
|
|
||||||
|
|
||||||
describe('Assertion library', () => {
|
|
||||||
const web3 = web3Factory.create();
|
|
||||||
const config = {
|
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
|
||||||
};
|
|
||||||
const zeroEx = new ZeroEx(web3.currentProvider, config);
|
|
||||||
describe('#isSenderAddressHexAsync', () => {
|
|
||||||
it('throws when address is invalid', async () => {
|
|
||||||
const address = '0xdeadbeef';
|
|
||||||
const varName = 'address';
|
|
||||||
return expect(
|
|
||||||
assert.isSenderAddressAsync(varName, address, (zeroEx as any)._web3Wrapper),
|
|
||||||
).to.be.rejectedWith(`Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`);
|
|
||||||
});
|
|
||||||
it('throws when address is unavailable', async () => {
|
|
||||||
const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42';
|
|
||||||
const varName = 'address';
|
|
||||||
return expect(
|
|
||||||
assert.isSenderAddressAsync(varName, validUnrelatedAddress, (zeroEx as any)._web3Wrapper),
|
|
||||||
).to.be.rejectedWith(
|
|
||||||
`Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it("doesn't throw if address is available", async () => {
|
|
||||||
const availableAddress = (await zeroEx.getAvailableAddressesAsync())[0];
|
|
||||||
const varName = 'address';
|
|
||||||
return expect(
|
|
||||||
assert.isSenderAddressAsync(varName, availableAddress, (zeroEx as any)._web3Wrapper),
|
|
||||||
).to.become(undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
@@ -3,7 +3,6 @@ import { BigNumber } from '@0xproject/utils';
|
|||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
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 {
|
import {
|
||||||
ApprovalContractEventArgs,
|
ApprovalContractEventArgs,
|
||||||
@@ -24,7 +23,7 @@ import { chaiSetup } from './utils/chai_setup';
|
|||||||
import { constants } from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import { reportNodeCallbackErrors } 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 { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -55,7 +54,7 @@ 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 () => {
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
|
zeroEx = new ZeroEx(provider, 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];
|
||||||
@@ -79,7 +78,7 @@ describe('EtherTokenWrapper', () => {
|
|||||||
const UNKNOWN_NETWORK_NETWORK_ID = 10;
|
const UNKNOWN_NETWORK_NETWORK_ID = 10;
|
||||||
expect(
|
expect(
|
||||||
() =>
|
() =>
|
||||||
new ZeroEx(web3.currentProvider, {
|
new ZeroEx(provider, {
|
||||||
networkId: UNKNOWN_NETWORK_NETWORK_ID,
|
networkId: UNKNOWN_NETWORK_NETWORK_ID,
|
||||||
} as any),
|
} as any),
|
||||||
).to.throw();
|
).to.throw();
|
||||||
@@ -261,8 +260,7 @@ describe('EtherTokenWrapper', () => {
|
|||||||
callbackNeverToBeCalled,
|
callbackNeverToBeCalled,
|
||||||
);
|
);
|
||||||
const callbackToBeCalled = reportNodeCallbackErrors(done)();
|
const callbackToBeCalled = reportNodeCallbackErrors(done)();
|
||||||
const newProvider = web3Factory.getRpcProvider();
|
zeroEx.setProvider(provider, 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,
|
etherTokenAddress,
|
||||||
|
@@ -5,7 +5,6 @@ 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 { LogEvent } from '../src';
|
import { LogEvent } from '../src';
|
||||||
import { EventWatcher } from '../src/order_watcher/event_watcher';
|
import { EventWatcher } from '../src/order_watcher/event_watcher';
|
||||||
@@ -13,12 +12,12 @@ import { DoneCallback } from '../src/types';
|
|||||||
|
|
||||||
import { chaiSetup } from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import { reportNodeCallbackErrors } from './utils/report_callback_errors';
|
import { reportNodeCallbackErrors } from './utils/report_callback_errors';
|
||||||
|
import { provider } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
describe('EventWatcher', () => {
|
describe('EventWatcher', () => {
|
||||||
let web3: Web3;
|
|
||||||
let stubs: Sinon.SinonStub[] = [];
|
let stubs: Sinon.SinonStub[] = [];
|
||||||
let eventWatcher: EventWatcher;
|
let eventWatcher: EventWatcher;
|
||||||
let web3Wrapper: Web3Wrapper;
|
let web3Wrapper: Web3Wrapper;
|
||||||
@@ -53,9 +52,8 @@ describe('EventWatcher', () => {
|
|||||||
transactionIndex: 0,
|
transactionIndex: 0,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
web3 = web3Factory.create();
|
|
||||||
const pollingIntervalMs = 10;
|
const pollingIntervalMs = 10;
|
||||||
web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
web3Wrapper = new Web3Wrapper(provider);
|
||||||
eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalMs);
|
eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalMs);
|
||||||
});
|
});
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@@ -9,7 +9,7 @@ import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simula
|
|||||||
|
|
||||||
import { chaiSetup } from './utils/chai_setup';
|
import { chaiSetup } from './utils/chai_setup';
|
||||||
import { constants } from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -19,7 +19,7 @@ describe('ExchangeTransferSimulator', () => {
|
|||||||
const config = {
|
const config = {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
const zeroEx = new ZeroEx(web3.currentProvider, config);
|
const zeroEx = new ZeroEx(provider, config);
|
||||||
const transferAmount = new BigNumber(5);
|
const transferAmount = new BigNumber(5);
|
||||||
let userAddresses: string[];
|
let userAddresses: string[];
|
||||||
let tokens: Token[];
|
let tokens: Token[];
|
||||||
|
@@ -4,7 +4,6 @@ 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 Web3 from 'web3';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BlockRange,
|
BlockRange,
|
||||||
@@ -15,6 +14,7 @@ import {
|
|||||||
LogFillContractEventArgs,
|
LogFillContractEventArgs,
|
||||||
OrderCancellationRequest,
|
OrderCancellationRequest,
|
||||||
OrderFillRequest,
|
OrderFillRequest,
|
||||||
|
OrderState,
|
||||||
SignedOrder,
|
SignedOrder,
|
||||||
Token,
|
Token,
|
||||||
ZeroEx,
|
ZeroEx,
|
||||||
@@ -26,7 +26,7 @@ import { constants } from './utils/constants';
|
|||||||
import { FillScenarios } from './utils/fill_scenarios';
|
import { FillScenarios } from './utils/fill_scenarios';
|
||||||
import { reportNodeCallbackErrors } 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 { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -46,7 +46,7 @@ describe('ExchangeWrapper', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
@@ -977,8 +977,7 @@ describe('ExchangeWrapper', () => {
|
|||||||
);
|
);
|
||||||
zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled);
|
zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled);
|
||||||
|
|
||||||
const newProvider = web3Factory.getRpcProvider();
|
zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID);
|
||||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
|
||||||
|
|
||||||
const callback = reportNodeCallbackErrors(done)(
|
const callback = reportNodeCallbackErrors(done)(
|
||||||
(logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
|
(logEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
|
||||||
@@ -1156,4 +1155,41 @@ describe('ExchangeWrapper', () => {
|
|||||||
expect(args.maker).to.be.equal(differentMakerAddress);
|
expect(args.maker).to.be.equal(differentMakerAddress);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('#getOrderStateAsync', () => {
|
||||||
|
let maker: string;
|
||||||
|
let taker: string;
|
||||||
|
let makerToken: Token;
|
||||||
|
let takerToken: Token;
|
||||||
|
let signedOrder: SignedOrder;
|
||||||
|
let orderState: OrderState;
|
||||||
|
const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), constants.ZRX_DECIMALS);
|
||||||
|
before(async () => {
|
||||||
|
[, maker, taker] = userAddresses;
|
||||||
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
|
[makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||||
|
});
|
||||||
|
it('should report orderStateValid when order is fillable', async () => {
|
||||||
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
|
);
|
||||||
|
orderState = await zeroEx.exchange.getOrderStateAsync(signedOrder);
|
||||||
|
expect(orderState.isValid).to.be.true();
|
||||||
|
});
|
||||||
|
it('should report orderStateInvalid when maker allowance set to 0', async () => {
|
||||||
|
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
|
makerToken.address,
|
||||||
|
takerToken.address,
|
||||||
|
maker,
|
||||||
|
taker,
|
||||||
|
fillableAmount,
|
||||||
|
);
|
||||||
|
await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0));
|
||||||
|
orderState = await zeroEx.exchange.getOrderStateAsync(signedOrder);
|
||||||
|
expect(orderState.isValid).to.be.false();
|
||||||
|
});
|
||||||
|
});
|
||||||
}); // tslint:disable:max-file-line-count
|
}); // tslint:disable:max-file-line-count
|
||||||
|
@@ -4,7 +4,6 @@ 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 { 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';
|
||||||
@@ -16,7 +15,7 @@ import { constants } from './utils/constants';
|
|||||||
import { FillScenarios } from './utils/fill_scenarios';
|
import { FillScenarios } from './utils/fill_scenarios';
|
||||||
import { reportNoErrorCallbackErrors } 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 { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -44,7 +43,7 @@ describe('ExpirationWatcher', () => {
|
|||||||
const config = {
|
const config = {
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
@@ -154,4 +153,43 @@ describe('ExpirationWatcher', () => {
|
|||||||
timer.tick(order2Lifetime * 1000);
|
timer.tick(order2Lifetime * 1000);
|
||||||
})().catch(done);
|
})().catch(done);
|
||||||
});
|
});
|
||||||
|
it('emits events in correct order when expirations are equal', (done: DoneCallback) => {
|
||||||
|
(async () => {
|
||||||
|
const order1Lifetime = 60;
|
||||||
|
const order2Lifetime = 60;
|
||||||
|
const order1ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order1Lifetime);
|
||||||
|
const order2ExpirationUnixTimestampSec = currentUnixTimestampSec.plus(order2Lifetime);
|
||||||
|
const signedOrder1 = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
order1ExpirationUnixTimestampSec,
|
||||||
|
);
|
||||||
|
const signedOrder2 = await fillScenarios.createFillableSignedOrderAsync(
|
||||||
|
makerTokenAddress,
|
||||||
|
takerTokenAddress,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
order2ExpirationUnixTimestampSec,
|
||||||
|
);
|
||||||
|
const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1);
|
||||||
|
const orderHash2 = ZeroEx.getOrderHashHex(signedOrder2);
|
||||||
|
expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000));
|
||||||
|
expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000));
|
||||||
|
const expirationOrder = orderHash1 < orderHash2 ? [orderHash1, orderHash2] : [orderHash2, orderHash1];
|
||||||
|
const expectToBeCalledOnce = false;
|
||||||
|
const callbackAsync = reportNoErrorCallbackErrors(done, expectToBeCalledOnce)((hash: string) => {
|
||||||
|
const orderHash = expirationOrder.shift();
|
||||||
|
expect(hash).to.be.equal(orderHash);
|
||||||
|
if (_.isEmpty(expirationOrder)) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expirationWatcher.subscribe(callbackAsync);
|
||||||
|
timer.tick(order2Lifetime * 1000);
|
||||||
|
})().catch(done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
7
packages/0x.js/test/global_hooks.ts
Normal file
7
packages/0x.js/test/global_hooks.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { runMigrationsAsync } from '@0xproject/migrations';
|
||||||
|
|
||||||
|
import { deployer } from './utils/deployer';
|
||||||
|
|
||||||
|
before('migrate contracts', async () => {
|
||||||
|
await runMigrationsAsync(deployer);
|
||||||
|
});
|
@@ -3,7 +3,6 @@ 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 Web3 from 'web3';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ExchangeContractErrs,
|
ExchangeContractErrs,
|
||||||
@@ -23,7 +22,7 @@ import { constants } from './utils/constants';
|
|||||||
import { FillScenarios } from './utils/fill_scenarios';
|
import { FillScenarios } from './utils/fill_scenarios';
|
||||||
import { reportNodeCallbackErrors } 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 { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
const TIMEOUT_MS = 150;
|
const TIMEOUT_MS = 150;
|
||||||
|
|
||||||
@@ -51,7 +50,7 @@ describe('OrderStateWatcher', () => {
|
|||||||
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 () => {
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
orderStateWatcher = zeroEx.createOrderStateWatcher();
|
orderStateWatcher = zeroEx.createOrderStateWatcher();
|
||||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||||
|
import { OrderError } from '@0xproject/order-utils';
|
||||||
import { BlockParamLiteral } from '@0xproject/types';
|
import { BlockParamLiteral } from '@0xproject/types';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
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 { ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError } from '../src';
|
import { ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError } from '../src';
|
||||||
import { TradeSide, TransferType } from '../src/types';
|
import { TradeSide, TransferType } from '../src/types';
|
||||||
@@ -14,7 +14,7 @@ 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 { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -40,7 +40,7 @@ describe('OrderValidation', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
exchangeContractAddress = zeroEx.exchange.getContractAddress();
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||||
@@ -69,6 +69,40 @@ describe('OrderValidation', () => {
|
|||||||
);
|
);
|
||||||
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||||
});
|
});
|
||||||
|
it('should succeed if the maker is buying ZRX and has no ZRX balance', async () => {
|
||||||
|
const makerFee = new BigNumber(2);
|
||||||
|
const takerFee = new BigNumber(2);
|
||||||
|
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
|
makerTokenAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
makerAddress,
|
||||||
|
takerAddress,
|
||||||
|
fillableAmount,
|
||||||
|
feeRecipient,
|
||||||
|
);
|
||||||
|
const zrxMakerBalance = await zeroEx.token.getBalanceAsync(zrxTokenAddress, makerAddress);
|
||||||
|
await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance);
|
||||||
|
await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder);
|
||||||
|
});
|
||||||
|
it('should succeed if the maker is buying ZRX and has no ZRX balance and there is no specified taker', async () => {
|
||||||
|
const makerFee = new BigNumber(2);
|
||||||
|
const takerFee = new BigNumber(2);
|
||||||
|
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||||
|
makerTokenAddress,
|
||||||
|
zrxTokenAddress,
|
||||||
|
makerFee,
|
||||||
|
takerFee,
|
||||||
|
makerAddress,
|
||||||
|
constants.NULL_ADDRESS,
|
||||||
|
fillableAmount,
|
||||||
|
feeRecipient,
|
||||||
|
);
|
||||||
|
const zrxMakerBalance = await zeroEx.token.getBalanceAsync(zrxTokenAddress, makerAddress);
|
||||||
|
await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance);
|
||||||
|
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);
|
||||||
@@ -136,7 +170,7 @@ describe('OrderValidation', () => {
|
|||||||
signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27;
|
signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27;
|
||||||
return expect(
|
return expect(
|
||||||
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
|
zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress),
|
||||||
).to.be.rejectedWith(ZeroExError.InvalidSignature);
|
).to.be.rejectedWith(OrderError.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(
|
||||||
@@ -470,4 +504,4 @@ describe('OrderValidation', () => {
|
|||||||
expect(partialTakerFee).to.be.bignumber.equal(takerPartialFee);
|
expect(partialTakerFee).to.be.bignumber.equal(takerPartialFee);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}); // tslint:disable-line:max-file-line-count
|
||||||
|
@@ -3,7 +3,6 @@ import { BigNumber } from '@0xproject/utils';
|
|||||||
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 { ApprovalContractEventArgs, DecodedLogEvent, Token, TokenEvents, ZeroEx } from '../src';
|
import { ApprovalContractEventArgs, DecodedLogEvent, Token, TokenEvents, ZeroEx } from '../src';
|
||||||
import { DoneCallback } from '../src/types';
|
import { DoneCallback } from '../src/types';
|
||||||
@@ -11,7 +10,7 @@ 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 { assertNodeCallbackError } from './utils/report_callback_errors';
|
import { assertNodeCallbackError } from './utils/report_callback_errors';
|
||||||
import { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
@@ -26,7 +25,7 @@ describe('SubscriptionTest', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
coinbase = userAddresses[0];
|
coinbase = userAddresses[0];
|
||||||
|
@@ -8,7 +8,7 @@ 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 { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -31,7 +31,7 @@ describe('TokenRegistryWrapper', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||||
_.map(tokens, token => {
|
_.map(tokens, token => {
|
||||||
tokenAddressBySymbol[token.symbol] = token.address;
|
tokenAddressBySymbol[token.symbol] = token.address;
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
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 { provider } from './utils/web3_wrapper';
|
||||||
|
|
||||||
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;
|
||||||
@@ -16,7 +15,7 @@ describe('TokenTransferProxyWrapper', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
});
|
});
|
||||||
describe('#isAuthorizedAsync', () => {
|
describe('#isAuthorizedAsync', () => {
|
||||||
it('should return false if the address is not authorized', async () => {
|
it('should return false if the address is not authorized', async () => {
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
|
||||||
|
import { EmptyWalletSubprovider } from '@0xproject/subproviders';
|
||||||
|
import { Provider } from '@0xproject/types';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
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 Web3ProviderEngine = require('web3-provider-engine');
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApprovalContractEventArgs,
|
ApprovalContractEventArgs,
|
||||||
@@ -22,7 +23,7 @@ import { chaiSetup } from './utils/chai_setup';
|
|||||||
import { constants } from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import { reportNodeCallbackErrors } 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 { web3, web3Wrapper } from './utils/web3_wrapper';
|
import { provider, web3Wrapper } from './utils/web3_wrapper';
|
||||||
|
|
||||||
chaiSetup.configure();
|
chaiSetup.configure();
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@@ -39,7 +40,7 @@ describe('TokenWrapper', () => {
|
|||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
};
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
zeroEx = new ZeroEx(provider, config);
|
||||||
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);
|
||||||
@@ -164,7 +165,7 @@ describe('TokenWrapper', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getBalanceAsync', () => {
|
describe('#getBalanceAsync', () => {
|
||||||
describe('With web3 provider with accounts', () => {
|
describe('With provider with accounts', () => {
|
||||||
it('should return the balance for an existing ERC20 token', async () => {
|
it('should return the balance for an existing ERC20 token', async () => {
|
||||||
const token = tokens[0];
|
const token = tokens[0];
|
||||||
const ownerAddress = coinbase;
|
const ownerAddress = coinbase;
|
||||||
@@ -187,14 +188,14 @@ describe('TokenWrapper', () => {
|
|||||||
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
return expect(balance).to.be.bignumber.equal(expectedBalance);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('With web3 provider without accounts', () => {
|
describe('With provider without accounts', () => {
|
||||||
let zeroExWithoutAccounts: ZeroEx;
|
let zeroExWithoutAccounts: ZeroEx;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const hasAddresses = false;
|
const hasAddresses = false;
|
||||||
const web3WithoutAccounts = web3Factory.create({ hasAddresses });
|
const emptyWalletProvider = addEmptyWalletSubprovider(provider);
|
||||||
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
zeroExWithoutAccounts = new ZeroEx(emptyWalletProvider, config);
|
||||||
});
|
});
|
||||||
it('should return balance even when called with Web3 provider instance without addresses', async () => {
|
it('should return balance even when called with 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);
|
||||||
@@ -277,7 +278,7 @@ describe('TokenWrapper', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#getAllowanceAsync', () => {
|
describe('#getAllowanceAsync', () => {
|
||||||
describe('With web3 provider with accounts', () => {
|
describe('With provider with accounts', () => {
|
||||||
it('should get the proxy allowance', async () => {
|
it('should get the proxy allowance', async () => {
|
||||||
const token = tokens[0];
|
const token = tokens[0];
|
||||||
const ownerAddress = coinbase;
|
const ownerAddress = coinbase;
|
||||||
@@ -299,12 +300,12 @@ describe('TokenWrapper', () => {
|
|||||||
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('With web3 provider without accounts', () => {
|
describe('With provider without accounts', () => {
|
||||||
let zeroExWithoutAccounts: ZeroEx;
|
let zeroExWithoutAccounts: ZeroEx;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const hasAddresses = false;
|
const hasAddresses = false;
|
||||||
const web3WithoutAccounts = web3Factory.create({ hasAddresses });
|
const emptyWalletProvider = addEmptyWalletSubprovider(provider);
|
||||||
zeroExWithoutAccounts = new ZeroEx(web3WithoutAccounts.currentProvider, config);
|
zeroExWithoutAccounts = new ZeroEx(emptyWalletProvider, config);
|
||||||
});
|
});
|
||||||
it('should get the proxy allowance', async () => {
|
it('should get the proxy allowance', async () => {
|
||||||
const token = tokens[0];
|
const token = tokens[0];
|
||||||
@@ -424,8 +425,7 @@ describe('TokenWrapper', () => {
|
|||||||
);
|
);
|
||||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
||||||
const callbackToBeCalled = reportNodeCallbackErrors(done)();
|
const callbackToBeCalled = reportNodeCallbackErrors(done)();
|
||||||
const newProvider = web3Factory.getRpcProvider();
|
zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID);
|
||||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
|
||||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled);
|
zeroEx.token.subscribe(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);
|
||||||
@@ -515,3 +515,14 @@ describe('TokenWrapper', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
// tslint:disable:max-file-line-count
|
// tslint:disable:max-file-line-count
|
||||||
|
|
||||||
|
function addEmptyWalletSubprovider(p: Provider): Provider {
|
||||||
|
const providerEngine = new Web3ProviderEngine();
|
||||||
|
providerEngine.addProvider(new EmptyWalletSubprovider());
|
||||||
|
const currentSubproviders = (p as any)._providers;
|
||||||
|
for (const subprovider of currentSubproviders) {
|
||||||
|
providerEngine.addProvider(subprovider);
|
||||||
|
}
|
||||||
|
providerEngine.start();
|
||||||
|
return providerEngine;
|
||||||
|
}
|
||||||
|
@@ -2,19 +2,17 @@ import { Deployer } from '@0xproject/deployer';
|
|||||||
import { devConstants } from '@0xproject/dev-utils';
|
import { devConstants } from '@0xproject/dev-utils';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
import { constants } from '../util/constants';
|
import { constants } from './constants';
|
||||||
|
|
||||||
import { runMigrationsAsync } from './migrate';
|
import { provider } from './web3_wrapper';
|
||||||
|
|
||||||
|
const artifactsDir = path.resolve('test', 'artifacts');
|
||||||
const deployerOpts = {
|
const deployerOpts = {
|
||||||
artifactsDir: path.resolve('src', 'artifacts'),
|
artifactsDir,
|
||||||
jsonrpcUrl: devConstants.RPC_URL,
|
provider,
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
defaults: {
|
defaults: {
|
||||||
gas: devConstants.GAS_ESTIMATE,
|
gas: devConstants.GAS_ESTIMATE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deployer = new Deployer(deployerOpts);
|
export const deployer = new Deployer(deployerOpts);
|
||||||
|
|
||||||
runMigrationsAsync(deployer).catch(console.log);
|
|
@@ -1,10 +1,10 @@
|
|||||||
|
import { orderFactory } from '@0xproject/order-utils';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
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 { constants } from './constants';
|
import { constants } from './constants';
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ export class FillScenarios {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const signedOrder = await orderFactory.createSignedOrderAsync(
|
const signedOrder = await orderFactory.createSignedOrderAsync(
|
||||||
this._zeroEx,
|
this._zeroEx.getProvider(),
|
||||||
makerAddress,
|
makerAddress,
|
||||||
takerAddress,
|
takerAddress,
|
||||||
makerFee,
|
makerFee,
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
import { web3Factory } from '@0xproject/dev-utils';
|
import { devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||||
|
import { Provider } from '@0xproject/types';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as Web3 from 'web3';
|
|
||||||
|
|
||||||
export const web3 = web3Factory.create();
|
const web3 = web3Factory.create({ shouldUseInProcessGanache: true });
|
||||||
export const web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
const provider: Provider = web3.currentProvider;
|
||||||
|
const web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
||||||
|
|
||||||
|
export { provider, web3Wrapper };
|
||||||
|
@@ -1,4 +1,22 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1525428773,
|
||||||
|
"version": "0.2.12",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1524044013,
|
||||||
|
"version": "0.2.11",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1523462196,
|
"timestamp": 1523462196,
|
||||||
"version": "0.2.10",
|
"version": "0.2.10",
|
||||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v0.2.12 - _May 4, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v0.2.11 - _April 18, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v0.2.10 - _April 11, 2018_
|
## v0.2.10 - _April 11, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0xproject/abi-gen",
|
"name": "@0xproject/abi-gen",
|
||||||
"version": "0.2.9",
|
"version": "0.2.11",
|
||||||
"description": "Generate contract wrappers from ABI and handlebars templates",
|
"description": "Generate contract wrappers from ABI and handlebars templates",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
@@ -24,9 +24,9 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/types": "^0.5.0",
|
"@0xproject/types": "^0.6.1",
|
||||||
"@0xproject/typescript-typings": "^0.0.3",
|
"@0xproject/typescript-typings": "^0.2.0",
|
||||||
"@0xproject/utils": "^0.5.0",
|
"@0xproject/utils": "^0.5.2",
|
||||||
"chalk": "^2.3.0",
|
"chalk": "^2.3.0",
|
||||||
"glob": "^7.1.2",
|
"glob": "^7.1.2",
|
||||||
"handlebars": "^4.0.11",
|
"handlebars": "^4.0.11",
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
"yargs": "^10.0.3"
|
"yargs": "^10.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0xproject/monorepo-scripts": "^0.1.16",
|
"@0xproject/monorepo-scripts": "^0.1.18",
|
||||||
"@0xproject/tslint-config": "^0.4.14",
|
"@0xproject/tslint-config": "^0.4.16",
|
||||||
"@types/glob": "^5.0.33",
|
"@types/glob": "^5.0.33",
|
||||||
"@types/handlebars": "^4.0.36",
|
"@types/handlebars": "^4.0.36",
|
||||||
"@types/mkdirp": "^0.5.1",
|
"@types/mkdirp": "^0.5.1",
|
||||||
|
@@ -1,4 +1,22 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1525428773,
|
||||||
|
"version": "0.2.8",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1524044013,
|
||||||
|
"version": "0.2.7",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1523462196,
|
"timestamp": 1523462196,
|
||||||
"version": "0.2.6",
|
"version": "0.2.6",
|
||||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v0.2.8 - _May 4, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v0.2.7 - _April 18, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v0.2.6 - _April 11, 2018_
|
## v0.2.6 - _April 11, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0xproject/assert",
|
"name": "@0xproject/assert",
|
||||||
"version": "0.2.5",
|
"version": "0.2.7",
|
||||||
"description": "Provides a standard way of performing type and schema validation across 0x projects",
|
"description": "Provides a standard way of performing type and schema validation across 0x projects",
|
||||||
"main": "lib/src/index.js",
|
"main": "lib/src/index.js",
|
||||||
"types": "lib/src/index.d.ts",
|
"types": "lib/src/index.d.ts",
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
||||||
"clean": "shx rm -rf lib test_temp scripts",
|
"clean": "shx rm -rf lib test_temp scripts",
|
||||||
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
||||||
"run_mocha": "mocha lib/test/**/*_test.js",
|
"run_mocha": "mocha lib/test/**/*_test.js --exit",
|
||||||
"prepublishOnly": "run-p build",
|
"prepublishOnly": "run-p build",
|
||||||
"test": "run-s clean build run_mocha",
|
"test": "run-s clean build run_mocha",
|
||||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0xproject/monorepo-scripts": "^0.1.16",
|
"@0xproject/monorepo-scripts": "^0.1.18",
|
||||||
"@0xproject/tslint-config": "^0.4.14",
|
"@0xproject/tslint-config": "^0.4.16",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"@types/mocha": "^2.2.42",
|
"@types/mocha": "^2.2.42",
|
||||||
"@types/valid-url": "^1.0.2",
|
"@types/valid-url": "^1.0.2",
|
||||||
@@ -43,9 +43,9 @@
|
|||||||
"typescript": "2.7.1"
|
"typescript": "2.7.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/json-schemas": "^0.7.19",
|
"@0xproject/json-schemas": "^0.7.21",
|
||||||
"@0xproject/typescript-typings": "^0.0.3",
|
"@0xproject/typescript-typings": "^0.2.0",
|
||||||
"@0xproject/utils": "^0.5.0",
|
"@0xproject/utils": "^0.5.2",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"valid-url": "^1.0.9"
|
"valid-url": "^1.0.9"
|
||||||
},
|
},
|
||||||
|
@@ -1,4 +1,23 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "0.3.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Update ethers-contracts to ethers.js",
|
||||||
|
"pr": 540
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1525428773
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1524044013,
|
||||||
|
"version": "0.2.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v0.3.0 - _May 4, 2018_
|
||||||
|
|
||||||
|
* Update ethers-contracts to ethers.js (#540)
|
||||||
|
|
||||||
|
## v0.2.1 - _April 18, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v0.2.0 - _April 11, 2018_
|
## v0.2.0 - _April 11, 2018_
|
||||||
|
|
||||||
* Contract wrappers now accept Provider and defaults instead of Web3Wrapper (#501)
|
* Contract wrappers now accept Provider and defaults instead of Web3Wrapper (#501)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0xproject/base-contract",
|
"name": "@0xproject/base-contract",
|
||||||
"version": "0.1.0",
|
"version": "0.2.1",
|
||||||
"description": "0x Base TS contract",
|
"description": "0x Base TS contract",
|
||||||
"main": "lib/src/index.js",
|
"main": "lib/src/index.js",
|
||||||
"types": "lib/src/index.d.ts",
|
"types": "lib/src/index.d.ts",
|
||||||
@@ -26,8 +26,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0xproject/monorepo-scripts": "^0.1.16",
|
"@0xproject/monorepo-scripts": "^0.1.18",
|
||||||
"@0xproject/tslint-config": "^0.4.14",
|
"@0xproject/tslint-config": "^0.4.16",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"chai": "^4.0.1",
|
"chai": "^4.0.1",
|
||||||
"copyfiles": "^1.2.0",
|
"copyfiles": "^1.2.0",
|
||||||
@@ -38,11 +38,11 @@
|
|||||||
"typescript": "2.7.1"
|
"typescript": "2.7.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/types": "^0.5.0",
|
"@0xproject/types": "^0.6.1",
|
||||||
"@0xproject/typescript-typings": "^0.0.3",
|
"@0xproject/typescript-typings": "^0.2.0",
|
||||||
"@0xproject/utils": "^0.5.0",
|
"@0xproject/utils": "^0.5.2",
|
||||||
"@0xproject/web3-wrapper": "^0.5.0",
|
"@0xproject/web3-wrapper": "^0.6.1",
|
||||||
"ethers-contracts": "^2.2.1",
|
"ethers": "^3.0.15",
|
||||||
"lodash": "^4.17.4"
|
"lodash": "^4.17.4"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
|
@@ -10,13 +10,13 @@ import {
|
|||||||
} from '@0xproject/types';
|
} from '@0xproject/types';
|
||||||
import { abiUtils, BigNumber } from '@0xproject/utils';
|
import { abiUtils, BigNumber } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as ethersContracts from 'ethers-contracts';
|
import * as ethers from 'ethers';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { formatABIDataItem } from './utils';
|
import { formatABIDataItem } from './utils';
|
||||||
|
|
||||||
export interface EthersInterfaceByFunctionSignature {
|
export interface EthersInterfaceByFunctionSignature {
|
||||||
[key: string]: ethersContracts.Interface;
|
[key: string]: ethers.Interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BaseContract {
|
export class BaseContract {
|
||||||
@@ -62,7 +62,7 @@ export class BaseContract {
|
|||||||
}
|
}
|
||||||
return txDataWithDefaults;
|
return txDataWithDefaults;
|
||||||
}
|
}
|
||||||
protected _lookupEthersInterface(functionSignature: string): ethersContracts.Interface {
|
protected _lookupEthersInterface(functionSignature: string): ethers.Interface {
|
||||||
const ethersInterface = this._ethersInterfacesByFunctionSignature[functionSignature];
|
const ethersInterface = this._ethersInterfacesByFunctionSignature[functionSignature];
|
||||||
if (_.isUndefined(ethersInterface)) {
|
if (_.isUndefined(ethersInterface)) {
|
||||||
throw new Error(`Failed to lookup method with function signature '${functionSignature}'`);
|
throw new Error(`Failed to lookup method with function signature '${functionSignature}'`);
|
||||||
@@ -92,7 +92,7 @@ export class BaseContract {
|
|||||||
this._ethersInterfacesByFunctionSignature = {};
|
this._ethersInterfacesByFunctionSignature = {};
|
||||||
_.each(methodAbis, methodAbi => {
|
_.each(methodAbis, methodAbi => {
|
||||||
const functionSignature = abiUtils.getFunctionSignature(methodAbi);
|
const functionSignature = abiUtils.getFunctionSignature(methodAbi);
|
||||||
this._ethersInterfacesByFunctionSignature[functionSignature] = new ethersContracts.Interface([methodAbi]);
|
this._ethersInterfacesByFunctionSignature[functionSignature] = new ethers.Interface([methodAbi]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,22 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"timestamp": 1525428773,
|
||||||
|
"version": "0.6.11",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"timestamp": 1524044013,
|
||||||
|
"version": "0.6.10",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Dependencies updated"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1523462196,
|
"timestamp": 1523462196,
|
||||||
"version": "0.6.9",
|
"version": "0.6.9",
|
||||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v0.6.11 - _May 4, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
|
## v0.6.10 - _April 18, 2018_
|
||||||
|
|
||||||
|
* Dependencies updated
|
||||||
|
|
||||||
## v0.6.9 - _April 11, 2018_
|
## v0.6.9 - _April 11, 2018_
|
||||||
|
|
||||||
* Dependencies updated
|
* Dependencies updated
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0xproject/connect",
|
"name": "@0xproject/connect",
|
||||||
"version": "0.6.8",
|
"version": "0.6.10",
|
||||||
"description": "A javascript library for interacting with the standard relayer api",
|
"description": "A javascript library for interacting with the standard relayer api",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"connect",
|
"connect",
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"clean": "shx rm -rf lib test_temp scripts",
|
"clean": "shx rm -rf lib test_temp scripts",
|
||||||
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
|
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
|
||||||
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
||||||
"run_mocha": "mocha lib/test/**/*_test.js",
|
"run_mocha": "mocha lib/test/**/*_test.js --exit",
|
||||||
"test": "run-s clean build copy_test_fixtures run_mocha",
|
"test": "run-s clean build copy_test_fixtures run_mocha",
|
||||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||||
@@ -50,19 +50,19 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/assert": "^0.2.5",
|
"@0xproject/assert": "^0.2.7",
|
||||||
"@0xproject/json-schemas": "^0.7.19",
|
"@0xproject/json-schemas": "^0.7.21",
|
||||||
"@0xproject/types": "^0.5.0",
|
"@0xproject/types": "^0.6.1",
|
||||||
"@0xproject/typescript-typings": "^0.0.3",
|
"@0xproject/typescript-typings": "^0.2.0",
|
||||||
"@0xproject/utils": "^0.5.0",
|
"@0xproject/utils": "^0.5.2",
|
||||||
"isomorphic-fetch": "^2.2.1",
|
"isomorphic-fetch": "^2.2.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"query-string": "^5.0.1",
|
"query-string": "^5.0.1",
|
||||||
"websocket": "^1.0.25"
|
"websocket": "^1.0.25"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0xproject/monorepo-scripts": "^0.1.16",
|
"@0xproject/monorepo-scripts": "^0.1.18",
|
||||||
"@0xproject/tslint-config": "^0.4.14",
|
"@0xproject/tslint-config": "^0.4.16",
|
||||||
"@types/fetch-mock": "^5.12.1",
|
"@types/fetch-mock": "^5.12.1",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"@types/mocha": "^2.2.42",
|
"@types/mocha": "^2.2.42",
|
||||||
|
@@ -15,14 +15,14 @@ export interface OrderbookChannel {
|
|||||||
close: () => void;
|
close: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* heartbeatInterval: Interval in milliseconds that the orderbook channel should ping the underlying websocket. Default: 15000
|
* heartbeatInterval: Interval in milliseconds that the orderbook channel should ping the underlying websocket. Default: 15000
|
||||||
*/
|
*/
|
||||||
export interface WebSocketOrderbookChannelConfig {
|
export interface WebSocketOrderbookChannelConfig {
|
||||||
heartbeatIntervalMs?: number;
|
heartbeatIntervalMs?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* baseTokenAddress: The address of token designated as the baseToken in the currency pair calculation of price
|
* baseTokenAddress: The address of token designated as the baseToken in the currency pair calculation of price
|
||||||
* quoteTokenAddress: The address of token designated as the quoteToken in the currency pair calculation of price
|
* quoteTokenAddress: The address of token designated as the quoteToken in the currency pair calculation of price
|
||||||
* snapshot: If true, a snapshot of the orderbook will be sent before the updates to the orderbook
|
* snapshot: If true, a snapshot of the orderbook will be sent before the updates to the orderbook
|
||||||
|
@@ -8,7 +8,7 @@ import { BaseContract } from '@0xproject/base-contract';
|
|||||||
import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, MethodAbi, Provider, TxData, TxDataPayable } from '@0xproject/types';
|
import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, MethodAbi, Provider, TxData, TxDataPayable } from '@0xproject/types';
|
||||||
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as ethersContracts from 'ethers-contracts';
|
import * as ethers from 'ethers';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
{{#if events}}
|
{{#if events}}
|
||||||
|
@@ -5,20 +5,21 @@ async callAsync(
|
|||||||
defaultBlock?: BlockParam,
|
defaultBlock?: BlockParam,
|
||||||
): Promise<{{> return_type outputs=outputs}}> {
|
): Promise<{{> return_type outputs=outputs}}> {
|
||||||
const self = this as any as {{contractName}}Contract;
|
const self = this as any as {{contractName}}Contract;
|
||||||
const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
|
const functionSignature = '{{this.functionSignature}}';
|
||||||
|
const inputAbi = self._lookupAbi(functionSignature).inputs;
|
||||||
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
|
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
|
||||||
const encodedData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
|
const ethersFunction = self._lookupEthersInterface(functionSignature).functions.{{this.name}}(
|
||||||
{{> params inputs=inputs}}
|
{{> params inputs=inputs}}
|
||||||
).data;
|
) as ethers.CallDescription;
|
||||||
|
const encodedData = ethersFunction.data;
|
||||||
const callDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
const callDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||||
{
|
{
|
||||||
data: encodedData,
|
data: encodedData,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||||
|
let resultArray = ethersFunction.parse(rawCallResult);
|
||||||
const outputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).outputs;
|
const outputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).outputs;
|
||||||
const outputParamsTypes = _.map(outputAbi, 'type');
|
|
||||||
let resultArray = ethersContracts.Interface.decodeParams(outputParamsTypes, rawCallResult) as any;
|
|
||||||
resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._lowercaseAddress.bind(this));
|
resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._lowercaseAddress.bind(this));
|
||||||
resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._bnToBigNumber.bind(this));
|
resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._bnToBigNumber.bind(this));
|
||||||
return resultArray{{#singleReturnValue}}[0]{{/singleReturnValue}};
|
return resultArray{{#singleReturnValue}}[0]{{/singleReturnValue}};
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{{#if outputs.length}}
|
{{#if outputs.length}}
|
||||||
{{#singleReturnValue}}
|
{{#singleReturnValue}}
|
||||||
{{#returnType outputs.0.type components}}{{/returnType}}
|
{{#returnType outputs.0.type outputs.0.components}}{{/returnType}}
|
||||||
{{/singleReturnValue}}
|
{{/singleReturnValue}}
|
||||||
{{^singleReturnValue}}
|
{{^singleReturnValue}}
|
||||||
[{{#each outputs}}{{#returnType type components}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
[{{#each outputs}}{{#returnType type components}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||||
|
@@ -52,7 +52,7 @@ public {{this.tsName}} = {
|
|||||||
const self = this as any as {{contractName}}Contract;
|
const self = this as any as {{contractName}}Contract;
|
||||||
const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
|
const inputAbi = self._lookupAbi('{{this.functionSignature}}').inputs;
|
||||||
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
|
[{{> params inputs=inputs}}] = BaseContract._formatABIDataItemList(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(self));
|
||||||
const abiEncodedTransactionData = self._lookupEthersInterface('{{this.name}}').functions.{{this.name}}(
|
const abiEncodedTransactionData = self._lookupEthersInterface('{{this.functionSignature}}').functions.{{this.name}}(
|
||||||
{{> params inputs=inputs}}
|
{{> params inputs=inputs}}
|
||||||
).data;
|
).data;
|
||||||
return abiEncodedTransactionData;
|
return abiEncodedTransactionData;
|
||||||
|
@@ -72,17 +72,6 @@ yarn lint
|
|||||||
|
|
||||||
### Run Tests
|
### Run Tests
|
||||||
|
|
||||||
Before running the tests, you will need to spin up a [TestRPC](https://www.npmjs.com/package/ethereumjs-testrpc) instance.
|
|
||||||
|
|
||||||
In a separate terminal, start TestRPC (a convenience command is provided as part of the [0x.js monorepo](https://github.com/0xProject/0x-monorepo))
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ../..
|
|
||||||
yarn testrpc
|
|
||||||
```
|
|
||||||
|
|
||||||
Then in your main terminal run
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn test
|
yarn test
|
||||||
```
|
```
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
import { MultiSigConfigByNetwork } from '../types';
|
|
||||||
|
|
||||||
// Make a copy of this file named `multisig.js` and input custom params as needed
|
|
||||||
export const multiSig: MultiSigConfigByNetwork = {
|
|
||||||
kovan: {
|
|
||||||
owners: [],
|
|
||||||
confirmationsRequired: 0,
|
|
||||||
secondsRequired: 0,
|
|
||||||
},
|
|
||||||
};
|
|
@@ -1,23 +0,0 @@
|
|||||||
export interface MultiSigConfig {
|
|
||||||
owners: string[];
|
|
||||||
confirmationsRequired: number;
|
|
||||||
secondsRequired: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MultiSigConfigByNetwork {
|
|
||||||
[networkName: string]: MultiSigConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Token {
|
|
||||||
address?: string;
|
|
||||||
name: string;
|
|
||||||
symbol: string;
|
|
||||||
decimals: number;
|
|
||||||
ipfsHash: string;
|
|
||||||
swarmHash: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TokenInfoByNetwork {
|
|
||||||
development: Token[];
|
|
||||||
live: Token[];
|
|
||||||
}
|
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "contracts",
|
"name": "contracts",
|
||||||
"version": "2.1.21",
|
"version": "2.1.25",
|
||||||
"description": "Smart contract components of 0x protocol",
|
"description": "Smart contract components of 0x protocol",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
@@ -10,16 +10,15 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build:watch": "tsc -w",
|
"build:watch": "tsc -w",
|
||||||
"prebuild": "run-s clean compile copy_artifacts generate_contract_wrappers",
|
"prebuild": "run-s clean compile copy_artifacts generate_contract_wrappers",
|
||||||
"copy_artifacts": "copyfiles './src/artifacts/**/*' ./lib",
|
"copy_artifacts": "copyfiles -u 4 '../migrations/src/artifacts/**/*' ./lib/src/artifacts;",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"test": "run-s build run_mocha",
|
"test": "run-s build run_mocha",
|
||||||
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
|
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
|
||||||
"run_mocha": "mocha 'lib/test/**/*.js' --timeout 100000 --bail --exit",
|
"run_mocha": "mocha 'lib/test/**/*.js' --timeout 100000 --bail --exit",
|
||||||
"compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846",
|
"compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846",
|
||||||
"compile": "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contract-dirs src/contracts --artifacts-dir src/artifacts",
|
"compile": "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir src/contracts --artifacts-dir ../migrations/src/artifacts",
|
||||||
"clean": "shx rm -rf ./lib",
|
"clean": "shx rm -rf ./lib",
|
||||||
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis ${npm_package_config_abis} --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 --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
|
||||||
"migrate": "yarn build && yarn compile && node ./lib/migrations/index.js",
|
|
||||||
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
|
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
|
||||||
"coverage:report:text": "istanbul report text",
|
"coverage:report:text": "istanbul report text",
|
||||||
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
||||||
@@ -27,7 +26,7 @@
|
|||||||
"test:circleci": "yarn test:coverage"
|
"test:circleci": "yarn test:coverage"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis": "src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels).json",
|
"abis": "../migrations/src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels).json",
|
||||||
"contracts": "Exchange,DummyToken,ZRXToken,Token,WETH9,TokenTransferProxy,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,MaliciousToken,TokenRegistry,Arbitrage,EtherDelta,AccountLevels"
|
"contracts": "Exchange,DummyToken,ZRXToken,Token,WETH9,TokenTransferProxy,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,MaliciousToken,TokenRegistry,Arbitrage,EtherDelta,AccountLevels"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -41,8 +40,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0xproject/dev-utils": "^0.3.4",
|
"@0xproject/dev-utils": "^0.3.6",
|
||||||
"@0xproject/tslint-config": "^0.4.14",
|
"@0xproject/tslint-config": "^0.4.16",
|
||||||
"@types/lodash": "4.14.104",
|
"@types/lodash": "4.14.104",
|
||||||
"@types/node": "^8.0.53",
|
"@types/node": "^8.0.53",
|
||||||
"@types/yargs": "^10.0.0",
|
"@types/yargs": "^10.0.0",
|
||||||
@@ -55,18 +54,18 @@
|
|||||||
"npm-run-all": "^4.1.2",
|
"npm-run-all": "^4.1.2",
|
||||||
"prettier": "^1.11.1",
|
"prettier": "^1.11.1",
|
||||||
"shx": "^0.2.2",
|
"shx": "^0.2.2",
|
||||||
"solc": "^0.4.18",
|
"solc": "^0.4.23",
|
||||||
"tslint": "5.8.0",
|
"tslint": "5.8.0",
|
||||||
"typescript": "2.7.1",
|
"typescript": "2.7.1",
|
||||||
"yargs": "^10.0.3"
|
"yargs": "^10.0.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"0x.js": "^0.35.0",
|
"0x.js": "^0.36.3",
|
||||||
"@0xproject/deployer": "^0.3.5",
|
"@0xproject/deployer": "^0.4.1",
|
||||||
"@0xproject/types": "^0.5.0",
|
"@0xproject/types": "^0.6.1",
|
||||||
"@0xproject/typescript-typings": "^0.0.3",
|
"@0xproject/typescript-typings": "^0.2.0",
|
||||||
"@0xproject/utils": "^0.5.0",
|
"@0xproject/utils": "^0.5.2",
|
||||||
"@0xproject/web3-wrapper": "^0.5.0",
|
"@0xproject/web3-wrapper": "^0.6.1",
|
||||||
"bn.js": "^4.11.8",
|
"bn.js": "^4.11.8",
|
||||||
"ethereumjs-abi": "^0.6.4",
|
"ethereumjs-abi": "^0.6.4",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
|
@@ -46,7 +46,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
|
|
||||||
describe('changeTimeLock', () => {
|
describe('changeTimeLock', () => {
|
||||||
describe('initially non-time-locked', async () => {
|
describe('initially non-time-locked', async () => {
|
||||||
before('deploy a walet', async () => {
|
before('deploy a wallet', async () => {
|
||||||
const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
|
const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
|
||||||
owners,
|
owners,
|
||||||
SIGNATURES_REQUIRED,
|
SIGNATURES_REQUIRED,
|
||||||
@@ -143,7 +143,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('initially time-locked', async () => {
|
describe('initially time-locked', async () => {
|
||||||
before('deploy a walet', async () => {
|
before('deploy a wallet', async () => {
|
||||||
const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
|
const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
|
||||||
owners,
|
owners,
|
||||||
SIGNATURES_REQUIRED,
|
SIGNATURES_REQUIRED,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { ZeroEx } from '0x.js';
|
import { ZeroEx } from '0x.js';
|
||||||
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
|
||||||
import { BigNumber } from '@0xproject/utils';
|
import { BigNumber, NULL_BYTES } from '@0xproject/utils';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import ethUtil = require('ethereumjs-util');
|
import ethUtil = require('ethereumjs-util');
|
||||||
@@ -66,8 +66,8 @@ describe('TokenRegistry', () => {
|
|||||||
name: '',
|
name: '',
|
||||||
symbol: '',
|
symbol: '',
|
||||||
decimals: 0,
|
decimals: 0,
|
||||||
ipfsHash: constants.NULL_BYTES,
|
ipfsHash: NULL_BYTES,
|
||||||
swarmHash: constants.NULL_BYTES,
|
swarmHash: NULL_BYTES,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('addToken', () => {
|
describe('addToken', () => {
|
||||||
|
@@ -8,7 +8,7 @@ import { web3 } from './web3_wrapper';
|
|||||||
|
|
||||||
const deployerOpts = {
|
const deployerOpts = {
|
||||||
provider: web3.currentProvider,
|
provider: web3.currentProvider,
|
||||||
artifactsDir: path.resolve('src', 'artifacts'),
|
artifactsDir: path.resolve('lib', 'src', 'artifacts'),
|
||||||
networkId: constants.TESTRPC_NETWORK_ID,
|
networkId: constants.TESTRPC_NETWORK_ID,
|
||||||
defaults: {
|
defaults: {
|
||||||
gas: devConstants.GAS_ESTIMATE,
|
gas: devConstants.GAS_ESTIMATE,
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import { web3Factory } from '@0xproject/dev-utils';
|
import { web3Factory } from '@0xproject/dev-utils';
|
||||||
|
import { Provider } from '@0xproject/types';
|
||||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||||
|
|
||||||
const web3ProviderConfig = { shouldUseInProcessGanache: true };
|
const providerConfigs = { shouldUseInProcessGanache: true };
|
||||||
export const web3 = web3Factory.create(web3ProviderConfig);
|
export const web3 = web3Factory.create(providerConfigs);
|
||||||
export const provider = web3.currentProvider;
|
export const provider = web3.currentProvider;
|
||||||
export const web3Wrapper = new Web3Wrapper(provider);
|
export const web3Wrapper = new Web3Wrapper(provider);
|
||||||
|
@@ -4,7 +4,6 @@ const DUMMY_TOKEN_DECIMALS = 18;
|
|||||||
const DUMMY_TOKEN_TOTAL_SUPPLY = 0;
|
const DUMMY_TOKEN_TOTAL_SUPPLY = 0;
|
||||||
|
|
||||||
export const constants = {
|
export const constants = {
|
||||||
NULL_BYTES: '0x',
|
|
||||||
INVALID_OPCODE: 'invalid opcode',
|
INVALID_OPCODE: 'invalid opcode',
|
||||||
REVERT: 'revert',
|
REVERT: 'revert',
|
||||||
TESTRPC_NETWORK_ID: 50,
|
TESTRPC_NETWORK_ID: 50,
|
||||||
|
@@ -4,7 +4,7 @@ import ethUtil = require('ethereumjs-util');
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
export const crypto = {
|
export const crypto = {
|
||||||
/*
|
/**
|
||||||
* We convert types from JS to Solidity as follows:
|
* We convert types from JS to Solidity as follows:
|
||||||
* BigNumber -> uint256
|
* BigNumber -> uint256
|
||||||
* number -> uint8
|
* number -> uint8
|
||||||
|
@@ -1,4 +1,24 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "0.4.2",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add support for solidity 0.4.23",
|
||||||
|
"pr": 545
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1525428773
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "0.4.1",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add support for solidity 0.4.22",
|
||||||
|
"pr": 531
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": 1524044013
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
|
|||||||
|
|
||||||
CHANGELOG
|
CHANGELOG
|
||||||
|
|
||||||
|
## v0.4.2 - _May 4, 2018_
|
||||||
|
|
||||||
|
* Add support for solidity 0.4.23 (#545)
|
||||||
|
|
||||||
|
## v0.4.1 - _April 18, 2018_
|
||||||
|
|
||||||
|
* Add support for solidity 0.4.22 (#531)
|
||||||
|
|
||||||
## v0.4.0 - _April 11, 2018_
|
## v0.4.0 - _April 11, 2018_
|
||||||
|
|
||||||
* Changed the config key `web3Provider` to `provider` to be consistent with other tools (#501)
|
* Changed the config key `web3Provider` to `provider` to be consistent with other tools (#501)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@0xproject/deployer",
|
"name": "@0xproject/deployer",
|
||||||
"version": "0.3.5",
|
"version": "0.4.1",
|
||||||
"description": "Smart contract deployer of 0x protocol",
|
"description": "Smart contract deployer of 0x protocol",
|
||||||
"main": "lib/src/index.js",
|
"main": "lib/src/index.js",
|
||||||
"types": "lib/src/index.d.ts",
|
"types": "lib/src/index.d.ts",
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
"build:watch": "tsc -w",
|
"build:watch": "tsc -w",
|
||||||
"build": "yarn clean && copyfiles 'test/fixtures/contracts/**/*' ./lib && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
"build": "yarn clean && copyfiles 'test/fixtures/contracts/**/*' ./lib && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
||||||
"test": "run-s build run_mocha",
|
"test": "run-s build run_mocha",
|
||||||
"run_mocha": "mocha lib/test/*_test.js",
|
"run_mocha": "mocha lib/test/*_test.js --bail --exit",
|
||||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||||
"compile": "npm run build; node lib/src/cli.js compile",
|
"compile": "npm run build; node lib/src/cli.js compile",
|
||||||
@@ -47,12 +47,11 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/deployer/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/packages/deployer/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@0xproject/dev-utils": "^0.2.1",
|
"@0xproject/dev-utils": "^0.3.6",
|
||||||
"@0xproject/monorepo-scripts": "^0.1.16",
|
"@0xproject/monorepo-scripts": "^0.1.18",
|
||||||
"@0xproject/tslint-config": "^0.4.14",
|
"@0xproject/tslint-config": "^0.4.16",
|
||||||
"@types/require-from-string": "^1.2.0",
|
"@types/require-from-string": "^1.2.0",
|
||||||
"@types/semver": "^5.5.0",
|
"@types/semver": "^5.5.0",
|
||||||
"@types/yargs": "^11.0.0",
|
|
||||||
"chai": "^4.0.1",
|
"chai": "^4.0.1",
|
||||||
"chai-as-promised": "^7.1.0",
|
"chai-as-promised": "^7.1.0",
|
||||||
"copyfiles": "^1.2.0",
|
"copyfiles": "^1.2.0",
|
||||||
@@ -65,20 +64,24 @@
|
|||||||
"typedoc": "0xProject/typedoc",
|
"typedoc": "0xProject/typedoc",
|
||||||
"types-bn": "^0.0.1",
|
"types-bn": "^0.0.1",
|
||||||
"typescript": "2.7.1",
|
"typescript": "2.7.1",
|
||||||
"web3-typescript-typings": "^0.10.2"
|
"web3-typescript-typings": "^0.10.2",
|
||||||
|
"zeppelin-solidity": "1.8.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0xproject/json-schemas": "^0.7.19",
|
"@0xproject/json-schemas": "^0.7.21",
|
||||||
"@0xproject/types": "^0.5.0",
|
"@0xproject/sol-resolver": "^0.0.2",
|
||||||
"@0xproject/typescript-typings": "^0.0.3",
|
"@0xproject/types": "^0.6.1",
|
||||||
"@0xproject/utils": "^0.5.0",
|
"@0xproject/typescript-typings": "^0.2.0",
|
||||||
"@0xproject/web3-wrapper": "^0.5.0",
|
"@0xproject/utils": "^0.5.2",
|
||||||
|
"@0xproject/web3-wrapper": "^0.6.1",
|
||||||
|
"@types/yargs": "^11.0.0",
|
||||||
|
"chalk": "^2.3.0",
|
||||||
"ethereumjs-util": "^5.1.1",
|
"ethereumjs-util": "^5.1.1",
|
||||||
"isomorphic-fetch": "^2.2.1",
|
"isomorphic-fetch": "^2.2.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"require-from-string": "^2.0.1",
|
"require-from-string": "^2.0.1",
|
||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"solc": "^0.4.18",
|
"solc": "^0.4.23",
|
||||||
"web3": "^0.20.0",
|
"web3": "^0.20.0",
|
||||||
"web3-eth-abi": "^1.0.0-beta.24",
|
"web3-eth-abi": "^1.0.0-beta.24",
|
||||||
"yargs": "^10.0.3"
|
"yargs": "^10.0.3"
|
||||||
|
@@ -11,7 +11,7 @@ import * as yargs from 'yargs';
|
|||||||
import { commands } from './commands';
|
import { commands } from './commands';
|
||||||
import { constants } from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import { consoleReporter } from './utils/error_reporter';
|
import { consoleReporter } from './utils/error_reporter';
|
||||||
import { CliOptions, CompilerOptions, ContractDirectory, DeployerOptions } from './utils/types';
|
import { CliOptions, CompilerOptions, DeployerOptions } from './utils/types';
|
||||||
|
|
||||||
const DEFAULT_OPTIMIZER_ENABLED = false;
|
const DEFAULT_OPTIMIZER_ENABLED = false;
|
||||||
const DEFAULT_CONTRACTS_DIR = path.resolve('src/contracts');
|
const DEFAULT_CONTRACTS_DIR = path.resolve('src/contracts');
|
||||||
@@ -27,7 +27,7 @@ const DEFAULT_CONTRACTS_LIST = '*';
|
|||||||
*/
|
*/
|
||||||
async function onCompileCommandAsync(argv: CliOptions): Promise<void> {
|
async function onCompileCommandAsync(argv: CliOptions): Promise<void> {
|
||||||
const opts: CompilerOptions = {
|
const opts: CompilerOptions = {
|
||||||
contractDirs: getContractDirectoriesFromList(argv.contractDirs),
|
contractsDir: argv.contractsDir,
|
||||||
networkId: argv.networkId,
|
networkId: argv.networkId,
|
||||||
optimizerEnabled: argv.shouldOptimize,
|
optimizerEnabled: argv.shouldOptimize,
|
||||||
artifactsDir: argv.artifactsDir,
|
artifactsDir: argv.artifactsDir,
|
||||||
@@ -41,11 +41,11 @@ async function onCompileCommandAsync(argv: CliOptions): Promise<void> {
|
|||||||
*/
|
*/
|
||||||
async function onDeployCommandAsync(argv: CliOptions): Promise<void> {
|
async function onDeployCommandAsync(argv: CliOptions): Promise<void> {
|
||||||
const url = argv.jsonrpcUrl;
|
const url = argv.jsonrpcUrl;
|
||||||
const web3Provider = new Web3.providers.HttpProvider(url);
|
const provider = new Web3.providers.HttpProvider(url);
|
||||||
const web3Wrapper = new Web3Wrapper(web3Provider);
|
const web3Wrapper = new Web3Wrapper(provider);
|
||||||
const networkId = await web3Wrapper.getNetworkIdAsync();
|
const networkId = await web3Wrapper.getNetworkIdAsync();
|
||||||
const compilerOpts: CompilerOptions = {
|
const compilerOpts: CompilerOptions = {
|
||||||
contractDirs: getContractDirectoriesFromList(argv.contractDirs),
|
contractsDir: argv.contractsDir,
|
||||||
networkId,
|
networkId,
|
||||||
optimizerEnabled: argv.shouldOptimize,
|
optimizerEnabled: argv.shouldOptimize,
|
||||||
artifactsDir: argv.artifactsDir,
|
artifactsDir: argv.artifactsDir,
|
||||||
@@ -67,29 +67,6 @@ async function onDeployCommandAsync(argv: CliOptions): Promise<void> {
|
|||||||
const deployerArgs = deployerArgsString.split(',');
|
const deployerArgs = deployerArgsString.split(',');
|
||||||
await commands.deployAsync(argv.contract as string, deployerArgs, deployerOpts);
|
await commands.deployAsync(argv.contract as string, deployerArgs, deployerOpts);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Creates a set of contracts to compile.
|
|
||||||
* @param contractDirectoriesList Comma separated list of contract directories
|
|
||||||
* @return Set of contract directories
|
|
||||||
*/
|
|
||||||
function getContractDirectoriesFromList(contractDirectoriesList: string): Set<ContractDirectory> {
|
|
||||||
const directories = new Set();
|
|
||||||
const possiblyNamespacedDirectories = contractDirectoriesList.split(',');
|
|
||||||
_.forEach(possiblyNamespacedDirectories, namespacedDirectory => {
|
|
||||||
const directoryComponents = namespacedDirectory.split(':');
|
|
||||||
if (directoryComponents.length === 1) {
|
|
||||||
const directory = { namespace: '', path: directoryComponents[0] };
|
|
||||||
directories.add(directory);
|
|
||||||
} else if (directoryComponents.length === 2) {
|
|
||||||
const directory = { namespace: directoryComponents[0], path: directoryComponents[1] };
|
|
||||||
directories.add(directory);
|
|
||||||
} else {
|
|
||||||
throw new Error(`Unable to parse contracts directory: '${namespacedDirectory}'`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return directories;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Creates a set of contracts to compile.
|
* Creates a set of contracts to compile.
|
||||||
* @param contracts Comma separated list of contracts to compile
|
* @param contracts Comma separated list of contracts to compile
|
||||||
@@ -126,11 +103,10 @@ function deployCommandBuilder(yargsInstance: any) {
|
|||||||
(() => {
|
(() => {
|
||||||
const identityCommandBuilder = _.identity;
|
const identityCommandBuilder = _.identity;
|
||||||
return yargs
|
return yargs
|
||||||
.option('contract-dirs', {
|
.option('contracts-dir', {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: DEFAULT_CONTRACTS_DIR,
|
default: DEFAULT_CONTRACTS_DIR,
|
||||||
description:
|
description: 'path of contracts directory to compile',
|
||||||
"comma separated list of contract directories.\nTo avoid filename clashes, directories should be prefixed with a namespace as follows: 'namespace:/path/to/dir'.",
|
|
||||||
})
|
})
|
||||||
.option('network-id', {
|
.option('network-id', {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
|
@@ -1,5 +1,17 @@
|
|||||||
import { AbiType, ContractAbi, MethodAbi } from '@0xproject/types';
|
import {
|
||||||
|
ContractSource,
|
||||||
|
ContractSources,
|
||||||
|
EnumerableResolver,
|
||||||
|
FallthroughResolver,
|
||||||
|
FSResolver,
|
||||||
|
NameResolver,
|
||||||
|
NPMResolver,
|
||||||
|
Resolver,
|
||||||
|
URLResolver,
|
||||||
|
} from '@0xproject/sol-resolver';
|
||||||
|
import { ContractAbi } from '@0xproject/types';
|
||||||
import { logUtils, promisify } from '@0xproject/utils';
|
import { logUtils, promisify } from '@0xproject/utils';
|
||||||
|
import chalk from 'chalk';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import 'isomorphic-fetch';
|
import 'isomorphic-fetch';
|
||||||
@@ -11,10 +23,7 @@ import solc = require('solc');
|
|||||||
|
|
||||||
import { binPaths } from './solc/bin_paths';
|
import { binPaths } from './solc/bin_paths';
|
||||||
import {
|
import {
|
||||||
constructContractId,
|
|
||||||
constructUniqueSourceFileId,
|
|
||||||
createDirIfDoesNotExistAsync,
|
createDirIfDoesNotExistAsync,
|
||||||
findImportIfExist,
|
|
||||||
getContractArtifactIfExistsAsync,
|
getContractArtifactIfExistsAsync,
|
||||||
getNormalizedErrMsg,
|
getNormalizedErrMsg,
|
||||||
parseDependencies,
|
parseDependencies,
|
||||||
@@ -25,14 +34,10 @@ import { fsWrapper } from './utils/fs_wrapper';
|
|||||||
import {
|
import {
|
||||||
CompilerOptions,
|
CompilerOptions,
|
||||||
ContractArtifact,
|
ContractArtifact,
|
||||||
ContractDirectory,
|
|
||||||
ContractIdToSourceFileId,
|
|
||||||
ContractNetworkData,
|
ContractNetworkData,
|
||||||
ContractNetworks,
|
ContractNetworks,
|
||||||
ContractSourceDataByFileId,
|
ContractSourceData,
|
||||||
ContractSources,
|
|
||||||
ContractSpecificSourceData,
|
ContractSpecificSourceData,
|
||||||
FunctionNameToSeenCount,
|
|
||||||
} from './utils/types';
|
} from './utils/types';
|
||||||
import { utils } from './utils/utils';
|
import { utils } from './utils/utils';
|
||||||
|
|
||||||
@@ -44,71 +49,32 @@ const SOLC_BIN_DIR = path.join(__dirname, '..', '..', 'solc_bin');
|
|||||||
* to artifact files.
|
* to artifact files.
|
||||||
*/
|
*/
|
||||||
export class Compiler {
|
export class Compiler {
|
||||||
private _contractDirs: Set<ContractDirectory>;
|
private _resolver: Resolver;
|
||||||
|
private _nameResolver: NameResolver;
|
||||||
|
private _contractsDir: string;
|
||||||
private _networkId: number;
|
private _networkId: number;
|
||||||
private _optimizerEnabled: boolean;
|
private _optimizerEnabled: boolean;
|
||||||
private _artifactsDir: string;
|
private _artifactsDir: string;
|
||||||
// This get's set in the beggining of `compileAsync` function. It's not called from a constructor, but it's the only public method of that class and could as well be.
|
|
||||||
private _contractSources!: ContractSources;
|
|
||||||
private _specifiedContracts: Set<string> = new Set();
|
private _specifiedContracts: Set<string> = new Set();
|
||||||
private _contractSourceDataByFileId: ContractSourceDataByFileId = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively retrieves Solidity source code from directory.
|
|
||||||
* @param dirPath Directory to search.
|
|
||||||
* @param contractBaseDir Base contracts directory of search tree.
|
|
||||||
* @return Mapping of sourceFilePath to the contract source.
|
|
||||||
*/
|
|
||||||
private static async _getContractSourcesAsync(dirPath: string, contractBaseDir: string): Promise<ContractSources> {
|
|
||||||
let dirContents: string[] = [];
|
|
||||||
try {
|
|
||||||
dirContents = await fsWrapper.readdirAsync(dirPath);
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(`No directory found at ${dirPath}`);
|
|
||||||
}
|
|
||||||
let sources: ContractSources = {};
|
|
||||||
for (const fileName of dirContents) {
|
|
||||||
const contentPath = `${dirPath}/${fileName}`;
|
|
||||||
if (path.extname(fileName) === constants.SOLIDITY_FILE_EXTENSION) {
|
|
||||||
try {
|
|
||||||
const opts = {
|
|
||||||
encoding: 'utf8',
|
|
||||||
};
|
|
||||||
const source = await fsWrapper.readFileAsync(contentPath, opts);
|
|
||||||
if (!_.startsWith(contentPath, contractBaseDir)) {
|
|
||||||
throw new Error(`Expected content path '${contentPath}' to begin with '${contractBaseDir}'`);
|
|
||||||
}
|
|
||||||
const sourceFilePath = contentPath.slice(contractBaseDir.length);
|
|
||||||
sources[sourceFilePath] = source;
|
|
||||||
logUtils.log(`Reading ${sourceFilePath} source...`);
|
|
||||||
} catch (err) {
|
|
||||||
logUtils.log(`Could not find file at ${contentPath}`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
const nestedSources = await Compiler._getContractSourcesAsync(contentPath, contractBaseDir);
|
|
||||||
sources = {
|
|
||||||
...sources,
|
|
||||||
...nestedSources,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
logUtils.log(`${contentPath} is not a directory or ${constants.SOLIDITY_FILE_EXTENSION} file`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sources;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new instance of the Compiler class.
|
* Instantiates a new instance of the Compiler class.
|
||||||
* @param opts Options specifying directories, network, and optimization settings.
|
* @param opts Options specifying directories, network, and optimization settings.
|
||||||
* @return An instance of the Compiler class.
|
* @return An instance of the Compiler class.
|
||||||
*/
|
*/
|
||||||
constructor(opts: CompilerOptions) {
|
constructor(opts: CompilerOptions) {
|
||||||
this._contractDirs = opts.contractDirs;
|
this._contractsDir = opts.contractsDir;
|
||||||
this._networkId = opts.networkId;
|
this._networkId = opts.networkId;
|
||||||
this._optimizerEnabled = opts.optimizerEnabled;
|
this._optimizerEnabled = opts.optimizerEnabled;
|
||||||
this._artifactsDir = opts.artifactsDir;
|
this._artifactsDir = opts.artifactsDir;
|
||||||
this._specifiedContracts = opts.specifiedContracts;
|
this._specifiedContracts = opts.specifiedContracts;
|
||||||
|
this._nameResolver = new NameResolver(path.resolve(this._contractsDir));
|
||||||
|
const resolver = new FallthroughResolver();
|
||||||
|
resolver.appendResolver(new URLResolver());
|
||||||
|
const packagePath = path.resolve('');
|
||||||
|
resolver.appendResolver(new NPMResolver(packagePath));
|
||||||
|
resolver.appendResolver(new FSResolver());
|
||||||
|
resolver.appendResolver(this._nameResolver);
|
||||||
|
this._resolver = resolver;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Compiles selected Solidity files found in `contractsDir` and writes JSON artifacts to `artifactsDir`.
|
* Compiles selected Solidity files found in `contractsDir` and writes JSON artifacts to `artifactsDir`.
|
||||||
@@ -116,51 +82,27 @@ export class Compiler {
|
|||||||
public async compileAsync(): Promise<void> {
|
public async compileAsync(): Promise<void> {
|
||||||
await createDirIfDoesNotExistAsync(this._artifactsDir);
|
await createDirIfDoesNotExistAsync(this._artifactsDir);
|
||||||
await createDirIfDoesNotExistAsync(SOLC_BIN_DIR);
|
await createDirIfDoesNotExistAsync(SOLC_BIN_DIR);
|
||||||
this._contractSources = {};
|
let contractNamesToCompile: string[] = [];
|
||||||
const contractIdToSourceFileId: ContractIdToSourceFileId = {};
|
if (this._specifiedContracts.has(ALL_CONTRACTS_IDENTIFIER)) {
|
||||||
const contractDirs = Array.from(this._contractDirs.values());
|
const allContracts = this._nameResolver.getAll();
|
||||||
for (const contractDir of contractDirs) {
|
contractNamesToCompile = _.map(allContracts, contractSource =>
|
||||||
const sources = await Compiler._getContractSourcesAsync(contractDir.path, contractDir.path);
|
path.basename(contractSource.path, constants.SOLIDITY_FILE_EXTENSION),
|
||||||
_.forIn(sources, (source, sourceFilePath) => {
|
|
||||||
const sourceFileId = constructUniqueSourceFileId(contractDir.namespace, sourceFilePath);
|
|
||||||
// Record the file's source and data
|
|
||||||
if (!_.isUndefined(this._contractSources[sourceFileId])) {
|
|
||||||
throw new Error(`Found duplicate source files with ID '${sourceFileId}'`);
|
|
||||||
}
|
|
||||||
this._contractSources[sourceFileId] = source;
|
|
||||||
// Create a mapping between the contract id and its source file id
|
|
||||||
const contractId = constructContractId(contractDir.namespace, sourceFilePath);
|
|
||||||
if (!_.isUndefined(contractIdToSourceFileId[contractId])) {
|
|
||||||
throw new Error(`Found duplicate contract with ID '${contractId}'`);
|
|
||||||
}
|
|
||||||
contractIdToSourceFileId[contractId] = sourceFileId;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_.forIn(this._contractSources, this._setContractSpecificSourceData.bind(this));
|
|
||||||
const specifiedContractIds = this._specifiedContracts.has(ALL_CONTRACTS_IDENTIFIER)
|
|
||||||
? _.keys(contractIdToSourceFileId)
|
|
||||||
: Array.from(this._specifiedContracts.values());
|
|
||||||
await Promise.all(
|
|
||||||
_.map(specifiedContractIds, async contractId =>
|
|
||||||
this._compileContractAsync(contractIdToSourceFileId[contractId]),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
contractNamesToCompile = Array.from(this._specifiedContracts.values());
|
||||||
|
}
|
||||||
|
for (const contractNameToCompile of contractNamesToCompile) {
|
||||||
|
await this._compileContractAsync(contractNameToCompile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Compiles contract and saves artifact to artifactsDir.
|
* Compiles contract and saves artifact to artifactsDir.
|
||||||
* @param sourceFileId Unique ID of the source file.
|
* @param fileName Name of contract with '.sol' extension.
|
||||||
*/
|
*/
|
||||||
private async _compileContractAsync(sourceFileId: string): Promise<void> {
|
private async _compileContractAsync(contractName: string): Promise<void> {
|
||||||
if (_.isUndefined(this._contractSources)) {
|
const contractSource = this._resolver.resolve(contractName);
|
||||||
throw new Error('Contract sources not yet initialized');
|
const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, contractName);
|
||||||
}
|
const sourceTreeHashHex = `0x${this._getSourceTreeHash(contractSource.path).toString('hex')}`;
|
||||||
if (_.isUndefined(this._contractSourceDataByFileId[sourceFileId])) {
|
|
||||||
throw new Error(`Contract source for ${sourceFileId} not yet initialized`);
|
|
||||||
}
|
|
||||||
const contractSpecificSourceData = this._contractSourceDataByFileId[sourceFileId];
|
|
||||||
const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, sourceFileId);
|
|
||||||
const sourceHash = `0x${contractSpecificSourceData.sourceHash.toString('hex')}`;
|
|
||||||
const sourceTreeHash = `0x${contractSpecificSourceData.sourceTreeHash.toString('hex')}`;
|
|
||||||
|
|
||||||
let shouldCompile = false;
|
let shouldCompile = false;
|
||||||
if (_.isUndefined(currentArtifactIfExists)) {
|
if (_.isUndefined(currentArtifactIfExists)) {
|
||||||
@@ -169,16 +111,14 @@ export class Compiler {
|
|||||||
const currentArtifact = currentArtifactIfExists as ContractArtifact;
|
const currentArtifact = currentArtifactIfExists as ContractArtifact;
|
||||||
shouldCompile =
|
shouldCompile =
|
||||||
currentArtifact.networks[this._networkId].optimizer_enabled !== this._optimizerEnabled ||
|
currentArtifact.networks[this._networkId].optimizer_enabled !== this._optimizerEnabled ||
|
||||||
currentArtifact.networks[this._networkId].source_tree_hash !== sourceTreeHash;
|
currentArtifact.networks[this._networkId].source_tree_hash !== sourceTreeHashHex;
|
||||||
}
|
}
|
||||||
if (!shouldCompile) {
|
if (!shouldCompile) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const solcVersionRange = parseSolidityVersionRange(contractSource.source);
|
||||||
const availableCompilerVersions = _.keys(binPaths);
|
const availableCompilerVersions = _.keys(binPaths);
|
||||||
const solcVersion = semver.maxSatisfying(
|
const solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange);
|
||||||
availableCompilerVersions,
|
|
||||||
contractSpecificSourceData.solcVersionRange,
|
|
||||||
);
|
|
||||||
const fullSolcVersion = binPaths[solcVersion];
|
const fullSolcVersion = binPaths[solcVersion];
|
||||||
const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion);
|
const compilerBinFilename = path.join(SOLC_BIN_DIR, fullSolcVersion);
|
||||||
let solcjs: string;
|
let solcjs: string;
|
||||||
@@ -197,57 +137,77 @@ export class Compiler {
|
|||||||
}
|
}
|
||||||
const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename));
|
const solcInstance = solc.setupMethods(requireFromString(solcjs, compilerBinFilename));
|
||||||
|
|
||||||
logUtils.log(`Compiling ${sourceFileId} with Solidity v${solcVersion}...`);
|
logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`);
|
||||||
const source = this._contractSources[sourceFileId];
|
const source = contractSource.source;
|
||||||
const input = {
|
const absoluteFilePath = contractSource.path;
|
||||||
[sourceFileId]: source,
|
const standardInput: solc.StandardInput = {
|
||||||
|
language: 'Solidity',
|
||||||
|
sources: {
|
||||||
|
[absoluteFilePath]: {
|
||||||
|
urls: [`file://${absoluteFilePath}`],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
optimizer: {
|
||||||
|
enabled: this._optimizerEnabled,
|
||||||
|
},
|
||||||
|
outputSelection: {
|
||||||
|
'*': {
|
||||||
|
'*': [
|
||||||
|
'abi',
|
||||||
|
'evm.bytecode.object',
|
||||||
|
'evm.bytecode.sourceMap',
|
||||||
|
'evm.deployedBytecode.object',
|
||||||
|
'evm.deployedBytecode.sourceMap',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
const sourcesToCompile = {
|
const compiled: solc.StandardOutput = JSON.parse(
|
||||||
sources: input,
|
solcInstance.compileStandardWrapper(JSON.stringify(standardInput), importPath => {
|
||||||
};
|
const sourceCodeIfExists = this._resolver.resolve(importPath);
|
||||||
|
return { contents: sourceCodeIfExists.source };
|
||||||
const compiled = solcInstance.compile(sourcesToCompile, Number(this._optimizerEnabled), importPath =>
|
}),
|
||||||
findImportIfExist(this._contractSources, sourceFileId, importPath),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!_.isUndefined(compiled.errors)) {
|
if (!_.isUndefined(compiled.errors)) {
|
||||||
const SOLIDITY_WARNING_PREFIX = 'Warning';
|
const SOLIDITY_WARNING = 'warning';
|
||||||
const isError = (errorOrWarning: string) => !errorOrWarning.includes(SOLIDITY_WARNING_PREFIX);
|
const errors = _.filter(compiled.errors, entry => entry.severity !== SOLIDITY_WARNING);
|
||||||
const isWarning = (errorOrWarning: string) => errorOrWarning.includes(SOLIDITY_WARNING_PREFIX);
|
const warnings = _.filter(compiled.errors, entry => entry.severity === SOLIDITY_WARNING);
|
||||||
const errors = _.filter(compiled.errors, isError);
|
|
||||||
const warnings = _.filter(compiled.errors, isWarning);
|
|
||||||
if (!_.isEmpty(errors)) {
|
if (!_.isEmpty(errors)) {
|
||||||
errors.forEach(errMsg => {
|
errors.forEach(error => {
|
||||||
const normalizedErrMsg = getNormalizedErrMsg(errMsg);
|
const normalizedErrMsg = getNormalizedErrMsg(error.formattedMessage || error.message);
|
||||||
logUtils.log(normalizedErrMsg);
|
logUtils.log(chalk.red(normalizedErrMsg));
|
||||||
});
|
});
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
warnings.forEach(errMsg => {
|
warnings.forEach(warning => {
|
||||||
const normalizedErrMsg = getNormalizedErrMsg(errMsg);
|
const normalizedWarningMsg = getNormalizedErrMsg(warning.formattedMessage || warning.message);
|
||||||
logUtils.log(normalizedErrMsg);
|
logUtils.log(chalk.yellow(normalizedWarningMsg));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const contractName = path.basename(sourceFileId, constants.SOLIDITY_FILE_EXTENSION);
|
const compiledData = compiled.contracts[absoluteFilePath][contractName];
|
||||||
const contractIdentifier = `${sourceFileId}:${contractName}`;
|
if (_.isUndefined(compiledData)) {
|
||||||
if (_.isUndefined(compiled.contracts[contractIdentifier])) {
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Contract ${contractName} not found in ${sourceFileId}. Please make sure your contract has the same name as it's file name`,
|
`Contract ${contractName} not found in ${absoluteFilePath}. Please make sure your contract has the same name as it's file name`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const abi: ContractAbi = JSON.parse(compiled.contracts[contractIdentifier].interface);
|
const abi: ContractAbi = compiledData.abi;
|
||||||
const bytecode = `0x${compiled.contracts[contractIdentifier].bytecode}`;
|
const bytecode = `0x${compiledData.evm.bytecode.object}`;
|
||||||
const runtimeBytecode = `0x${compiled.contracts[contractIdentifier].runtimeBytecode}`;
|
const runtimeBytecode = `0x${compiledData.evm.deployedBytecode.object}`;
|
||||||
const sourceMap = compiled.contracts[contractIdentifier].srcmap;
|
const sourceMap = compiledData.evm.bytecode.sourceMap;
|
||||||
const sourceMapRuntime = compiled.contracts[contractIdentifier].srcmapRuntime;
|
const sourceMapRuntime = compiledData.evm.deployedBytecode.sourceMap;
|
||||||
const sources = _.keys(compiled.sources);
|
const unresolvedSourcePaths = _.keys(compiled.sources);
|
||||||
|
const sources = _.map(
|
||||||
|
unresolvedSourcePaths,
|
||||||
|
unresolvedSourcePath => this._resolver.resolve(unresolvedSourcePath).path,
|
||||||
|
);
|
||||||
const updated_at = Date.now();
|
const updated_at = Date.now();
|
||||||
|
|
||||||
const contractNetworkData: ContractNetworkData = {
|
const contractNetworkData: ContractNetworkData = {
|
||||||
solc_version: solcVersion,
|
solc_version: solcVersion,
|
||||||
keccak256: sourceHash,
|
source_tree_hash: sourceTreeHashHex,
|
||||||
source_tree_hash: sourceTreeHash,
|
|
||||||
optimizer_enabled: this._optimizerEnabled,
|
optimizer_enabled: this._optimizerEnabled,
|
||||||
abi,
|
abi,
|
||||||
bytecode,
|
bytecode,
|
||||||
@@ -280,44 +240,22 @@ export class Compiler {
|
|||||||
const artifactString = utils.stringifyWithFormatting(newArtifact);
|
const artifactString = utils.stringifyWithFormatting(newArtifact);
|
||||||
const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`;
|
const currentArtifactPath = `${this._artifactsDir}/${contractName}.json`;
|
||||||
await fsWrapper.writeFileAsync(currentArtifactPath, artifactString);
|
await fsWrapper.writeFileAsync(currentArtifactPath, artifactString);
|
||||||
logUtils.log(`${sourceFileId} artifact saved!`);
|
logUtils.log(`${contractName} artifact saved!`);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Gets contract dependendencies and keccak256 hash from source.
|
|
||||||
* @param source Source code of contract.
|
|
||||||
* @param fileId FileId of the contract source file.
|
|
||||||
* @return Object with contract dependencies and keccak256 hash of source.
|
|
||||||
*/
|
|
||||||
private _setContractSpecificSourceData(source: string, fileId: string): void {
|
|
||||||
if (!_.isUndefined(this._contractSourceDataByFileId[fileId])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const sourceHash = ethUtil.sha3(source);
|
|
||||||
const solcVersionRange = parseSolidityVersionRange(source);
|
|
||||||
const dependencies = parseDependencies(source, fileId);
|
|
||||||
const sourceTreeHash = this._getSourceTreeHash(fileId, sourceHash, dependencies);
|
|
||||||
this._contractSourceDataByFileId[fileId] = {
|
|
||||||
dependencies,
|
|
||||||
solcVersionRange,
|
|
||||||
sourceHash,
|
|
||||||
sourceTreeHash,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the source tree hash for a file and its dependencies.
|
* Gets the source tree hash for a file and its dependencies.
|
||||||
* @param fileName Name of contract file.
|
* @param fileName Name of contract file.
|
||||||
*/
|
*/
|
||||||
private _getSourceTreeHash(fileName: string, sourceHash: Buffer, dependencies: string[]): Buffer {
|
private _getSourceTreeHash(importPath: string): Buffer {
|
||||||
|
const contractSource = this._resolver.resolve(importPath);
|
||||||
|
const dependencies = parseDependencies(contractSource);
|
||||||
|
const sourceHash = ethUtil.sha3(contractSource.source);
|
||||||
if (dependencies.length === 0) {
|
if (dependencies.length === 0) {
|
||||||
return sourceHash;
|
return sourceHash;
|
||||||
} else {
|
} else {
|
||||||
const dependencySourceTreeHashes = _.map(dependencies, dependency => {
|
const dependencySourceTreeHashes = _.map(dependencies, (dependency: string) =>
|
||||||
const source = this._contractSources[dependency];
|
this._getSourceTreeHash(dependency),
|
||||||
this._setContractSpecificSourceData(source, dependency);
|
);
|
||||||
const sourceData = this._contractSourceDataByFileId[dependency];
|
|
||||||
return this._getSourceTreeHash(dependency, sourceData.sourceHash, sourceData.dependencies);
|
|
||||||
});
|
|
||||||
const sourceTreeHashesBuffer = Buffer.concat([sourceHash, ...dependencySourceTreeHashes]);
|
const sourceTreeHashesBuffer = Buffer.concat([sourceHash, ...dependencySourceTreeHashes]);
|
||||||
const sourceTreeHash = ethUtil.sha3(sourceTreeHashesBuffer);
|
const sourceTreeHash = ethUtil.sha3(sourceTreeHashesBuffer);
|
||||||
return sourceTreeHash;
|
return sourceTreeHash;
|
||||||
|
@@ -38,17 +38,17 @@ export class Deployer {
|
|||||||
this._artifactsDir = opts.artifactsDir;
|
this._artifactsDir = opts.artifactsDir;
|
||||||
this._networkId = opts.networkId;
|
this._networkId = opts.networkId;
|
||||||
this._defaults = opts.defaults;
|
this._defaults = opts.defaults;
|
||||||
let web3Provider: Provider;
|
let provider: Provider;
|
||||||
if (_.isUndefined((opts as ProviderDeployerOptions).provider)) {
|
if (_.isUndefined((opts as ProviderDeployerOptions).provider)) {
|
||||||
const jsonrpcUrl = (opts as UrlDeployerOptions).jsonrpcUrl;
|
const jsonrpcUrl = (opts as UrlDeployerOptions).jsonrpcUrl;
|
||||||
if (_.isUndefined(jsonrpcUrl)) {
|
if (_.isUndefined(jsonrpcUrl)) {
|
||||||
throw new Error(`Deployer options don't contain web3Provider nor jsonrpcUrl. Please pass one of them`);
|
throw new Error(`Deployer options don't contain provider nor jsonrpcUrl. Please pass one of them`);
|
||||||
}
|
}
|
||||||
web3Provider = new Web3.providers.HttpProvider(jsonrpcUrl);
|
provider = new Web3.providers.HttpProvider(jsonrpcUrl);
|
||||||
} else {
|
} else {
|
||||||
web3Provider = (opts as ProviderDeployerOptions).provider;
|
provider = (opts as ProviderDeployerOptions).provider;
|
||||||
}
|
}
|
||||||
this.web3Wrapper = new Web3Wrapper(web3Provider, this._defaults);
|
this.web3Wrapper = new Web3Wrapper(provider, this._defaults);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Loads a contract's corresponding artifacts and deploys it with the supplied constructor arguments.
|
* Loads a contract's corresponding artifacts and deploys it with the supplied constructor arguments.
|
||||||
@@ -170,7 +170,7 @@ export class Deployer {
|
|||||||
const contractArtifact: ContractArtifact = require(artifactPath);
|
const contractArtifact: ContractArtifact = require(artifactPath);
|
||||||
return contractArtifact;
|
return contractArtifact;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new Error(`Artifact not found for contract: ${contractName}`);
|
throw new Error(`Artifact not found for contract: ${contractName} at ${artifactPath}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@@ -15,4 +15,6 @@ export const binPaths: BinaryPaths = {
|
|||||||
'0.4.19': 'soljson-v0.4.19+commit.c4cbbb05.js',
|
'0.4.19': 'soljson-v0.4.19+commit.c4cbbb05.js',
|
||||||
'0.4.20': 'soljson-v0.4.20+commit.3155dd80.js',
|
'0.4.20': 'soljson-v0.4.20+commit.3155dd80.js',
|
||||||
'0.4.21': 'soljson-v0.4.21+commit.dfe3193c.js',
|
'0.4.21': 'soljson-v0.4.21+commit.dfe3193c.js',
|
||||||
|
'0.4.22': 'soljson-v0.4.22+commit.4cb486ee.js',
|
||||||
|
'0.4.23': 'soljson-v0.4.23+commit.124ca40d.js',
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { AbiType, ContractAbi, MethodAbi } from '@0xproject/types';
|
import { ContractSource, ContractSources } from '@0xproject/sol-resolver';
|
||||||
import { logUtils } from '@0xproject/utils';
|
import { logUtils } from '@0xproject/utils';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
@@ -6,60 +6,19 @@ import * as solc from 'solc';
|
|||||||
|
|
||||||
import { constants } from './constants';
|
import { constants } from './constants';
|
||||||
import { fsWrapper } from './fs_wrapper';
|
import { fsWrapper } from './fs_wrapper';
|
||||||
import { ContractArtifact, ContractSources, FunctionNameToSeenCount } from './types';
|
import { ContractArtifact } from './types';
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a system-wide unique identifier for a source file.
|
|
||||||
* @param directoryNamespace Namespace of the source file's root contract directory.
|
|
||||||
* @param sourceFilePath Path to a source file, relative to contractBaseDir.
|
|
||||||
* @return sourceFileId A system-wide unique identifier for the source file.
|
|
||||||
*/
|
|
||||||
export function constructUniqueSourceFileId(directoryNamespace: string, sourceFilePath: string): string {
|
|
||||||
const namespacePrefix = !_.isEmpty(directoryNamespace) ? `/${directoryNamespace}` : '';
|
|
||||||
const sourceFilePathNoLeadingSlash = sourceFilePath.replace(/^\/+/g, '');
|
|
||||||
const sourceFileId = `${namespacePrefix}/${sourceFilePathNoLeadingSlash}`;
|
|
||||||
return sourceFileId;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Constructs a system-wide unique identifier for a dependency file.
|
|
||||||
* @param dependencyFilePath Path from a sourceFile to a dependency.
|
|
||||||
* @param contractBaseDir Base contracts directory of search tree.
|
|
||||||
* @return sourceFileId A system-wide unique identifier for the source file.
|
|
||||||
*/
|
|
||||||
export function constructDependencyFileId(dependencyFilePath: string, sourceFilePath: string): string {
|
|
||||||
if (_.startsWith(dependencyFilePath, '/')) {
|
|
||||||
// Path of the form /namespace/path/to/dependency.sol
|
|
||||||
return dependencyFilePath;
|
|
||||||
} else {
|
|
||||||
// Dependency is relative to the source file: ./dependency.sol, ../../some/path/dependency.sol, etc.
|
|
||||||
// Join the two paths to construct a valid source file id: /namespace/path/to/dependency.sol
|
|
||||||
return path.join(path.dirname(sourceFilePath), dependencyFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Constructs a system-wide unique identifier for a contract.
|
|
||||||
* @param directoryNamespace Namespace of the source file's root contract directory.
|
|
||||||
* @param sourceFilePath Path to a source file, relative to contractBaseDir.
|
|
||||||
* @return sourceFileId A system-wide unique identifier for contract.
|
|
||||||
*/
|
|
||||||
export function constructContractId(directoryNamespace: string, sourceFilePath: string): string {
|
|
||||||
const namespacePrefix = !_.isEmpty(directoryNamespace) ? `${directoryNamespace}:` : '';
|
|
||||||
const sourceFileName = path.basename(sourceFilePath, constants.SOLIDITY_FILE_EXTENSION);
|
|
||||||
const contractId = `${namespacePrefix}${sourceFileName}`;
|
|
||||||
return contractId;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Gets contract data on network or returns if an artifact does not exist.
|
* Gets contract data on network or returns if an artifact does not exist.
|
||||||
* @param artifactsDir Path to the artifacts directory.
|
* @param artifactsDir Path to the artifacts directory.
|
||||||
* @param fileName Name of contract file.
|
* @param contractName Name of contract.
|
||||||
* @return Contract data on network or undefined.
|
* @return Contract data on network or undefined.
|
||||||
*/
|
*/
|
||||||
export async function getContractArtifactIfExistsAsync(
|
export async function getContractArtifactIfExistsAsync(
|
||||||
artifactsDir: string,
|
artifactsDir: string,
|
||||||
fileName: string,
|
contractName: string,
|
||||||
): Promise<ContractArtifact | void> {
|
): Promise<ContractArtifact | void> {
|
||||||
let contractArtifact;
|
let contractArtifact;
|
||||||
const contractName = path.basename(fileName, constants.SOLIDITY_FILE_EXTENSION);
|
|
||||||
const currentArtifactPath = `${artifactsDir}/${contractName}.json`;
|
const currentArtifactPath = `${artifactsDir}/${contractName}.json`;
|
||||||
try {
|
try {
|
||||||
const opts = {
|
const opts = {
|
||||||
@@ -69,7 +28,7 @@ export async function getContractArtifactIfExistsAsync(
|
|||||||
contractArtifact = JSON.parse(contractArtifactString);
|
contractArtifact = JSON.parse(contractArtifactString);
|
||||||
return contractArtifact;
|
return contractArtifact;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logUtils.log(`Artifact for ${fileName} does not exist`);
|
logUtils.log(`Artifact for ${contractName} does not exist`);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,11 +82,11 @@ export function getNormalizedErrMsg(errMsg: string): string {
|
|||||||
/**
|
/**
|
||||||
* Parses the contract source code and extracts the dendencies
|
* Parses the contract source code and extracts the dendencies
|
||||||
* @param source Contract source code
|
* @param source Contract source code
|
||||||
* @param sourceFilePath File path of the source code.
|
|
||||||
* @return List of dependendencies
|
* @return List of dependendencies
|
||||||
*/
|
*/
|
||||||
export function parseDependencies(source: string, sourceFileId: string): string[] {
|
export function parseDependencies(contractSource: ContractSource): string[] {
|
||||||
// TODO: Use a proper parser
|
// TODO: Use a proper parser
|
||||||
|
const source = contractSource.source;
|
||||||
const IMPORT_REGEX = /(import\s)/;
|
const IMPORT_REGEX = /(import\s)/;
|
||||||
const DEPENDENCY_PATH_REGEX = /"([^"]+)"/; // Source: https://github.com/BlockChainCompany/soljitsu/blob/master/lib/shared.js
|
const DEPENDENCY_PATH_REGEX = /"([^"]+)"/; // Source: https://github.com/BlockChainCompany/soljitsu/blob/master/lib/shared.js
|
||||||
const dependencies: string[] = [];
|
const dependencies: string[] = [];
|
||||||
@@ -136,35 +95,13 @@ export function parseDependencies(source: string, sourceFileId: string): string[
|
|||||||
if (!_.isNull(line.match(IMPORT_REGEX))) {
|
if (!_.isNull(line.match(IMPORT_REGEX))) {
|
||||||
const dependencyMatch = line.match(DEPENDENCY_PATH_REGEX);
|
const dependencyMatch = line.match(DEPENDENCY_PATH_REGEX);
|
||||||
if (!_.isNull(dependencyMatch)) {
|
if (!_.isNull(dependencyMatch)) {
|
||||||
const dependencyPath = dependencyMatch[1];
|
let dependencyPath = dependencyMatch[1];
|
||||||
const dependencyId = constructDependencyFileId(dependencyPath, sourceFileId);
|
if (dependencyPath.startsWith('.')) {
|
||||||
dependencies.push(dependencyId);
|
dependencyPath = path.join(path.dirname(contractSource.path), dependencyPath);
|
||||||
|
}
|
||||||
|
dependencies.push(dependencyPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to resolve dependencies with `solc.compile`.
|
|
||||||
* Throws error if contractSources not yet initialized.
|
|
||||||
* @param contractSources Source codes of contracts.
|
|
||||||
* @param sourceFileId ID of the source file.
|
|
||||||
* @param importPath Path of dependency source file.
|
|
||||||
* @return Import contents object containing source code of dependency.
|
|
||||||
*/
|
|
||||||
export function findImportIfExist(
|
|
||||||
contractSources: ContractSources,
|
|
||||||
sourceFileId: string,
|
|
||||||
importPath: string,
|
|
||||||
): solc.ImportContents {
|
|
||||||
const dependencyFileId = constructDependencyFileId(importPath, sourceFileId);
|
|
||||||
const source = contractSources[dependencyFileId];
|
|
||||||
if (_.isUndefined(source)) {
|
|
||||||
throw new Error(`Contract source not found for ${dependencyFileId}`);
|
|
||||||
}
|
|
||||||
const importContents: solc.ImportContents = {
|
|
||||||
contents: source,
|
|
||||||
};
|
|
||||||
return importContents;
|
|
||||||
}
|
|
||||||
|
@@ -18,15 +18,9 @@ export interface ContractNetworks {
|
|||||||
[key: number]: ContractNetworkData;
|
[key: number]: ContractNetworkData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContractDirectory {
|
|
||||||
path: string;
|
|
||||||
namespace: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ContractNetworkData {
|
export interface ContractNetworkData {
|
||||||
solc_version: string;
|
solc_version: string;
|
||||||
optimizer_enabled: boolean;
|
optimizer_enabled: boolean;
|
||||||
keccak256: string;
|
|
||||||
source_tree_hash: string;
|
source_tree_hash: string;
|
||||||
abi: ContractAbi;
|
abi: ContractAbi;
|
||||||
bytecode: string;
|
bytecode: string;
|
||||||
@@ -45,7 +39,7 @@ export interface SolcErrors {
|
|||||||
|
|
||||||
export interface CliOptions extends yargs.Arguments {
|
export interface CliOptions extends yargs.Arguments {
|
||||||
artifactsDir: string;
|
artifactsDir: string;
|
||||||
contractDirs: string;
|
contractsDir: string;
|
||||||
jsonrpcUrl: string;
|
jsonrpcUrl: string;
|
||||||
networkId: number;
|
networkId: number;
|
||||||
shouldOptimize: boolean;
|
shouldOptimize: boolean;
|
||||||
@@ -56,7 +50,7 @@ export interface CliOptions extends yargs.Arguments {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CompilerOptions {
|
export interface CompilerOptions {
|
||||||
contractDirs: Set<ContractDirectory>;
|
contractsDir: string;
|
||||||
networkId: number;
|
networkId: number;
|
||||||
optimizerEnabled: boolean;
|
optimizerEnabled: boolean;
|
||||||
artifactsDir: string;
|
artifactsDir: string;
|
||||||
@@ -79,20 +73,11 @@ export interface UrlDeployerOptions extends BaseDeployerOptions {
|
|||||||
|
|
||||||
export type DeployerOptions = UrlDeployerOptions | ProviderDeployerOptions;
|
export type DeployerOptions = UrlDeployerOptions | ProviderDeployerOptions;
|
||||||
|
|
||||||
export interface ContractSources {
|
export interface ContractSourceData {
|
||||||
[key: string]: string;
|
[contractName: string]: ContractSpecificSourceData;
|
||||||
}
|
|
||||||
|
|
||||||
export interface ContractIdToSourceFileId {
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ContractSourceDataByFileId {
|
|
||||||
[key: string]: ContractSpecificSourceData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContractSpecificSourceData {
|
export interface ContractSpecificSourceData {
|
||||||
dependencies: string[];
|
|
||||||
solcVersionRange: string;
|
solcVersionRange: string;
|
||||||
sourceHash: Buffer;
|
sourceHash: Buffer;
|
||||||
sourceTreeHash: Buffer;
|
sourceTreeHash: Buffer;
|
||||||
@@ -107,8 +92,4 @@ export interface Token {
|
|||||||
swarmHash: string;
|
swarmHash: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FunctionNameToSeenCount {
|
|
||||||
[key: string]: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DoneCallback = (err?: Error) => void;
|
export type DoneCallback = (err?: Error) => void;
|
||||||
|
@@ -3,13 +3,7 @@ import 'mocha';
|
|||||||
|
|
||||||
import { Compiler } from '../src/compiler';
|
import { Compiler } from '../src/compiler';
|
||||||
import { fsWrapper } from '../src/utils/fs_wrapper';
|
import { fsWrapper } from '../src/utils/fs_wrapper';
|
||||||
import {
|
import { CompilerOptions, ContractArtifact, ContractNetworkData, DoneCallback } from '../src/utils/types';
|
||||||
CompilerOptions,
|
|
||||||
ContractArtifact,
|
|
||||||
ContractDirectory,
|
|
||||||
ContractNetworkData,
|
|
||||||
DoneCallback,
|
|
||||||
} from '../src/utils/types';
|
|
||||||
|
|
||||||
import { exchange_binary } from './fixtures/exchange_bin';
|
import { exchange_binary } from './fixtures/exchange_bin';
|
||||||
import { constants } from './util/constants';
|
import { constants } from './util/constants';
|
||||||
@@ -19,15 +13,11 @@ const expect = chai.expect;
|
|||||||
describe('#Compiler', function() {
|
describe('#Compiler', function() {
|
||||||
this.timeout(constants.timeoutMs);
|
this.timeout(constants.timeoutMs);
|
||||||
const artifactsDir = `${__dirname}/fixtures/artifacts`;
|
const artifactsDir = `${__dirname}/fixtures/artifacts`;
|
||||||
const mainContractDir: ContractDirectory = { path: `${__dirname}/fixtures/contracts/main`, namespace: 'main' };
|
const contractsDir = `${__dirname}/fixtures/contracts`;
|
||||||
const baseContractDir: ContractDirectory = { path: `${__dirname}/fixtures/contracts/base`, namespace: 'base' };
|
|
||||||
const contractDirs: Set<ContractDirectory> = new Set();
|
|
||||||
contractDirs.add(mainContractDir);
|
|
||||||
contractDirs.add(baseContractDir);
|
|
||||||
const exchangeArtifactPath = `${artifactsDir}/Exchange.json`;
|
const exchangeArtifactPath = `${artifactsDir}/Exchange.json`;
|
||||||
const compilerOpts: CompilerOptions = {
|
const compilerOpts: CompilerOptions = {
|
||||||
artifactsDir,
|
artifactsDir,
|
||||||
contractDirs,
|
contractsDir,
|
||||||
networkId: constants.networkId,
|
networkId: constants.networkId,
|
||||||
optimizerEnabled: constants.optimizerEnabled,
|
optimizerEnabled: constants.optimizerEnabled,
|
||||||
specifiedContracts: new Set(constants.specifiedContracts),
|
specifiedContracts: new Set(constants.specifiedContracts),
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import * as chai from 'chai';
|
import * as chai from 'chai';
|
||||||
import * as dirtyChai from 'dirty-chai';
|
import * as dirtyChai from 'dirty-chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -47,34 +48,36 @@ describe('Compiler utils', () => {
|
|||||||
});
|
});
|
||||||
describe('#parseDependencies', () => {
|
describe('#parseDependencies', () => {
|
||||||
it('correctly parses Exchange dependencies', async () => {
|
it('correctly parses Exchange dependencies', async () => {
|
||||||
const exchangeSource = await fsWrapper.readFileAsync(`${__dirname}/fixtures/contracts/main/Exchange.sol`, {
|
const path = `${__dirname}/fixtures/contracts/Exchange.sol`;
|
||||||
|
const source = await fsWrapper.readFileAsync(path, {
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
});
|
});
|
||||||
const sourceFileId = '/main/Exchange.sol';
|
const dependencies = parseDependencies({ source, path });
|
||||||
expect(parseDependencies(exchangeSource, sourceFileId)).to.be.deep.equal([
|
const expectedDependencies = [
|
||||||
'/main/TokenTransferProxy.sol',
|
'zeppelin-solidity/contracts/token/ERC20/ERC20.sol',
|
||||||
'/base/Token.sol',
|
'packages/deployer/lib/test/fixtures/contracts/TokenTransferProxy.sol',
|
||||||
'/base/SafeMath.sol',
|
'packages/deployer/lib/test/fixtures/contracts/base/SafeMath.sol',
|
||||||
]);
|
];
|
||||||
|
_.each(expectedDependencies, expectedDepdency => {
|
||||||
|
const foundDependency = _.find(dependencies, dependency => _.endsWith(dependency, expectedDepdency));
|
||||||
|
expect(foundDependency, `${expectedDepdency} not found`).to.not.be.undefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
it('correctly parses TokenTransferProxy dependencies', async () => {
|
it('correctly parses TokenTransferProxy dependencies', async () => {
|
||||||
const exchangeSource = await fsWrapper.readFileAsync(
|
const path = `${__dirname}/fixtures/contracts/TokenTransferProxy.sol`;
|
||||||
`${__dirname}/fixtures/contracts/main/TokenTransferProxy.sol`,
|
const source = await fsWrapper.readFileAsync(path, {
|
||||||
{
|
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
},
|
});
|
||||||
);
|
expect(parseDependencies({ source, path })).to.be.deep.equal([
|
||||||
const sourceFileId = '/main/TokenTransferProxy.sol';
|
'zeppelin-solidity/contracts/ownership/Ownable.sol',
|
||||||
expect(parseDependencies(exchangeSource, sourceFileId)).to.be.deep.equal([
|
'zeppelin-solidity/contracts/token/ERC20/ERC20.sol',
|
||||||
'/base/Token.sol',
|
|
||||||
'/base/Ownable.sol',
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
// TODO: For now that doesn't work. This will work after we switch to a grammar-based parser
|
// TODO: For now that doesn't work. This will work after we switch to a grammar-based parser
|
||||||
it.skip('correctly parses commented out dependencies', async () => {
|
it.skip('correctly parses commented out dependencies', async () => {
|
||||||
const contractWithCommentedOutDependencies = `// import "./TokenTransferProxy.sol";`;
|
const path = '';
|
||||||
const sourceFileId = '/main/TokenTransferProxy.sol';
|
const source = `// import "./TokenTransferProxy.sol";`;
|
||||||
expect(parseDependencies(contractWithCommentedOutDependencies, sourceFileId)).to.be.deep.equal([]);
|
expect(parseDependencies({ path, source })).to.be.deep.equal([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -4,30 +4,21 @@ import 'mocha';
|
|||||||
import { Compiler } from '../src/compiler';
|
import { Compiler } from '../src/compiler';
|
||||||
import { Deployer } from '../src/deployer';
|
import { Deployer } from '../src/deployer';
|
||||||
import { fsWrapper } from '../src/utils/fs_wrapper';
|
import { fsWrapper } from '../src/utils/fs_wrapper';
|
||||||
import {
|
import { CompilerOptions, ContractArtifact, ContractNetworkData, DoneCallback } from '../src/utils/types';
|
||||||
CompilerOptions,
|
|
||||||
ContractArtifact,
|
|
||||||
ContractDirectory,
|
|
||||||
ContractNetworkData,
|
|
||||||
DoneCallback,
|
|
||||||
} from '../src/utils/types';
|
|
||||||
|
|
||||||
import { constructor_args, exchange_binary } from './fixtures/exchange_bin';
|
import { constructor_args, exchange_binary } from './fixtures/exchange_bin';
|
||||||
import { constants } from './util/constants';
|
import { constants } from './util/constants';
|
||||||
|
import { provider } from './util/provider';
|
||||||
|
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
describe('#Deployer', () => {
|
describe('#Deployer', () => {
|
||||||
const artifactsDir = `${__dirname}/fixtures/artifacts`;
|
const artifactsDir = `${__dirname}/fixtures/artifacts`;
|
||||||
|
const contractsDir = `${__dirname}/fixtures/contracts`;
|
||||||
const exchangeArtifactPath = `${artifactsDir}/Exchange.json`;
|
const exchangeArtifactPath = `${artifactsDir}/Exchange.json`;
|
||||||
const mainContractDir: ContractDirectory = { path: `${__dirname}/fixtures/contracts/main`, namespace: '' };
|
|
||||||
const baseContractDir: ContractDirectory = { path: `${__dirname}/fixtures/contracts/base`, namespace: 'base' };
|
|
||||||
const contractDirs: Set<ContractDirectory> = new Set();
|
|
||||||
contractDirs.add(mainContractDir);
|
|
||||||
contractDirs.add(baseContractDir);
|
|
||||||
const compilerOpts: CompilerOptions = {
|
const compilerOpts: CompilerOptions = {
|
||||||
artifactsDir,
|
artifactsDir,
|
||||||
contractDirs,
|
contractsDir,
|
||||||
networkId: constants.networkId,
|
networkId: constants.networkId,
|
||||||
optimizerEnabled: constants.optimizerEnabled,
|
optimizerEnabled: constants.optimizerEnabled,
|
||||||
specifiedContracts: new Set(constants.specifiedContracts),
|
specifiedContracts: new Set(constants.specifiedContracts),
|
||||||
@@ -36,7 +27,7 @@ describe('#Deployer', () => {
|
|||||||
const deployerOpts = {
|
const deployerOpts = {
|
||||||
artifactsDir,
|
artifactsDir,
|
||||||
networkId: constants.networkId,
|
networkId: constants.networkId,
|
||||||
jsonrpcUrl: constants.jsonrpcUrl,
|
provider,
|
||||||
defaults: {
|
defaults: {
|
||||||
gasPrice: constants.gasPrice,
|
gasPrice: constants.gasPrice,
|
||||||
},
|
},
|
||||||
|
@@ -16,11 +16,12 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pragma solidity 0.4.14;
|
pragma solidity ^0.4.14;
|
||||||
|
|
||||||
|
import {ERC20 as Token} from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
|
||||||
|
|
||||||
import "./TokenTransferProxy.sol";
|
import "./TokenTransferProxy.sol";
|
||||||
import "/base/Token.sol";
|
import "./base/SafeMath.sol";
|
||||||
import "/base/SafeMath.sol";
|
|
||||||
|
|
||||||
/// @title Exchange - Facilitates exchange of ERC20 tokens.
|
/// @title Exchange - Facilitates exchange of ERC20 tokens.
|
||||||
/// @author Amir Bandeali - <amir@0xProject.com>, Will Warren - <will@0xProject.com>
|
/// @author Amir Bandeali - <amir@0xProject.com>, Will Warren - <will@0xProject.com>
|
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pragma solidity 0.4.14;
|
pragma solidity ^0.4.14;
|
||||||
|
|
||||||
import "/base/Token.sol";
|
import { Ownable } from "zeppelin-solidity/contracts/ownership/Ownable.sol";
|
||||||
import "/base/Ownable.sol";
|
import { ERC20 as Token } from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
|
||||||
|
|
||||||
/// @title TokenTransferProxy - Transfers tokens on behalf of contracts that have been approved via decentralized governance.
|
/// @title TokenTransferProxy - Transfers tokens on behalf of contracts that have been approved via decentralized governance.
|
||||||
/// @author Amir Bandeali - <amir@0xProject.com>, Will Warren - <will@0xProject.com>
|
/// @author Amir Bandeali - <amir@0xProject.com>, Will Warren - <will@0xProject.com>
|
@@ -1,27 +0,0 @@
|
|||||||
pragma solidity 0.4.14;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ownable
|
|
||||||
*
|
|
||||||
* Base contract with an owner.
|
|
||||||
* Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.
|
|
||||||
*/
|
|
||||||
|
|
||||||
contract Ownable {
|
|
||||||
address public owner;
|
|
||||||
|
|
||||||
function Ownable() {
|
|
||||||
owner = msg.sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
modifier onlyOwner() {
|
|
||||||
require(msg.sender == owner);
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
|
|
||||||
function transferOwnership(address newOwner) onlyOwner {
|
|
||||||
if (newOwner != address(0)) {
|
|
||||||
owner = newOwner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user