Compare commits
381 Commits
@0xproject
...
@0xproject
Author | SHA1 | Date | |
---|---|---|---|
|
8e5a876b37 | ||
|
c71b710d7e | ||
|
7440b87596 | ||
|
583a17d627 | ||
|
caf1a22084 | ||
|
29abc5e921 | ||
|
098dae9a7e | ||
|
aaa7affa46 | ||
|
40ca846cdc | ||
|
2a24f6e2ea | ||
|
98e8105ec5 | ||
|
4a94a2b4e8 | ||
|
2011349eb1 | ||
|
8057f4a678 | ||
|
f9ec8a0828 | ||
|
a0030c7bdb | ||
|
0e4448fd3f | ||
|
21d2d59b50 | ||
|
295f177271 | ||
|
f3154313a8 | ||
|
e37f3b4fa3 | ||
|
7e5c35d06e | ||
|
60756aa02b | ||
|
3779ab90de | ||
|
5b5037a844 | ||
|
03902b0b26 | ||
|
883feabb8b | ||
|
5fb79e3253 | ||
|
c44811fbc2 | ||
|
c3eaa694dd | ||
|
bd8b8abfea | ||
|
1a6c2e2bac | ||
|
e2e6ae937d | ||
|
5b9c5d2790 | ||
|
896a57d4ed | ||
|
c3de8d3a67 | ||
|
d1a92a0a2e | ||
|
5f626495fd | ||
|
238f3c89a7 | ||
|
6e724eb8a5 | ||
|
9aec1feae3 | ||
|
8517de128b | ||
|
a3e15c910c | ||
|
a6303de4d1 | ||
|
5356b0e118 | ||
|
e31309f213 | ||
|
6f8a70834b | ||
|
327cc307b3 | ||
|
f191ba6e69 | ||
|
a2b89411b0 | ||
|
f66efed777 | ||
|
f61b59fa89 | ||
|
6288a72036 | ||
|
a941f0ffb6 | ||
|
d7373a5c04 | ||
|
2ff485d2e0 | ||
|
5a67068348 | ||
|
d39af6c9eb | ||
|
1789025da9 | ||
|
696f49497b | ||
|
e88eba1877 | ||
|
f8b8a10b8f | ||
|
01e505a5f4 | ||
|
5b2d9a4668 | ||
|
71008dc819 | ||
|
9301173f7d | ||
|
60d95475eb | ||
|
c8ace2edc0 | ||
|
0b1ba9f997 | ||
|
f3026e33fd | ||
|
f014a97e9a | ||
|
ddad09a936 | ||
|
5dd0654105 | ||
|
b4b664e97a | ||
|
551771235b | ||
|
eb201c4084 | ||
|
7bfc499ec8 | ||
|
71e7e9c9c3 | ||
|
8521775389 | ||
|
61ad8d4c10 | ||
|
38a4ccd9f2 | ||
|
cf342dd00e | ||
|
08ab81c54c | ||
|
d355382f70 | ||
|
d171ce4fba | ||
|
5a90fece80 | ||
|
994935b5da | ||
|
874e667849 | ||
|
1817f6eaf6 | ||
|
2e19930178 | ||
|
2b01461748 | ||
|
24b9df475c | ||
|
011bab3c80 | ||
|
699c0c3e05 | ||
|
5f4b28960e | ||
|
3837913855 | ||
|
65eb3997d9 | ||
|
47411b406d | ||
|
f710026a8f | ||
|
925e133f50 | ||
|
2bdd60ed72 | ||
|
9ac1cce26f | ||
|
0a597c94d6 | ||
|
02f82be094 | ||
|
86e26240a1 | ||
|
82c5be2564 | ||
|
42f4f07268 | ||
|
df4db8fa4c | ||
|
bd85fe0af3 | ||
|
aee15e5dff | ||
|
d7a803d9fd | ||
|
839e5895e4 | ||
|
49a4f0c74c | ||
|
5bea8e63de | ||
|
e64be284dd | ||
|
e11e26a352 | ||
|
bee90abbc4 | ||
|
8782559c33 | ||
|
223ddc0f68 | ||
|
4445d1d5a0 | ||
|
b7d001da88 | ||
|
3592ebef08 | ||
|
a783d21409 | ||
|
a716e3de74 | ||
|
c797c720be | ||
|
1b5742fbf0 | ||
|
5794349d97 | ||
|
456f094913 | ||
|
abb9eb0df4 | ||
|
9e7b45ea4c | ||
|
6c6bd60a48 | ||
|
cef82e72dc | ||
|
45b9647ba0 | ||
|
160f74d53e | ||
|
3ab6139522 | ||
|
9aa54257e7 | ||
|
8eafa62bbe | ||
|
968c24f0bc | ||
|
e5c755b1fc | ||
|
6d56f01c40 | ||
|
eefce48e68 | ||
|
c7d97c733a | ||
|
3db42deb42 | ||
|
02603e8926 | ||
|
c5003554f4 | ||
|
eb223805ca | ||
|
244c148a80 | ||
|
4dbb2ed167 | ||
|
212d680a47 | ||
|
a853e35dec | ||
|
fdaf9f0bfc | ||
|
0afe45b3a8 | ||
|
f9a37168b0 | ||
|
52232e98c7 | ||
|
0fbb443e4b | ||
|
8021694b81 | ||
|
a2b262c9df | ||
|
5906f4c995 | ||
|
da8edd2226 | ||
|
406aedfdc2 | ||
|
67c834841e | ||
|
edaa0b0e34 | ||
|
31f03fcf3a | ||
|
4a57f2a762 | ||
|
92b9dbd706 | ||
|
6edd7682a9 | ||
|
447891b396 | ||
|
89bfcafb80 | ||
|
a74a04c5d5 | ||
|
0c16f0ea22 | ||
|
003d43b03a | ||
|
6323496945 | ||
|
fd5e231a93 | ||
|
ae209677de | ||
|
d5ca00de95 | ||
|
7be84c6ad3 | ||
|
425039e4d3 | ||
|
6c5333180d | ||
|
cb47a51b70 | ||
|
e36fb654b0 | ||
|
6325fac020 | ||
|
c6358d5f22 | ||
|
413e8b6062 | ||
|
e113a8e7af | ||
|
e42891ae5b | ||
|
c90770472e | ||
|
45df9de5b5 | ||
|
2d0940589e | ||
|
5908f189a7 | ||
|
17328bce53 | ||
|
451a0dacbe | ||
|
a46199e37d | ||
|
e25cc301fd | ||
|
5bbb0d1f60 | ||
|
a5b8875356 | ||
|
3e86df311d | ||
|
002f9ebde7 | ||
|
72e6e1ce8b | ||
|
a3c7af95e1 | ||
|
0987c9a7cf | ||
|
bbd87daf6d | ||
|
30e4613d0a | ||
|
79593f52b0 | ||
|
bab8c1eeff | ||
|
8b6cc95c1b | ||
|
90236b87de | ||
|
b6a133cc64 | ||
|
7aa070f9ea | ||
|
c2ec2291e8 | ||
|
97fcfb7f6c | ||
|
ce677fd55a | ||
|
e48a3edacb | ||
|
ce0b92d681 | ||
|
29c5ba5639 | ||
|
cdea618457 | ||
|
425a519f97 | ||
|
c07d64c6ff | ||
|
c07e3a76bb | ||
|
8fe844bcc9 | ||
|
a0390956a9 | ||
|
4f1e6296ca | ||
|
0ef372e531 | ||
|
06e2894750 | ||
|
10e2d4b99c | ||
|
ef40cb9687 | ||
|
758604fc1a | ||
|
34c1134b55 | ||
|
a5ef1db0c5 | ||
|
748ed40321 | ||
|
42063f785e | ||
|
1657451f37 | ||
|
0bb0bff0b3 | ||
|
747732118c | ||
|
2aec1501d0 | ||
|
39c6bc1106 | ||
|
4e451479f8 | ||
|
93b2736d65 | ||
|
34274a1042 | ||
|
fa822caa62 | ||
|
ddc30cc2c0 | ||
|
9d9cab1711 | ||
|
fe8f2d8d89 | ||
|
2d561bc8a0 | ||
|
f5275d3ad7 | ||
|
5fbdf9cfb9 | ||
|
0409c9c1e5 | ||
|
42a5da1df4 | ||
|
0b326a8bbe | ||
|
9c8501a84e | ||
|
2da7f82171 | ||
|
593474031d | ||
|
fce10548d2 | ||
|
addca63938 | ||
|
6961169f89 | ||
|
3d66feb89f | ||
|
bb157eefc6 | ||
|
7f8f4df0a0 | ||
|
4b325676f7 | ||
|
ecba95250d | ||
|
dd116b3cd6 | ||
|
eabe96fd19 | ||
|
7dd9ce2e32 | ||
|
fffaafe4c9 | ||
|
0b9646136a | ||
|
55f38b9c35 | ||
|
709fa9e02e | ||
|
f42bdb8bab | ||
|
10aed46062 | ||
|
6e43e89b2d | ||
|
10c0c0b6d2 | ||
|
e13924cd2d | ||
|
7afe00f06a | ||
|
87b9caa7dc | ||
|
f689d335c0 | ||
|
31f9a848f9 | ||
|
3d2c5d67af | ||
|
63f8f469b0 | ||
|
9929f1acf0 | ||
|
42ecc087cb | ||
|
93adee36b0 | ||
|
0e95fd0b9b | ||
|
611ddfeeb8 | ||
|
dfe2579eeb | ||
|
66b36f6d8f | ||
|
1b3a9102f1 | ||
|
9993a50903 | ||
|
c226509be0 | ||
|
ef6f52e722 | ||
|
7d8cad8e3a | ||
|
15507d3827 | ||
|
e2d17d122e | ||
|
0d7bf50581 | ||
|
a50618fcb0 | ||
|
fc2a9a756a | ||
|
07721eb99f | ||
|
13fed15e0c | ||
|
38a308ce5b | ||
|
be19316dfb | ||
|
c4f65681a1 | ||
|
f600226aa9 | ||
|
67f2864501 | ||
|
c1bbcaba73 | ||
|
6685cb3fba | ||
|
d770e46208 | ||
|
665636e642 | ||
|
0028e71ab2 | ||
|
7fb66bf71a | ||
|
3120d854f8 | ||
|
c85c14210f | ||
|
0fb81a11a8 | ||
|
7b67afae06 | ||
|
fe9e319a61 | ||
|
097fc477a2 | ||
|
f60b00d116 | ||
|
3a36e0621f | ||
|
b482473e23 | ||
|
9a5fd3f784 | ||
|
b703ccde9b | ||
|
80eca30725 | ||
|
7dbc14dc43 | ||
|
b3f9010eb5 | ||
|
f62d72e548 | ||
|
d12352972e | ||
|
03d3d84db3 | ||
|
6d818c25c7 | ||
|
6a8f624e75 | ||
|
0801b1ddf9 | ||
|
4fd64ca492 | ||
|
c4bcf24640 | ||
|
0114fc9608 | ||
|
8db098eaec | ||
|
05c3a66543 | ||
|
9349752baa | ||
|
974fab7284 | ||
|
8a52ffe7b7 | ||
|
c6ecdbd86e | ||
|
03797545f9 | ||
|
2778f96483 | ||
|
6cd4e7a17e | ||
|
5c91b4bfc6 | ||
|
e2b51c5dc4 | ||
|
b610b7c192 | ||
|
b75fdd6b66 | ||
|
060b02eaed | ||
|
003e5da00d | ||
|
02951d4813 | ||
|
db52ed9941 | ||
|
af333b1838 | ||
|
f62762bd0e | ||
|
4b67352278 | ||
|
76afb6b116 | ||
|
db52e87740 | ||
|
e22788abe8 | ||
|
bbfbfcda85 | ||
|
0dfb36e675 | ||
|
95a9d77301 | ||
|
ab1f070901 | ||
|
8201d5d1f8 | ||
|
8704c34a0f | ||
|
599adaf1bf | ||
|
778e399438 | ||
|
485ae4d997 | ||
|
8cd2ba3ad6 | ||
|
dbad7d1869 | ||
|
4d482438f5 | ||
|
b53a1b51d6 | ||
|
49375c73d4 | ||
|
98b78c56c5 | ||
|
f3e6ef0fa9 | ||
|
18e1c2dea5 | ||
|
91ae01e484 | ||
|
2897b72967 | ||
|
3510985cf4 | ||
|
5927e65045 | ||
|
13e2041d50 | ||
|
4bf530ed9e | ||
|
4c797405ad | ||
|
713c922e35 | ||
|
7f1e789264 | ||
|
07d00cc515 | ||
|
ba57c34adb |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -68,6 +68,10 @@ generated_docs/
|
||||
TODO.md
|
||||
|
||||
packages/website/public/bundle*
|
||||
packages/react-docs/example/public/bundle*
|
||||
|
||||
# generated binaries
|
||||
bin/
|
||||
|
||||
# generated contract artifacts
|
||||
packages/contracts/src/artifacts
|
||||
|
@@ -1,5 +1,5 @@
|
||||
lib
|
||||
generated
|
||||
.nyc_output
|
||||
/packages/contracts/build/contracts
|
||||
/packages/contracts/src/artifacts
|
||||
package.json
|
||||
scripts/postpublish_utils.js
|
||||
|
@@ -8,9 +8,9 @@ If you'd like to contribute to 0x protocol, please fork the repo, fix, commit an
|
||||
|
||||
We encourage a “PR early” approach so create the PR as early as possible even without the fix/feature ready, so that devs and other contributors know you have picked up the issue. These early PRs should indicate an 'in progress' status by adding the '[WIP]' prefix to the PR title. Please make sure your contributions adhere to our coding guidelines:
|
||||
|
||||
* Pull requests adding features or refactoring should be opened against the `development` branch
|
||||
* Pull requests fixing bugs in the latest release version should be opened again the `master` branch
|
||||
* Write [good commit messages](https://chris.beams.io/posts/git-commit/)
|
||||
* Pull requests adding features or refactoring should be opened against the `development` branch
|
||||
* Pull requests fixing bugs in the latest release version should be opened again the `master` branch
|
||||
* Write [good commit messages](https://chris.beams.io/posts/git-commit/)
|
||||
|
||||
### Code quality
|
||||
|
||||
@@ -23,7 +23,7 @@ If the sub-package you are modifying has a `CHANGELOG.md` file, make sure to add
|
||||
|
||||
### Styleguide
|
||||
|
||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x.js/tree/development/packages/tslint-config) to keep our code style consistent.
|
||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) to keep our code style consistent.
|
||||
|
||||
To lint your code just run: `yarn lint`
|
||||
|
||||
@@ -31,10 +31,10 @@ We also use [Prettier](https://prettier.io/) to auto-format our code. Be sure to
|
||||
|
||||
If using the Atom text editor, we recommend you install the following packages:
|
||||
|
||||
* [atom-typescript](https://atom.io/packages/atom-typescript)
|
||||
* [linter-tslint](https://atom.io/packages/linter-tslint)
|
||||
* [prettier-atom](https://atom.io/packages/prettier-atom)
|
||||
* [language-ethereum](https://atom.io/packages/language-ethereum)
|
||||
* [atom-typescript](https://atom.io/packages/atom-typescript)
|
||||
* [linter-tslint](https://atom.io/packages/linter-tslint)
|
||||
* [prettier-atom](https://atom.io/packages/prettier-atom)
|
||||
* [language-ethereum](https://atom.io/packages/language-ethereum)
|
||||
|
||||
Our CI will also run TSLint and Prettier as a part of the test run when you submit your PR. Make sure that the CI tests pass for your contribution.
|
||||
|
||||
|
@@ -24,9 +24,9 @@
|
||||
|
||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||
|
||||
* [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
* [ ] New feature (non-breaking change which adds functionality)
|
||||
* [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||
* [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
* [ ] New feature (non-breaking change which adds functionality)
|
||||
* [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||
|
||||
## Checklist:
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
|
||||
* [ ] Change requires a change to the documentation.
|
||||
* [ ] Added tests to cover my changes.
|
||||
* [ ] Added new entries to the relevant CHANGELOGs.
|
||||
* [ ] Updated the new versions of the changed packages in the relevant CHANGELOGs.
|
||||
* [ ] Labeled this PR with the 'WIP' label if it is a work in progress.
|
||||
* [ ] Labeled this PR with the labels corresponding to the changed package.
|
||||
* [ ] Change requires a change to the documentation.
|
||||
* [ ] Added tests to cover my changes.
|
||||
* [ ] Added new entries to the relevant CHANGELOGs.
|
||||
* [ ] Updated the new versions of the changed packages in the relevant CHANGELOGs.
|
||||
* [ ] Labeled this PR with the 'WIP' label if it is a work in progress.
|
||||
* [ ] Labeled this PR with the labels corresponding to the changed package.
|
||||
|
51
README.md
51
README.md
@@ -4,36 +4,39 @@
|
||||
|
||||
[0x][website-url] is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets. A full description of the protocol may be found in our [whitepaper][whitepaper-url].
|
||||
|
||||
This repository contains all the 0x developer tools written in TypeScript. Our hope is that these tools make it easy to build Relayers and other DApps that use the 0x protocol.
|
||||
This repository is a monorepo including the 0x protocol smart contracts and numerous developer tools. Each public sub-package is independently published to NPM.
|
||||
|
||||
[website-url]: https://0xproject.com/
|
||||
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
|
||||
|
||||
[](https://circleci.com/gh/0xProject/0x.js)
|
||||
[](https://coveralls.io/github/0xProject/0x.js?branch=master)
|
||||
[](https://circleci.com/gh/0xProject/0x-monorepo)
|
||||
[](https://coveralls.io/github/0xProject/0x-monorepo?branch=master)
|
||||
[](https://chat.0xproject.com)
|
||||
[](https://gitter.im/0xProject/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://greenkeeper.io/)
|
||||
[](https://greenkeeper.io/)
|
||||
|
||||
### Published Packages
|
||||
|
||||
| Package | Version | Description |
|
||||
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`chai-as-promised-typescript-typings`](/packages/chai-as-promised-typescript-typings) | [](https://www.npmjs.com/package/chai-as-promised-typescript-typings) | Chai as promised typescript typings |
|
||||
| [`chai-typescript-typings`](/packages/chai-typescript-typings) | [](https://www.npmjs.com/package/chai-typescript-typings) | Chai typescript typings |
|
||||
| [`web3-typescript-typings`](/packages/web3-typescript-typings) | [](https://www.npmjs.com/package/web3-typescript-typings) | Web3 typescript typings |
|
||||
| [`@0xproject/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the standard relayer api |
|
||||
| [`@0xproject/dev-utils`](/packages/dev-utils) | [](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
||||
| [`@0xproject/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
|
||||
| Package | Version | Description |
|
||||
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`@0xproject/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0xproject/base-contract`](/packages/base-contract) | [](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract to derive all auto-generated wrappers from |
|
||||
| [`chai-as-promised-typescript-typings`](/packages/chai-as-promised-typescript-typings) | [](https://www.npmjs.com/package/chai-as-promised-typescript-typings) | Chai as promised typescript typings |
|
||||
| [`chai-typescript-typings`](/packages/chai-typescript-typings) | [](https://www.npmjs.com/package/chai-typescript-typings) | Chai typescript typings |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the standard relayer api |
|
||||
| [`@0xproject/deployer`](/packages/deployer) | [](https://www.npmjs.com/package/@0xproject/deployer) | Smart contract deployer |
|
||||
| [`@0xproject/dev-utils`](/packages/dev-utils) | [](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
|
||||
| [`ethers-typescript-typings`](/packages/ethers-typescript-typings) | [](https://www.npmjs.com/package/ethers-typescript-typings) | [Ethers.js](https://github.com/ethers-io/ethers.js/) typescript typings |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
||||
| [`@0xproject/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
||||
| [`web3-typescript-typings`](/packages/web3-typescript-typings) | [](https://www.npmjs.com/package/web3-typescript-typings) | Web3 typescript typings |
|
||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
|
||||
|
||||
### Private Packages
|
||||
|
||||
@@ -48,10 +51,10 @@ This repository contains all the 0x developer tools written in TypeScript. Our h
|
||||
|
||||
Dedicated documentation pages:
|
||||
|
||||
* [0x.js Library](https://0xproject.com/docs/0xjs)
|
||||
* [0x Connect](https://0xproject.com/docs/connect)
|
||||
* [Smart contracts](https://0xproject.com/docs/contracts)
|
||||
* [Standard Relayer API](https://github.com/0xProject/standard-relayer-api/blob/master/README.md)
|
||||
* [0x.js Library](https://0xproject.com/docs/0xjs)
|
||||
* [0x Connect](https://0xproject.com/docs/connect)
|
||||
* [Smart contracts](https://0xproject.com/docs/contracts)
|
||||
* [Standard Relayer API](https://github.com/0xProject/standard-relayer-api/blob/master/README.md)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -1,6 +1,11 @@
|
||||
{
|
||||
"lerna": "2.5.1",
|
||||
"packages": ["packages/*"],
|
||||
"commands": {
|
||||
"publish": {
|
||||
"allowBranch": "development"
|
||||
}
|
||||
},
|
||||
"version": "independent",
|
||||
"commands": {
|
||||
"publish": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "0x.js",
|
||||
"name": "0x-monorepo",
|
||||
"workspaces": ["packages/*"],
|
||||
"scripts": {
|
||||
"dev": "lerna run --parallel build:watch",
|
||||
@@ -16,11 +16,11 @@
|
||||
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/utils": "^0.3.2",
|
||||
"@0xproject/utils": "^0.4.0",
|
||||
"async-child-process": "^1.1.1",
|
||||
"ethereumjs-testrpc": "^6.0.3",
|
||||
"lerna": "^2.5.1",
|
||||
"prettier": "1.9.2",
|
||||
"prettier": "^1.11.1",
|
||||
"publish-release": "0xproject/publish-release",
|
||||
"semver-sort": "^0.0.4"
|
||||
}
|
||||
|
@@ -1,5 +1,17 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.33.1 - _March 8, 2018_
|
||||
|
||||
* Add missing EthersJs typescript typings as dependency
|
||||
|
||||
## v0.33.0 - _March 4, 2018_
|
||||
|
||||
* Validate and lowercase all addresses in public methods (#373)
|
||||
* Improve validation to force passing contract addresses on private networks (#385)
|
||||
* Change `LogErrorContractEventArgs.errorId` type from `BigNumber` to `number` (#413)
|
||||
* Rename all public `_unsubscribeAll` methods to `unsubscribeAll` (#415)
|
||||
* Move web3 typings from devDep to dep since cannot use this package without it (#429)
|
||||
|
||||
## v0.32.2 - _February 9, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
@@ -18,11 +18,20 @@ npm install 0x.js --save
|
||||
import { ZeroEx } from '0x.js';
|
||||
```
|
||||
|
||||
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
|
||||
|
||||
```
|
||||
"include": [
|
||||
"./node_modules/web3-typescript-typings/index.d.ts",
|
||||
"./node_modules/ethers-typescript-typings/index.d.ts"
|
||||
]
|
||||
```
|
||||
|
||||
#### UMD:
|
||||
|
||||
**Install**
|
||||
|
||||
Download the UMD module from our [releases page](https://github.com/0xProject/0x.js/releases) and add it to your project.
|
||||
Download the UMD module from our [releases page](https://github.com/0xProject/0x-monorepo/releases) and add it to your project.
|
||||
|
||||
**Import**
|
||||
|
||||
|
@@ -1,15 +0,0 @@
|
||||
public {{this.name}} = {
|
||||
async callAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
defaultBlock?: Web3.BlockParam,
|
||||
): Promise<{{> return_type outputs=outputs}}> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const result = await promisify<{{> return_type outputs=outputs}}>(
|
||||
self._web3ContractInstance.{{this.name}}.call,
|
||||
self._web3ContractInstance,
|
||||
)(
|
||||
{{> params inputs=inputs}}
|
||||
);
|
||||
return result;
|
||||
},
|
||||
};
|
@@ -1,6 +0,0 @@
|
||||
{{#singleReturnValue}}
|
||||
{{#returnType outputs.0.type}}{{/returnType}}
|
||||
{{/singleReturnValue}}
|
||||
{{^singleReturnValue}}
|
||||
[{{#each outputs}}{{#returnType type}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||
{{/singleReturnValue}}
|
@@ -1,3 +0,0 @@
|
||||
{{#each inputs}}
|
||||
{{name}}: {{#parameterType type}}{{/parameterType}},
|
||||
{{/each}}
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "0x.js",
|
||||
"version": "0.32.2",
|
||||
"version": "0.33.1",
|
||||
"description": "A javascript library for interacting with the 0x protocol",
|
||||
"keywords": [
|
||||
"0x.js",
|
||||
@@ -15,9 +15,9 @@
|
||||
"build:watch": "tsc -w",
|
||||
"prebuild": "run-s clean generate_contract_wrappers",
|
||||
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
|
||||
"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",
|
||||
"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",
|
||||
"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'",
|
||||
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
||||
"test:circleci": "run-s test:coverage report_test_coverage",
|
||||
"test": "run-s clean test:commonjs",
|
||||
@@ -35,16 +35,16 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x.js"
|
||||
"url": "https://github.com/0xProject/0x-monorepo"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/abi-gen": "^0.2.1",
|
||||
"@0xproject/dev-utils": "^0.0.12",
|
||||
"@0xproject/tslint-config": "^0.4.8",
|
||||
"@0xproject/abi-gen": "^0.2.5",
|
||||
"@0xproject/dev-utils": "^0.2.1",
|
||||
"@0xproject/tslint-config": "^0.4.10",
|
||||
"@types/bintrees": "^1.0.2",
|
||||
"@types/jsonschema": "^1.1.1",
|
||||
"@types/lodash": "^4.14.86",
|
||||
@@ -55,9 +55,9 @@
|
||||
"awesome-typescript-loader": "^3.1.3",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-as-promised-typescript-typings": "^0.0.9",
|
||||
"chai-as-promised-typescript-typings": "^0.0.10",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"chai-typescript-typings": "^0.0.3",
|
||||
"chai-typescript-typings": "^0.0.4",
|
||||
"copyfiles": "^1.2.0",
|
||||
"coveralls": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
@@ -73,27 +73,30 @@
|
||||
"source-map-support": "^0.5.0",
|
||||
"truffle-hdwallet-provider": "^0.0.3",
|
||||
"tslint": "5.8.0",
|
||||
"typedoc": "~0.8.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"types-bn": "^0.0.1",
|
||||
"typescript": "2.7.1",
|
||||
"web3-provider-engine": "^13.0.1",
|
||||
"web3-typescript-typings": "^0.9.10",
|
||||
"webpack": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^0.0.18",
|
||||
"@0xproject/json-schemas": "^0.7.10",
|
||||
"@0xproject/types": "^0.2.1",
|
||||
"@0xproject/utils": "^0.3.2",
|
||||
"@0xproject/web3-wrapper": "^0.1.12",
|
||||
"@0xproject/assert": "^0.2.0",
|
||||
"@0xproject/base-contract": "^0.0.3",
|
||||
"@0xproject/json-schemas": "^0.7.14",
|
||||
"@0xproject/types": "^0.3.1",
|
||||
"@0xproject/utils": "^0.4.1",
|
||||
"@0xproject/web3-wrapper": "^0.2.1",
|
||||
"bintrees": "^1.0.2",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereumjs-abi": "^0.6.4",
|
||||
"ethereumjs-blockstream": "^2.0.6",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"ethers-contracts": "^2.2.1",
|
||||
"ethers-typescript-typings": "^0.0.2",
|
||||
"js-sha3": "^0.7.0",
|
||||
"lodash": "^4.17.4",
|
||||
"uuid": "^3.1.0",
|
||||
"web3": "^0.20.0"
|
||||
"web3": "^0.20.0",
|
||||
"web3-typescript-typings": "^0.10.0"
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,16 @@
|
||||
const execAsync = require('async-child-process').execAsync;
|
||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
|
||||
const packageJSON = require('../package.json');
|
||||
const tsConfig = require('../tsconfig.json');
|
||||
|
||||
const cwd = __dirname + '/..';
|
||||
const subPackageName = packageJSON.name;
|
||||
// Include any external packages that are part of the 0x.js public interface
|
||||
// to this array so that TypeDoc picks it up and adds it to the Docs JSON
|
||||
// So far, we only have @0xproject/types as part of 0x.js's public interface.
|
||||
const fileIncludes = [...tsConfig.include, '../types/src/index.ts'];
|
||||
const fileIncludesAdjusted = postpublish_utils.adjustFileIncludePaths(fileIncludes, __dirname);
|
||||
const projectFiles = fileIncludesAdjusted.join(' ');
|
||||
const S3BucketPath = 's3://0xjs-docs-jsons/';
|
||||
|
||||
let tag;
|
||||
@@ -20,7 +27,7 @@ postpublish_utils
|
||||
.then(function(release) {
|
||||
console.log('POSTPUBLISH: Release successful, generating docs...');
|
||||
const jsonFilePath = __dirname + '/../' + postpublish_utils.generatedDocsDirectoryName + '/index.json';
|
||||
return execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_DIR=' + __dirname + '/.. yarn docs:json', {
|
||||
return execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_FILES="' + projectFiles + '" yarn docs:json', {
|
||||
cwd,
|
||||
});
|
||||
})
|
||||
|
31
packages/0x.js/scripts/stagedocs.js
Normal file
31
packages/0x.js/scripts/stagedocs.js
Normal file
@@ -0,0 +1,31 @@
|
||||
const execAsync = require('async-child-process').execAsync;
|
||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
|
||||
const tsConfig = require('../tsconfig.json');
|
||||
|
||||
const cwd = __dirname + '/..';
|
||||
const S3BucketPath = 's3://staging-0xjs-docs-jsons/';
|
||||
// Include any external packages that are part of the 0x.js public interface
|
||||
// to this array so that TypeDoc picks it up and adds it to the Docs JSON
|
||||
// So far, we only have @0xproject/types as part of 0x.js's public interface.
|
||||
const fileIncludes = [...tsConfig.include, '../types/src/index.ts'];
|
||||
const fileIncludesAdjusted = postpublish_utils.adjustFileIncludePaths(fileIncludes, __dirname);
|
||||
const projectFiles = fileIncludesAdjusted.join(' ');
|
||||
const jsonFilePath = __dirname + '/../' + postpublish_utils.generatedDocsDirectoryName + '/index.json';
|
||||
const version = process.env.DOCS_VERSION;
|
||||
|
||||
execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_FILES="' + projectFiles + '" yarn docs:json', {
|
||||
cwd,
|
||||
})
|
||||
.then(function(result) {
|
||||
if (result.stderr !== '') {
|
||||
throw new Error(result.stderr);
|
||||
}
|
||||
const fileName = 'v' + version + '.json';
|
||||
const s3Url = S3BucketPath + fileName;
|
||||
return execAsync('S3_URL=' + s3Url + ' yarn upload_docs_json', {
|
||||
cwd,
|
||||
});
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log(err);
|
||||
});
|
@@ -13,6 +13,8 @@ import { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_pr
|
||||
import { TokenWrapper } from './contract_wrappers/token_wrapper';
|
||||
import { OrderStateWatcher } from './order_watcher/order_state_watcher';
|
||||
import { zeroExConfigSchema } from './schemas/zero_ex_config_schema';
|
||||
import { zeroExPrivateNetworkConfigSchema } from './schemas/zero_ex_private_network_config_schema';
|
||||
import { zeroExPublicNetworkConfigSchema } from './schemas/zero_ex_public_network_config_schema';
|
||||
import { ECSignature, Order, SignedOrder, Web3Provider, ZeroExConfig, ZeroExError } from './types';
|
||||
import { assert } from './utils/assert';
|
||||
import { constants } from './utils/constants';
|
||||
@@ -74,8 +76,9 @@ export class ZeroEx {
|
||||
assert.isHexString('data', data);
|
||||
assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema);
|
||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||
|
||||
const isValidSignature = signatureUtils.isValidSignature(data, signature, signerAddress);
|
||||
const isValidSignature = signatureUtils.isValidSignature(data, signature, normalizedSignerAddress);
|
||||
return isValidSignature;
|
||||
}
|
||||
/**
|
||||
@@ -163,7 +166,10 @@ export class ZeroEx {
|
||||
*/
|
||||
constructor(provider: Web3Provider, config: ZeroExConfig) {
|
||||
assert.isWeb3Provider('provider', provider);
|
||||
assert.doesConformToSchema('config', config, zeroExConfigSchema);
|
||||
assert.doesConformToSchema('config', config, zeroExConfigSchema, [
|
||||
zeroExPrivateNetworkConfigSchema,
|
||||
zeroExPublicNetworkConfigSchema,
|
||||
]);
|
||||
const artifactJSONs = _.values(artifacts);
|
||||
const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
|
||||
this._abiDecoder = new AbiDecoder(abiArrays);
|
||||
@@ -245,6 +251,7 @@ export class ZeroEx {
|
||||
): Promise<ECSignature> {
|
||||
assert.isHexString('orderHash', orderHash);
|
||||
await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper);
|
||||
const normalizedSignerAddress = signerAddress.toLowerCase();
|
||||
|
||||
let msgHashHex = orderHash;
|
||||
if (shouldAddPersonalMessagePrefix) {
|
||||
@@ -253,7 +260,7 @@ export class ZeroEx {
|
||||
msgHashHex = ethUtil.bufferToHex(msgHashBuff);
|
||||
}
|
||||
|
||||
const signature = await this._web3Wrapper.signTransactionAsync(signerAddress, msgHashHex);
|
||||
const signature = await this._web3Wrapper.signTransactionAsync(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)
|
||||
@@ -262,7 +269,7 @@ export class ZeroEx {
|
||||
const validVParamValues = [27, 28];
|
||||
const ecSignatureVRS = signatureUtils.parseSignatureHexAsVRS(signature);
|
||||
if (_.includes(validVParamValues, ecSignatureVRS.v)) {
|
||||
const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, signerAddress);
|
||||
const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, normalizedSignerAddress);
|
||||
if (isValidVRSSignature) {
|
||||
return ecSignatureVRS;
|
||||
}
|
||||
@@ -270,7 +277,7 @@ export class ZeroEx {
|
||||
|
||||
const ecSignatureRSV = signatureUtils.parseSignatureHexAsRSV(signature);
|
||||
if (_.includes(validVParamValues, ecSignatureRSV.v)) {
|
||||
const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, signerAddress);
|
||||
const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, normalizedSignerAddress);
|
||||
if (isValidRSVSignature) {
|
||||
return ecSignatureRSV;
|
||||
}
|
||||
|
@@ -108,10 +108,10 @@ export class ContractWrapper {
|
||||
const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
|
||||
return logWithDecodedArgs;
|
||||
}
|
||||
protected async _instantiateContractIfExistsAsync(
|
||||
protected async _getContractAbiAndAddressFromArtifactsAsync(
|
||||
artifact: Artifact,
|
||||
addressIfExists?: string,
|
||||
): Promise<Web3.ContractInstance> {
|
||||
): Promise<[Web3.ContractAbi, string]> {
|
||||
let contractAddress: string;
|
||||
if (_.isUndefined(addressIfExists)) {
|
||||
if (_.isUndefined(artifact.networks[this._networkId])) {
|
||||
@@ -125,8 +125,8 @@ export class ContractWrapper {
|
||||
if (!doesContractExist) {
|
||||
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
|
||||
}
|
||||
const contractInstance = this._web3Wrapper.getContractInstance(artifact.abi, contractAddress);
|
||||
return contractInstance;
|
||||
const abiAndAddress: [Web3.ContractAbi, string] = [artifact.abi, contractAddress];
|
||||
return abiAndAddress;
|
||||
}
|
||||
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
|
||||
if (_.isUndefined(addressIfExists)) {
|
||||
|
@@ -41,15 +41,18 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
depositor: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||
await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
|
||||
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||
const normalizedDepositorAddress = depositor.toLowerCase();
|
||||
|
||||
const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(depositor);
|
||||
const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(normalizedDepositorAddress);
|
||||
assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit);
|
||||
|
||||
const wethContract = await this._getEtherTokenContractAsync(etherTokenAddress);
|
||||
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
|
||||
const txHash = await wethContract.deposit.sendTransactionAsync({
|
||||
from: depositor,
|
||||
from: normalizedDepositorAddress,
|
||||
value: amountInWei,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
@@ -72,14 +75,20 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
|
||||
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||
const normalizedWithdrawerAddress = withdrawer.toLowerCase();
|
||||
|
||||
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(etherTokenAddress, withdrawer);
|
||||
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(
|
||||
normalizedEtherTokenAddress,
|
||||
normalizedWithdrawerAddress,
|
||||
);
|
||||
assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal);
|
||||
|
||||
const wethContract = await this._getEtherTokenContractAsync(etherTokenAddress);
|
||||
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
|
||||
const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
|
||||
from: withdrawer,
|
||||
from: normalizedWithdrawerAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
});
|
||||
@@ -101,11 +110,12 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const logs = await this._getLogsAsync<ArgsType>(
|
||||
etherTokenAddress,
|
||||
normalizedEtherTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
@@ -129,11 +139,12 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
callback: EventCallback<ArgsType>,
|
||||
): string {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
|
||||
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const subscriptionToken = this._subscribe<ArgsType>(
|
||||
etherTokenAddress,
|
||||
normalizedEtherTokenAddress,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
artifacts.EtherTokenArtifact.abi,
|
||||
@@ -151,7 +162,7 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public _unsubscribeAll(): void {
|
||||
public unsubscribeAll(): void {
|
||||
super._unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
@@ -168,7 +179,7 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
return contractAddressIfExists;
|
||||
}
|
||||
private _invalidateContractInstance(): void {
|
||||
this._unsubscribeAll();
|
||||
this.unsubscribeAll();
|
||||
this._etherTokenContractsByAddress = {};
|
||||
}
|
||||
private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<EtherTokenContract> {
|
||||
@@ -176,11 +187,11 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
if (!_.isUndefined(etherTokenContract)) {
|
||||
return etherTokenContract;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||
artifacts.EtherTokenArtifact,
|
||||
etherTokenAddress,
|
||||
);
|
||||
const contractInstance = new EtherTokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
||||
const contractInstance = new EtherTokenContract(this._web3Wrapper, abi, address);
|
||||
etherTokenContract = contractInstance;
|
||||
this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
|
||||
return etherTokenContract;
|
||||
|
@@ -108,8 +108,10 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||
const txData = {};
|
||||
let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.callAsync(
|
||||
orderHash,
|
||||
txData,
|
||||
defaultBlock,
|
||||
);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
@@ -127,7 +129,8 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||
let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, defaultBlock);
|
||||
const txData = {};
|
||||
let fillAmountInBaseUnits = await exchangeContract.filled.callAsync(orderHash, txData, defaultBlock);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
|
||||
return fillAmountInBaseUnits;
|
||||
@@ -144,7 +147,8 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||
let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, defaultBlock);
|
||||
const txData = {};
|
||||
let cancelledAmountInBaseUnits = await exchangeContract.cancelled.callAsync(orderHash, txData, defaultBlock);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
|
||||
return cancelledAmountInBaseUnits;
|
||||
@@ -180,6 +184,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
@@ -192,7 +197,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
normalizedTakerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
@@ -208,7 +213,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
signedOrder.ecSignature.r,
|
||||
signedOrder.ecSignature.s,
|
||||
{
|
||||
from: takerAddress,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
},
|
||||
@@ -254,6 +259,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
@@ -267,7 +273,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount.minus(filledTakerTokenAmount),
|
||||
takerAddress,
|
||||
normalizedTakerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
filledTakerTokenAmount = filledTakerTokenAmount.plus(singleFilledTakerTokenAmount);
|
||||
@@ -301,7 +307,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
rArray,
|
||||
sArray,
|
||||
{
|
||||
from: takerAddress,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
},
|
||||
@@ -345,6 +351,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
);
|
||||
assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
@@ -356,7 +363,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
exchangeTradeEmulator,
|
||||
orderFillRequest.signedOrder,
|
||||
orderFillRequest.takerTokenFillAmount,
|
||||
takerAddress,
|
||||
normalizedTakerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
@@ -389,7 +396,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
rArray,
|
||||
sArray,
|
||||
{
|
||||
from: takerAddress,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
},
|
||||
@@ -417,6 +424,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
|
||||
@@ -430,7 +438,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
normalizedTakerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
@@ -444,7 +452,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
signedOrder.ecSignature.r,
|
||||
signedOrder.ecSignature.s,
|
||||
{
|
||||
from: takerAddress,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
},
|
||||
@@ -476,6 +484,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
ExchangeContractErrs.BatchOrdersMustHaveSameExchangeAddress,
|
||||
);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
if (_.isEmpty(orderFillRequests)) {
|
||||
throw new Error(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem);
|
||||
}
|
||||
@@ -492,7 +501,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
exchangeTradeEmulator,
|
||||
orderFillRequest.signedOrder,
|
||||
orderFillRequest.takerTokenFillAmount,
|
||||
takerAddress,
|
||||
normalizedTakerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
@@ -520,7 +529,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
rParams,
|
||||
sParams,
|
||||
{
|
||||
from: takerAddress,
|
||||
from: normalizedTakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
},
|
||||
@@ -544,6 +553,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
assert.isValidBaseUnitAmount('takerTokenCancelAmount', cancelTakerTokenAmount);
|
||||
await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper);
|
||||
const normalizedMakerAddress = order.maker.toLowerCase();
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
|
||||
@@ -566,7 +576,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
orderValues,
|
||||
cancelTakerTokenAmount,
|
||||
{
|
||||
from: order.maker,
|
||||
from: normalizedMakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
},
|
||||
@@ -603,6 +613,8 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MultipleMakersInSingleCancelBatchDisallowed);
|
||||
const maker = makers[0];
|
||||
await assert.isSenderAddressAsync('maker', maker, this._web3Wrapper);
|
||||
const normalizedMakerAddress = maker.toLowerCase();
|
||||
|
||||
const shouldValidate = _.isUndefined(orderTransactionOpts.shouldValidate)
|
||||
? SHOULD_VALIDATE_BY_DEFAULT
|
||||
: orderTransactionOpts.shouldValidate;
|
||||
@@ -636,7 +648,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
orderValues,
|
||||
cancelTakerTokenAmounts,
|
||||
{
|
||||
from: maker,
|
||||
from: normalizedMakerAddress,
|
||||
gas: orderTransactionOpts.gasLimit,
|
||||
gasPrice: orderTransactionOpts.gasPrice,
|
||||
},
|
||||
@@ -679,7 +691,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public _unsubscribeAll(): void {
|
||||
public unsubscribeAll(): void {
|
||||
super._unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
@@ -757,13 +769,14 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
normalizedTakerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
@@ -803,13 +816,14 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
assert.isValidBaseUnitAmount('fillTakerTokenAmount', fillTakerTokenAmount);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
const normalizedTakerAddress = takerAddress.toLowerCase();
|
||||
const zrxTokenAddress = this.getZRXTokenAddress();
|
||||
const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest);
|
||||
await this._orderValidationUtils.validateFillOrKillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
takerAddress,
|
||||
normalizedTakerAddress,
|
||||
zrxTokenAddress,
|
||||
);
|
||||
}
|
||||
@@ -848,7 +862,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
});
|
||||
if (!_.isUndefined(errLog)) {
|
||||
const logArgs = (errLog as LogWithDecodedArgs<LogErrorContractEventArgs>).args;
|
||||
const errCode = logArgs.errorId.toNumber();
|
||||
const errCode = logArgs.errorId;
|
||||
const errMessage = this._exchangeContractErrCodesToMsg[errCode];
|
||||
throw new Error(errMessage);
|
||||
}
|
||||
@@ -862,7 +876,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
return contractAddress;
|
||||
}
|
||||
private _invalidateContractInstances(): void {
|
||||
this._unsubscribeAll();
|
||||
this.unsubscribeAll();
|
||||
delete this._exchangeContractIfExists;
|
||||
}
|
||||
private async _isValidSignatureUsingContractCallAsync(
|
||||
@@ -873,11 +887,12 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.isHexString('dataHex', dataHex);
|
||||
assert.doesConformToSchema('ecSignature', ecSignature, schemas.ecSignatureSchema);
|
||||
assert.isETHAddressHex('signerAddressHex', signerAddressHex);
|
||||
const normalizedSignerAddress = signerAddressHex.toLowerCase();
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
|
||||
const isValidSignature = await exchangeInstance.isValidSignature.callAsync(
|
||||
signerAddressHex,
|
||||
normalizedSignerAddress,
|
||||
dataHex,
|
||||
ecSignature.v,
|
||||
ecSignature.r,
|
||||
@@ -895,11 +910,11 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
if (!_.isUndefined(this._exchangeContractIfExists)) {
|
||||
return this._exchangeContractIfExists;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||
artifacts.ExchangeArtifact,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new ExchangeContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
||||
const contractInstance = new ExchangeContract(this._web3Wrapper, abi, address);
|
||||
this._exchangeContractIfExists = contractInstance;
|
||||
return this._exchangeContractIfExists;
|
||||
}
|
||||
|
@@ -1,6 +1 @@
|
||||
dummy_token.ts
|
||||
ether_token.ts
|
||||
exchange.ts
|
||||
token_registry.ts
|
||||
token_transfer_proxy.ts
|
||||
token.ts
|
||||
*
|
||||
|
@@ -1,33 +0,0 @@
|
||||
import {TxData, TxDataPayable} from '@0xproject/types';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export class BaseContract {
|
||||
protected _web3ContractInstance: Web3.ContractInstance;
|
||||
protected _defaults: Partial<TxData>;
|
||||
protected async _applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>(
|
||||
txData: T,
|
||||
estimateGasAsync?: (txData: T) => Promise<number>,
|
||||
): Promise<TxData> {
|
||||
// Gas amount sourced with the following priorities:
|
||||
// 1. Optional param passed in to public method call
|
||||
// 2. Global config passed in at library instantiation
|
||||
// 3. Gas estimate calculation + safety margin
|
||||
const removeUndefinedProperties = _.pickBy;
|
||||
const txDataWithDefaults = {
|
||||
...removeUndefinedProperties(this._defaults),
|
||||
...removeUndefinedProperties(txData as any),
|
||||
// HACK: TS can't prove that T is spreadable.
|
||||
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
|
||||
};
|
||||
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
|
||||
const estimatedGas = await estimateGasAsync(txData);
|
||||
txDataWithDefaults.gas = estimatedGas;
|
||||
}
|
||||
return txDataWithDefaults;
|
||||
}
|
||||
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
|
||||
this._web3ContractInstance = web3ContractInstance;
|
||||
this._defaults = defaults;
|
||||
}
|
||||
}
|
@@ -23,7 +23,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
address: metadata[0],
|
||||
name: metadata[1],
|
||||
symbol: metadata[2],
|
||||
decimals: metadata[3].toNumber(),
|
||||
decimals: metadata[3],
|
||||
};
|
||||
return token;
|
||||
}
|
||||
@@ -50,7 +50,8 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
public async getTokenAddressesAsync(): Promise<string[]> {
|
||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||
const addresses = await tokenRegistryContract.getTokenAddresses.callAsync();
|
||||
return addresses;
|
||||
const lowerCaseAddresses = _.map(addresses, address => address.toLowerCase());
|
||||
return lowerCaseAddresses;
|
||||
}
|
||||
/**
|
||||
* Retrieves a token by address currently listed in the Token Registry smart contract
|
||||
@@ -58,9 +59,10 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
*/
|
||||
public async getTokenIfExistsAsync(address: string): Promise<Token | undefined> {
|
||||
assert.isETHAddressHex('address', address);
|
||||
const normalizedAddress = address.toLowerCase();
|
||||
|
||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||
const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(address);
|
||||
const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(normalizedAddress);
|
||||
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
|
||||
return token;
|
||||
}
|
||||
@@ -115,14 +117,11 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
|
||||
return this._tokenRegistryContractIfExists;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||
artifacts.TokenRegistryArtifact,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new TokenRegistryContract(
|
||||
web3ContractInstance,
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const contractInstance = new TokenRegistryContract(this._web3Wrapper, abi, address);
|
||||
this._tokenRegistryContractIfExists = contractInstance;
|
||||
return this._tokenRegistryContractIfExists;
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from '../artifacts';
|
||||
import { assert } from '../utils/assert';
|
||||
|
||||
import { ContractWrapper } from './contract_wrapper';
|
||||
import { TokenTransferProxyContract } from './generated/token_transfer_proxy';
|
||||
@@ -22,8 +23,12 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
||||
* @return Whether the exchangeContractAddress is authorized.
|
||||
*/
|
||||
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
|
||||
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
|
||||
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
|
||||
const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
|
||||
const isAuthorized = await tokenTransferProxyContractInstance.authorized.callAsync(exchangeContractAddress);
|
||||
const isAuthorized = await tokenTransferProxyContractInstance.authorized.callAsync(
|
||||
normalizedExchangeContractAddress,
|
||||
);
|
||||
return isAuthorized;
|
||||
}
|
||||
/**
|
||||
@@ -54,14 +59,11 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
||||
if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
|
||||
return this._tokenTransferProxyContractIfExists;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||
artifacts.TokenTransferProxyArtifact,
|
||||
this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new TokenTransferProxyContract(
|
||||
web3ContractInstance,
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const contractInstance = new TokenTransferProxyContract(this._web3Wrapper, abi, address);
|
||||
this._tokenTransferProxyContractIfExists = contractInstance;
|
||||
return this._tokenTransferProxyContractIfExists;
|
||||
}
|
||||
|
@@ -46,10 +46,13 @@ export class TokenWrapper extends ContractWrapper {
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||
let balance = await tokenContract.balanceOf.callAsync(ownerAddress, defaultBlock);
|
||||
const txData = {};
|
||||
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, defaultBlock);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
balance = new BigNumber(balance);
|
||||
return balance;
|
||||
@@ -72,14 +75,17 @@ export class TokenWrapper extends ContractWrapper {
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
|
||||
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedSpenderAddress = spenderAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
||||
const txHash = await tokenContract.approve.sendTransactionAsync(spenderAddress, amountInBaseUnits, {
|
||||
from: ownerAddress,
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
const txHash = await tokenContract.approve.sendTransactionAsync(normalizedSpenderAddress, amountInBaseUnits, {
|
||||
from: normalizedOwnerAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
});
|
||||
@@ -103,10 +109,16 @@ export class TokenWrapper extends ContractWrapper {
|
||||
spenderAddress: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
const normalizedSpenderAddress = spenderAddress.toLowerCase();
|
||||
const txHash = await this.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
spenderAddress,
|
||||
normalizedTokenAddress,
|
||||
normalizedOwnerAddress,
|
||||
normalizedSpenderAddress,
|
||||
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
txOpts,
|
||||
);
|
||||
@@ -128,10 +140,20 @@ export class TokenWrapper extends ContractWrapper {
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('spenderAddress', spenderAddress);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
const normalizedSpenderAddress = spenderAddress.toLowerCase();
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
|
||||
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(ownerAddress, spenderAddress, defaultBlock);
|
||||
const txData = {};
|
||||
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
|
||||
normalizedOwnerAddress,
|
||||
normalizedSpenderAddress,
|
||||
txData,
|
||||
defaultBlock,
|
||||
);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
|
||||
return allowanceInBaseUnits;
|
||||
@@ -149,9 +171,16 @@ export class TokenWrapper extends ContractWrapper {
|
||||
): Promise<BigNumber> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
|
||||
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
|
||||
const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts);
|
||||
const allowanceInBaseUnits = await this.getAllowanceAsync(
|
||||
normalizedTokenAddress,
|
||||
normalizedOwnerAddress,
|
||||
proxyAddress,
|
||||
methodOpts,
|
||||
);
|
||||
return allowanceInBaseUnits;
|
||||
}
|
||||
/**
|
||||
@@ -172,12 +201,14 @@ export class TokenWrapper extends ContractWrapper {
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||
|
||||
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
|
||||
const txHash = await this.setAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
normalizedTokenAddress,
|
||||
normalizedOwnerAddress,
|
||||
proxyAddress,
|
||||
amountInBaseUnits,
|
||||
txOpts,
|
||||
@@ -200,9 +231,13 @@ export class TokenWrapper extends ContractWrapper {
|
||||
ownerAddress: string,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('ownerAddress', ownerAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedOwnerAddress = ownerAddress.toLowerCase();
|
||||
const txHash = await this.setProxyAllowanceAsync(
|
||||
tokenAddress,
|
||||
ownerAddress,
|
||||
normalizedTokenAddress,
|
||||
normalizedOwnerAddress,
|
||||
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
txOpts,
|
||||
);
|
||||
@@ -225,19 +260,22 @@ export class TokenWrapper extends ContractWrapper {
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
|
||||
assert.isETHAddressHex('toAddress', toAddress);
|
||||
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedFromAddress = fromAddress.toLowerCase();
|
||||
const normalizedToAddress = toAddress.toLowerCase();
|
||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const fromAddressBalance = await this.getBalanceAsync(tokenAddress, fromAddress);
|
||||
const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress);
|
||||
if (fromAddressBalance.lessThan(amountInBaseUnits)) {
|
||||
throw new Error(ZeroExError.InsufficientBalanceForTransfer);
|
||||
}
|
||||
|
||||
const txHash = await tokenContract.transfer.sendTransactionAsync(toAddress, amountInBaseUnits, {
|
||||
from: fromAddress,
|
||||
const txHash = await tokenContract.transfer.sendTransactionAsync(normalizedToAddress, amountInBaseUnits, {
|
||||
from: normalizedFromAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
});
|
||||
@@ -265,30 +303,38 @@ export class TokenWrapper extends ContractWrapper {
|
||||
amountInBaseUnits: BigNumber,
|
||||
txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.isETHAddressHex('fromAddress', fromAddress);
|
||||
assert.isETHAddressHex('toAddress', toAddress);
|
||||
assert.isETHAddressHex('fromAddress', fromAddress);
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
|
||||
const normalizedToAddress = toAddress.toLowerCase();
|
||||
const normalizedFromAddress = fromAddress.toLowerCase();
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
const normalizedSenderAddress = senderAddress.toLowerCase();
|
||||
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
|
||||
|
||||
const tokenContract = await this._getTokenContractAsync(tokenAddress);
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
|
||||
const fromAddressAllowance = await this.getAllowanceAsync(tokenAddress, fromAddress, senderAddress);
|
||||
const fromAddressAllowance = await this.getAllowanceAsync(
|
||||
normalizedTokenAddress,
|
||||
normalizedFromAddress,
|
||||
normalizedSenderAddress,
|
||||
);
|
||||
if (fromAddressAllowance.lessThan(amountInBaseUnits)) {
|
||||
throw new Error(ZeroExError.InsufficientAllowanceForTransfer);
|
||||
}
|
||||
|
||||
const fromAddressBalance = await this.getBalanceAsync(tokenAddress, fromAddress);
|
||||
const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress);
|
||||
if (fromAddressBalance.lessThan(amountInBaseUnits)) {
|
||||
throw new Error(ZeroExError.InsufficientBalanceForTransfer);
|
||||
}
|
||||
|
||||
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
|
||||
fromAddress,
|
||||
toAddress,
|
||||
normalizedFromAddress,
|
||||
normalizedToAddress,
|
||||
amountInBaseUnits,
|
||||
{
|
||||
from: senderAddress,
|
||||
from: normalizedSenderAddress,
|
||||
gas: txOpts.gasLimit,
|
||||
gasPrice: txOpts.gasPrice,
|
||||
},
|
||||
@@ -311,11 +357,12 @@ export class TokenWrapper extends ContractWrapper {
|
||||
callback: EventCallback<ArgsType>,
|
||||
): string {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const subscriptionToken = this._subscribe<ArgsType>(
|
||||
tokenAddress,
|
||||
normalizedTokenAddress,
|
||||
eventName,
|
||||
indexFilterValues,
|
||||
artifacts.TokenArtifact.abi,
|
||||
@@ -333,7 +380,7 @@ export class TokenWrapper extends ContractWrapper {
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public _unsubscribeAll(): void {
|
||||
public unsubscribeAll(): void {
|
||||
super._unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
@@ -352,11 +399,12 @@ export class TokenWrapper extends ContractWrapper {
|
||||
indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const logs = await this._getLogsAsync<ArgsType>(
|
||||
tokenAddress,
|
||||
normalizedTokenAddress,
|
||||
eventName,
|
||||
blockRange,
|
||||
indexFilterValues,
|
||||
@@ -365,21 +413,22 @@ export class TokenWrapper extends ContractWrapper {
|
||||
return logs;
|
||||
}
|
||||
private _invalidateContractInstances(): void {
|
||||
this._unsubscribeAll();
|
||||
this.unsubscribeAll();
|
||||
this._tokenContractsByAddress = {};
|
||||
}
|
||||
private async _getTokenContractAsync(tokenAddress: string): Promise<TokenContract> {
|
||||
let tokenContract = this._tokenContractsByAddress[tokenAddress];
|
||||
const normalizedTokenAddress = tokenAddress.toLowerCase();
|
||||
let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress];
|
||||
if (!_.isUndefined(tokenContract)) {
|
||||
return tokenContract;
|
||||
}
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
|
||||
artifacts.TokenArtifact,
|
||||
tokenAddress,
|
||||
normalizedTokenAddress,
|
||||
);
|
||||
const contractInstance = new TokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
||||
const contractInstance = new TokenContract(this._web3Wrapper, abi, address);
|
||||
tokenContract = contractInstance;
|
||||
this._tokenContractsByAddress[tokenAddress] = tokenContract;
|
||||
this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
|
||||
return tokenContract;
|
||||
}
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@ export {
|
||||
BlockParam,
|
||||
ContractEventArg,
|
||||
LogWithDecodedArgs,
|
||||
TransactionReceipt,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
} from '@0xproject/types';
|
||||
|
||||
@@ -58,5 +59,3 @@ export {
|
||||
ExchangeContractEventArgs,
|
||||
ExchangeEvents,
|
||||
} from './contract_wrappers/generated/exchange';
|
||||
|
||||
export { TransactionReceipt } from '@0xproject/types';
|
||||
|
@@ -1,27 +1,5 @@
|
||||
export const zeroExConfigSchema = {
|
||||
id: '/ZeroExConfig',
|
||||
properties: {
|
||||
networkId: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
gasPrice: { $ref: '/Number' },
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
tokenRegistryContractAddress: { $ref: '/Address' },
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
pollingIntervalMs: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
numConfirmations: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
oneOf: [{ $ref: '/ZeroExPrivateNetworkConfig' }, { $ref: '/ZeroExPublicNetworkConfig' }],
|
||||
type: 'object',
|
||||
required: ['networkId'],
|
||||
};
|
||||
|
@@ -0,0 +1,35 @@
|
||||
export const zeroExPrivateNetworkConfigSchema = {
|
||||
id: '/ZeroExPrivateNetworkConfig',
|
||||
properties: {
|
||||
networkId: {
|
||||
type: 'number',
|
||||
minimum: 1,
|
||||
},
|
||||
gasPrice: { $ref: '/Number' },
|
||||
zrxContractAddress: { $ref: '/Address' },
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
tokenRegistryContractAddress: { $ref: '/Address' },
|
||||
tokenTransferProxyContractAddress: { $ref: '/Address' },
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
pollingIntervalMs: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
numConfirmations: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'object',
|
||||
required: [
|
||||
'networkId',
|
||||
'zrxContractAddress',
|
||||
'exchangeContractAddress',
|
||||
'tokenRegistryContractAddress',
|
||||
'tokenTransferProxyContractAddress',
|
||||
],
|
||||
};
|
@@ -0,0 +1,29 @@
|
||||
export const zeroExPublicNetworkConfigSchema = {
|
||||
id: '/ZeroExPublicNetworkConfig',
|
||||
properties: {
|
||||
networkId: {
|
||||
type: 'number',
|
||||
enum: [1, 3, 4, 42, 50],
|
||||
},
|
||||
gasPrice: { $ref: '/Number' },
|
||||
zrxContractAddress: { $ref: '/Address' },
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
tokenRegistryContractAddress: { $ref: '/Address' },
|
||||
tokenTransferProxyContractAddress: { $ref: '/Address' },
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
pollingIntervalMs: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
numConfirmations: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'object',
|
||||
required: ['networkId'],
|
||||
};
|
@@ -127,7 +127,7 @@ export interface SignedOrder extends Order {
|
||||
}
|
||||
|
||||
// [address, name, symbol, decimals, ipfsHash, swarmHash]
|
||||
export type TokenMetadata = [string, string, string, BigNumber, string, string];
|
||||
export type TokenMetadata = [string, string, string, number, string, string];
|
||||
|
||||
export interface Token {
|
||||
name: string;
|
||||
@@ -196,7 +196,7 @@ export interface OrderStateWatcherConfig {
|
||||
}
|
||||
|
||||
/*
|
||||
* networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 42-kovan, 50-testrpc)
|
||||
* networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 3-ropsten, 4-rinkeby, 42-kovan, 50-testrpc)
|
||||
* gasPrice: Gas price to use with every transaction
|
||||
* exchangeContractAddress: The address of an exchange contract to use
|
||||
* zrxContractAddress: The address of the ZRX contract to use
|
||||
|
@@ -75,11 +75,14 @@ describe('EtherTokenWrapper', () => {
|
||||
const contractAddressIfExists = zeroEx.etherToken.getContractAddressIfExists();
|
||||
expect(contractAddressIfExists).to.not.be.undefined();
|
||||
});
|
||||
it('should return undefined if connected to an unknown network', () => {
|
||||
it('should throw if connected to a private network and contract addresses are not specified', () => {
|
||||
const UNKNOWN_NETWORK_NETWORK_ID = 10;
|
||||
const unknownNetworkZeroEx = new ZeroEx(web3.currentProvider, { networkId: UNKNOWN_NETWORK_NETWORK_ID });
|
||||
const contractAddressIfExists = unknownNetworkZeroEx.etherToken.getContractAddressIfExists();
|
||||
expect(contractAddressIfExists).to.be.undefined();
|
||||
expect(
|
||||
() =>
|
||||
new ZeroEx(web3.currentProvider, {
|
||||
networkId: UNKNOWN_NETWORK_NETWORK_ID,
|
||||
} as any),
|
||||
).to.throw();
|
||||
});
|
||||
});
|
||||
describe('#depositAsync', () => {
|
||||
@@ -155,7 +158,7 @@ describe('EtherTokenWrapper', () => {
|
||||
etherTokenAddress = etherToken.address;
|
||||
});
|
||||
afterEach(() => {
|
||||
zeroEx.etherToken._unsubscribeAll();
|
||||
zeroEx.etherToken.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
|
@@ -922,7 +922,7 @@ describe('ExchangeWrapper', () => {
|
||||
);
|
||||
});
|
||||
afterEach(async () => {
|
||||
zeroEx.exchange._unsubscribeAll();
|
||||
zeroEx.exchange.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
|
@@ -9,10 +9,10 @@ import * as Web3 from 'web3';
|
||||
import { ZeroEx } from '../src/0x';
|
||||
import { ExpirationWatcher } from '../src/order_watcher/expiration_watcher';
|
||||
import { DoneCallback, Token } from '../src/types';
|
||||
import { constants } from '../src/utils/constants';
|
||||
import { utils } from '../src/utils/utils';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { constants } from './utils/constants';
|
||||
import { FillScenarios } from './utils/fill_scenarios';
|
||||
import { reportNoErrorCallbackErrors } from './utils/report_callback_errors';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
|
@@ -49,7 +49,7 @@ describe('SubscriptionTest', () => {
|
||||
tokenAddress = token.address;
|
||||
});
|
||||
afterEach(() => {
|
||||
zeroEx.token._unsubscribeAll();
|
||||
zeroEx.token.unsubscribeAll();
|
||||
_.each(stubs, s => s.restore());
|
||||
stubs = [];
|
||||
});
|
||||
@@ -76,7 +76,7 @@ describe('SubscriptionTest', () => {
|
||||
const callback = (err: Error | null, logEvent?: DecodedLogEvent<ApprovalContractEventArgs>) => _.noop;
|
||||
zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
|
||||
stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error('JSON RPC error'))];
|
||||
zeroEx.token._unsubscribeAll();
|
||||
zeroEx.token.unsubscribeAll();
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
|
@@ -377,7 +377,7 @@ describe('TokenWrapper', () => {
|
||||
tokenAddress = token.address;
|
||||
});
|
||||
afterEach(() => {
|
||||
zeroEx.token._unsubscribeAll();
|
||||
zeroEx.token.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
|
@@ -35,12 +35,8 @@ export class FillScenarios {
|
||||
const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper;
|
||||
for (const token of this._tokens) {
|
||||
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
|
||||
const contractInstance = web3Wrapper.getContractInstance(
|
||||
artifacts.DummyTokenArtifact.abi,
|
||||
token.address,
|
||||
);
|
||||
const defaults = {};
|
||||
const dummyToken = new DummyTokenContract(contractInstance, defaults);
|
||||
const dummyToken = new DummyTokenContract(web3Wrapper, artifacts.DummyTokenArtifact.abi, token.address);
|
||||
const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
|
||||
const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, {
|
||||
from: this._coinbase,
|
||||
|
@@ -9,6 +9,7 @@
|
||||
"./test/**/*",
|
||||
"../../node_modules/types-bn/index.d.ts",
|
||||
"../../node_modules/types-ethereumjs-util/index.d.ts",
|
||||
"../../node_modules/ethers-typescript-typings/index.d.ts",
|
||||
"../../node_modules/web3-typescript-typings/index.d.ts",
|
||||
"../../node_modules/chai-typescript-typings/index.d.ts",
|
||||
"../../node_modules/chai-as-promised-typescript-typings/index.d.ts"
|
||||
|
@@ -1,5 +1,11 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.2.4 - _March 4, 2018_
|
||||
|
||||
* Add a `backend` parameter that allows you to specify the Ethereum library you use in your templates (`web3` or `ethers`). Ethers auto-converts small ints to numbers whereas Web3 doesn't. Defaults to `web3` (#413)
|
||||
* Add support for [tuple types](https://solidity.readthedocs.io/en/develop/abi-spec.html#handling-tuple-types) (#413)
|
||||
* Add `hasReturnValue` to context data (#413)
|
||||
|
||||
## v0.2.1 - _February 9, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
@@ -4,8 +4,8 @@ This package allows you to generate TypeScript contract wrappers from ABI files.
|
||||
It's heavily inspired by [Geth abigen](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) but takes a different approach.
|
||||
You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions.
|
||||
|
||||
For an example of the generated [wrapper files](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/src/contract_wrappers/generated) check out 0x.js.
|
||||
[Here](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files.
|
||||
For an example of the generated [wrapper files](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/src/contract_wrappers/generated) check out 0x.js.
|
||||
[Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -36,14 +36,14 @@ The abi file should be either a [Truffle](http://truffleframework.com/) contract
|
||||
|
||||
## How to write custom templates?
|
||||
|
||||
The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates) and start adjusting them for your needs.
|
||||
The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) and start adjusting them for your needs.
|
||||
We use [handlebars](http://handlebarsjs.com/) template engine under the hood.
|
||||
You need to have a master template called `contract.mustache`. it will be used to generate each contract wrapper. Although - you don't need and probably shouldn't write all your logic in a single template file. You can write [partial templates](http://handlebarsjs.com/partials.html) and as long as they are within a partials folder - they will be registered and available.
|
||||
|
||||
## Which data/context do I get in my templates?
|
||||
|
||||
For now you don't get much on top of methods abi, some useful helpers and a contract name because it was enough for our use-case, but if you need something else - create a PR.
|
||||
See the [type definition](https://github.com/0xProject/0x.js/tree/development/packages/abi-gen/src/types.ts) of what we pass to the render method.
|
||||
See the [type definition](https://github.com/0xProject/0x-monorepo/tree/development/packages/abi-gen/src/types.ts) of what we pass to the render method.
|
||||
|
||||
## Output files
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/abi-gen",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.5",
|
||||
"description": "Generate contract wrappers from ABI and handlebars templates",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
@@ -15,15 +15,15 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x.js.git"
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x.js/issues"
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/abi-gen/README.md",
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
|
||||
"dependencies": {
|
||||
"@0xproject/utils": "^0.3.2",
|
||||
"@0xproject/utils": "^0.4.1",
|
||||
"chalk": "^2.3.0",
|
||||
"glob": "^7.1.2",
|
||||
"handlebars": "^4.0.11",
|
||||
@@ -34,7 +34,7 @@
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.4.8",
|
||||
"@0xproject/tslint-config": "^0.4.10",
|
||||
"@types/glob": "^5.0.33",
|
||||
"@types/handlebars": "^4.0.36",
|
||||
"@types/mkdirp": "^0.5.1",
|
||||
@@ -44,6 +44,6 @@
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "2.7.1",
|
||||
"web3-typescript-typings": "^0.9.10"
|
||||
"web3-typescript-typings": "^0.10.0"
|
||||
}
|
||||
}
|
||||
|
@@ -11,13 +11,14 @@ import * as yargs from 'yargs';
|
||||
import toSnakeCase = require('to-snake-case');
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import { ContextData, ParamKind } from './types';
|
||||
import { ContextData, ContractsBackend, ParamKind } from './types';
|
||||
import { utils } from './utils';
|
||||
|
||||
const ABI_TYPE_CONSTRUCTOR = 'constructor';
|
||||
const ABI_TYPE_METHOD = 'function';
|
||||
const ABI_TYPE_EVENT = 'event';
|
||||
const DEFAULT_NETWORK_ID = 50;
|
||||
const DEFAULT_BACKEND = 'web3';
|
||||
|
||||
const args = yargs
|
||||
.option('abis', {
|
||||
@@ -43,6 +44,12 @@ const args = yargs
|
||||
demandOption: true,
|
||||
normalize: true,
|
||||
})
|
||||
.option('backend', {
|
||||
describe: `The backing Ethereum library your app uses. Either 'web3' or 'ethers'. Ethers auto-converts small ints to numbers whereas Web3 doesn't.`,
|
||||
type: 'string',
|
||||
choices: [ContractsBackend.Web3, ContractsBackend.Ethers],
|
||||
default: DEFAULT_BACKEND,
|
||||
})
|
||||
.option('network-id', {
|
||||
describe: 'ID of the network where contract ABIs are nested in artifacts',
|
||||
type: 'number',
|
||||
@@ -73,8 +80,8 @@ function writeOutputFile(name: string, renderedTsCode: string): void {
|
||||
utils.log(`Created: ${chalk.bold(filePath)}`);
|
||||
}
|
||||
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output));
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
|
||||
|
||||
if (args.partials) {
|
||||
registerPartials(args.partials);
|
||||
@@ -129,6 +136,7 @@ for (const abiFileName of abiFileNames) {
|
||||
const methodData = {
|
||||
...methodAbi,
|
||||
singleReturnValue: methodAbi.outputs.length === 1,
|
||||
hasReturnValue: methodAbi.outputs.length !== 0,
|
||||
};
|
||||
return methodData;
|
||||
});
|
||||
|
@@ -12,8 +12,14 @@ export enum AbiType {
|
||||
Fallback = 'fallback',
|
||||
}
|
||||
|
||||
export enum ContractsBackend {
|
||||
Web3 = 'web3',
|
||||
Ethers = 'ethers',
|
||||
}
|
||||
|
||||
export interface Method extends Web3.MethodAbi {
|
||||
singleReturnValue: boolean;
|
||||
hasReturnValue: boolean;
|
||||
}
|
||||
|
||||
export interface ContextData {
|
||||
|
@@ -3,17 +3,23 @@ import * as _ from 'lodash';
|
||||
import * as path from 'path';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import { AbiType, ParamKind } from './types';
|
||||
import { AbiType, ContractsBackend, ParamKind } from './types';
|
||||
|
||||
export const utils = {
|
||||
solTypeToTsType(paramKind: ParamKind, solType: string): string {
|
||||
solTypeToTsType(
|
||||
paramKind: ParamKind,
|
||||
backend: ContractsBackend,
|
||||
solType: string,
|
||||
components?: Web3.DataItem[],
|
||||
): string {
|
||||
const trailingArrayRegex = /\[\d*\]$/;
|
||||
if (solType.match(trailingArrayRegex)) {
|
||||
const arrayItemSolType = solType.replace(trailingArrayRegex, '');
|
||||
const arrayItemTsType = utils.solTypeToTsType(paramKind, arrayItemSolType);
|
||||
const arrayTsType = utils.isUnionType(arrayItemTsType)
|
||||
? `Array<${arrayItemTsType}>`
|
||||
: `${arrayItemTsType}[]`;
|
||||
const arrayItemTsType = utils.solTypeToTsType(paramKind, backend, arrayItemSolType, components);
|
||||
const arrayTsType =
|
||||
utils.isUnionType(arrayItemTsType) || utils.isObjectType(arrayItemTsType)
|
||||
? `Array<${arrayItemTsType}>`
|
||||
: `${arrayItemTsType}[]`;
|
||||
return arrayTsType;
|
||||
} else {
|
||||
const solTypeRegexToTsType = [
|
||||
@@ -24,25 +30,49 @@ export const utils = {
|
||||
{ regex: '^bytes\\d*$', tsType: 'string' },
|
||||
];
|
||||
if (paramKind === ParamKind.Input) {
|
||||
// web3 allows to pass those an non-bignumbers and that's nice
|
||||
// but it always returns stuff as BigNumbers
|
||||
// web3 and ethers allow to pass those as numbers instead of bignumbers
|
||||
solTypeRegexToTsType.unshift({
|
||||
regex: '^u?int(8|16|32)?$',
|
||||
tsType: 'number|BigNumber',
|
||||
});
|
||||
}
|
||||
if (backend === ContractsBackend.Ethers && paramKind === ParamKind.Output) {
|
||||
// ethers-contracts automatically converts small BigNumbers to numbers
|
||||
solTypeRegexToTsType.unshift({
|
||||
regex: '^u?int(8|16|32|48)?$',
|
||||
tsType: 'number',
|
||||
});
|
||||
}
|
||||
for (const regexAndTxType of solTypeRegexToTsType) {
|
||||
const { regex, tsType } = regexAndTxType;
|
||||
if (solType.match(regex)) {
|
||||
return tsType;
|
||||
}
|
||||
}
|
||||
const TUPLE_TYPE_REGEX = '^tuple$';
|
||||
if (solType.match(TUPLE_TYPE_REGEX)) {
|
||||
const componentsType = _.map(components, component => {
|
||||
const componentValueType = utils.solTypeToTsType(
|
||||
paramKind,
|
||||
backend,
|
||||
component.type,
|
||||
component.components,
|
||||
);
|
||||
const componentType = `${component.name}: ${componentValueType}`;
|
||||
return componentType;
|
||||
});
|
||||
const tsType = `{${componentsType}}`;
|
||||
return tsType;
|
||||
}
|
||||
throw new Error(`Unknown Solidity type found: ${solType}`);
|
||||
}
|
||||
},
|
||||
isUnionType(tsType: string): boolean {
|
||||
return tsType === 'number|BigNumber';
|
||||
},
|
||||
isObjectType(tsType: string): boolean {
|
||||
return /^{.*}$/.test(tsType);
|
||||
},
|
||||
log(...args: any[]): void {
|
||||
console.log(...args); // tslint:disable-line:no-console
|
||||
},
|
||||
|
@@ -1,5 +1,14 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.2.0 - _March 8, 2018_
|
||||
|
||||
* Rename `isHttpUrl` to `isWebUri` (#412)
|
||||
|
||||
## v0.1.0 - _March 4, 2018_
|
||||
|
||||
* Remove isETHAddressHex checksum address check and assume address will be lowercased (#373)
|
||||
* Add an optional parameter `subSchemas` to `doesConformToSchema` method (#385)
|
||||
|
||||
## v0.0.18 - _February 9, 2017_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
@@ -8,6 +8,14 @@ Standard type and schema assertions to be used across all 0x projects and packag
|
||||
yarn add @0xproject/assert
|
||||
```
|
||||
|
||||
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
|
||||
|
||||
```
|
||||
"include": [
|
||||
"./node_modules/web3-typescript-typings/index.d.ts",
|
||||
]
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/assert",
|
||||
"version": "0.0.18",
|
||||
"version": "0.2.0",
|
||||
"description": "Provides a standard way of performing type and schema validation across 0x projects",
|
||||
"main": "lib/src/index.js",
|
||||
"types": "lib/src/index.d.ts",
|
||||
@@ -17,19 +17,19 @@
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x.js.git"
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x.js/issues"
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/assert/README.md",
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.4.8",
|
||||
"@0xproject/tslint-config": "^0.4.10",
|
||||
"@types/lodash": "^4.14.86",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/valid-url": "^1.0.2",
|
||||
"chai": "^4.0.1",
|
||||
"chai-typescript-typings": "^0.0.3",
|
||||
"chai-typescript-typings": "^0.0.4",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"mocha": "^4.0.1",
|
||||
"npm-run-all": "^4.1.2",
|
||||
@@ -38,8 +38,8 @@
|
||||
"typescript": "2.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/json-schemas": "^0.7.10",
|
||||
"@0xproject/utils": "^0.3.2",
|
||||
"@0xproject/json-schemas": "^0.7.14",
|
||||
"@0xproject/utils": "^0.4.1",
|
||||
"lodash": "^4.17.4",
|
||||
"valid-url": "^1.0.9"
|
||||
}
|
||||
|
@@ -33,11 +33,8 @@ export const assert = {
|
||||
);
|
||||
},
|
||||
isETHAddressHex(variableName: string, value: string): void {
|
||||
this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value));
|
||||
this.assert(addressUtils.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value));
|
||||
this.assert(
|
||||
addressUtils.isAddress(value) && value.toLowerCase() === value,
|
||||
`Checksummed addresses are not supported. Convert ${variableName} to lower case before passing`,
|
||||
);
|
||||
},
|
||||
doesBelongToStringEnum(
|
||||
variableName: string,
|
||||
@@ -66,8 +63,11 @@ export const assert = {
|
||||
const isWeb3Provider = _.isFunction(value.send) || _.isFunction(value.sendAsync);
|
||||
this.assert(isWeb3Provider, this.typeAssertionMessage(variableName, 'Web3.Provider', value));
|
||||
},
|
||||
doesConformToSchema(variableName: string, value: any, schema: Schema): void {
|
||||
doesConformToSchema(variableName: string, value: any, schema: Schema, subSchemas?: Schema[]): void {
|
||||
const schemaValidator = new SchemaValidator();
|
||||
if (!_.isUndefined(subSchemas)) {
|
||||
_.map(subSchemas, schemaValidator.addSchema.bind(schemaValidator));
|
||||
}
|
||||
const validationResult = schemaValidator.validate(value, schema);
|
||||
const hasValidationErrors = validationResult.errors.length > 0;
|
||||
const msg = `Expected ${variableName} to conform to schema ${schema.id}
|
||||
@@ -75,9 +75,9 @@ Encountered: ${JSON.stringify(value, null, '\t')}
|
||||
Validation errors: ${validationResult.errors.join(', ')}`;
|
||||
this.assert(!hasValidationErrors, msg);
|
||||
},
|
||||
isHttpUrl(variableName: string, value: any): void {
|
||||
isWebUri(variableName: string, value: any): void {
|
||||
const isValidUrl = !_.isUndefined(validUrl.isWebUri(value));
|
||||
this.assert(isValidUrl, this.typeAssertionMessage(variableName, 'http url', value));
|
||||
this.assert(isValidUrl, this.typeAssertionMessage(variableName, 'web uri', value));
|
||||
},
|
||||
isUri(variableName: string, value: any): void {
|
||||
const isValidUri = !_.isUndefined(validUrl.isUri(value));
|
||||
|
@@ -183,7 +183,7 @@ describe('Assertions', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('#isHttpUrl', () => {
|
||||
describe('#isWebUri', () => {
|
||||
it('should not throw for valid input', () => {
|
||||
const validInputs = [
|
||||
'http://www.google.com',
|
||||
@@ -191,7 +191,7 @@ describe('Assertions', () => {
|
||||
'https://api.radarrelay.com/0x/v0/',
|
||||
'https://zeroex.beta.radarrelay.com:8000/0x/v0/',
|
||||
];
|
||||
validInputs.forEach(input => expect(assert.isHttpUrl.bind(assert, variableName, input)).to.not.throw());
|
||||
validInputs.forEach(input => expect(assert.isWebUri.bind(assert, variableName, input)).to.not.throw());
|
||||
});
|
||||
it('should throw for invalid input', () => {
|
||||
const invalidInputs = [
|
||||
@@ -205,7 +205,7 @@ describe('Assertions', () => {
|
||||
'user:password@api.example-relayer.net',
|
||||
'//api.example-relayer.net',
|
||||
];
|
||||
invalidInputs.forEach(input => expect(assert.isHttpUrl.bind(assert, variableName, input)).to.throw());
|
||||
invalidInputs.forEach(input => expect(assert.isWebUri.bind(assert, variableName, input)).to.throw());
|
||||
});
|
||||
});
|
||||
describe('#isUri', () => {
|
||||
|
5
packages/base-contract/.npmignore
Normal file
5
packages/base-contract/.npmignore
Normal file
@@ -0,0 +1,5 @@
|
||||
.*
|
||||
yarn-error.log
|
||||
/scripts/
|
||||
/src/
|
||||
tsconfig.json
|
5
packages/base-contract/CHANGELOG.md
Normal file
5
packages/base-contract/CHANGELOG.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.0.2 - _March 4, 2018_
|
||||
|
||||
* Initial release
|
62
packages/base-contract/README.md
Normal file
62
packages/base-contract/README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
## @0xproject/base-contract
|
||||
|
||||
BaseContract to derive all auto-generated wrappers from
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
yarn add @0xproject/base-contract
|
||||
```
|
||||
|
||||
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
|
||||
|
||||
```
|
||||
"include": [
|
||||
"./node_modules/web3-typescript-typings/index.d.ts",
|
||||
"./node_modules/ethers-typescript-typings/index.d.ts"
|
||||
]
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
import { BaseContract } from '@0xproject/base-contract';
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
yarn build:watch
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
39
packages/base-contract/package.json
Normal file
39
packages/base-contract/package.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "@0xproject/base-contract",
|
||||
"version": "0.0.3",
|
||||
"description": "0x Base TS contract",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"build:watch": "tsc -w",
|
||||
"build": "tsc",
|
||||
"clean": "shx rm -rf lib",
|
||||
"lint": "tslint --project . 'src/**/*.ts'"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.4.10",
|
||||
"@types/lodash": "^4.14.86",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "2.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/types": "^0.3.1",
|
||||
"@0xproject/web3-wrapper": "^0.2.1",
|
||||
"ethers-contracts": "^2.2.1",
|
||||
"ethers-typescript-typings": "^0.0.2",
|
||||
"lodash": "^4.17.4",
|
||||
"web3": "^0.20.0",
|
||||
"web3-typescript-typings": "^0.10.0"
|
||||
}
|
||||
}
|
68
packages/base-contract/src/index.ts
Normal file
68
packages/base-contract/src/index.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { TxData, TxDataPayable } from '@0xproject/types';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as ethersContracts from 'ethers-contracts';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export class BaseContract {
|
||||
protected _ethersInterface: ethersContracts.Interface;
|
||||
protected _web3Wrapper: Web3Wrapper;
|
||||
public abi: Web3.ContractAbi;
|
||||
public address: string;
|
||||
protected static _transformABIData(
|
||||
abis: Web3.DataItem[],
|
||||
values: any[],
|
||||
transformation: (type: string, value: any) => any,
|
||||
): any {
|
||||
return _.map(values, (value: any, i: number) =>
|
||||
BaseContract._transformTypedData(abis[i].type, value, transformation),
|
||||
);
|
||||
}
|
||||
protected static _lowercaseAddress(type: string, value: string): string {
|
||||
return type === 'address' ? value.toLowerCase() : value;
|
||||
}
|
||||
protected static _bigNumberToString(type: string, value: string): string {
|
||||
return _.isObject(value) && (value as any).isBigNumber ? value.toString() : value;
|
||||
}
|
||||
private static _transformTypedData(
|
||||
type: string,
|
||||
values: any,
|
||||
transformation: (type: string, value: any) => any,
|
||||
): any {
|
||||
const trailingArrayRegex = /\[\d*\]$/;
|
||||
if (type.match(trailingArrayRegex)) {
|
||||
const arrayItemType = type.replace(trailingArrayRegex, '');
|
||||
return _.map(values, value => this._transformTypedData(arrayItemType, value, transformation));
|
||||
} else {
|
||||
return transformation(type, values);
|
||||
}
|
||||
}
|
||||
protected async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>(
|
||||
txData: T,
|
||||
estimateGasAsync?: (txData: T) => Promise<number>,
|
||||
): Promise<TxData> {
|
||||
// Gas amount sourced with the following priorities:
|
||||
// 1. Optional param passed in to public method call
|
||||
// 2. Global config passed in at library instantiation
|
||||
// 3. Gas estimate calculation + safety margin
|
||||
const removeUndefinedProperties = _.pickBy;
|
||||
const txDataWithDefaults = {
|
||||
to: this.address,
|
||||
...removeUndefinedProperties(this._web3Wrapper.getContractDefaults()),
|
||||
...removeUndefinedProperties(txData as any),
|
||||
// HACK: TS can't prove that T is spreadable.
|
||||
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
|
||||
};
|
||||
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
|
||||
const estimatedGas = await estimateGasAsync(txData);
|
||||
txDataWithDefaults.gas = estimatedGas;
|
||||
}
|
||||
return txDataWithDefaults;
|
||||
}
|
||||
constructor(web3Wrapper: Web3Wrapper, abi: Web3.ContractAbi, address: string) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this.abi = abi;
|
||||
this.address = address;
|
||||
this._ethersInterface = new ethersContracts.Interface(abi);
|
||||
}
|
||||
}
|
11
packages/base-contract/tsconfig.json
Normal file
11
packages/base-contract/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*",
|
||||
"../../node_modules/web3-typescript-typings/index.d.ts",
|
||||
"../../node_modules/ethers-typescript-typings/index.d.ts"
|
||||
]
|
||||
}
|
3
packages/base-contract/tslint.json
Normal file
3
packages/base-contract/tslint.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": ["@0xproject/tslint-config"]
|
||||
}
|
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "chai-as-promised-typescript-typings",
|
||||
"version": "0.0.9",
|
||||
"version": "0.0.10",
|
||||
"description": "Typescript type definitions for chai-as-promised",
|
||||
"main": "index.d.ts",
|
||||
"types": "index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/0xProject/0x.js.git"
|
||||
"url": "git+https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"author": "Fabio Berger",
|
||||
"contributors": [
|
||||
@@ -14,10 +14,10 @@
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x.js/issues"
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/chai-as-promised-typescript-typings#readme",
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/chai-as-promised-typescript-typings#readme",
|
||||
"dependencies": {
|
||||
"chai-typescript-typings": "^0.0.3"
|
||||
"chai-typescript-typings": "^0.0.4"
|
||||
}
|
||||
}
|
||||
|
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "chai-typescript-typings",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"description": "Typescript type definitions for chai",
|
||||
"main": "index.d.ts",
|
||||
"types": "index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/0xProject/0x.js.git"
|
||||
"url": "git+https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x.js/issues"
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/chai-typescript-typings#readme"
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/chai-typescript-typings#readme"
|
||||
}
|
||||
|
@@ -1,5 +1,14 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v0.6.2 - _February 16, 2018_
|
||||
|
||||
* Fix JSON parse empty response (#407)
|
||||
|
||||
## v0.6.0 - _February 16, 2018_
|
||||
|
||||
* Add pagination options to HttpClient methods (#393)
|
||||
* Add heartbeat configuration to WebSocketOrderbookChannel constructor (#406)
|
||||
|
||||
## v0.5.7 - _February 9, 2018_
|
||||
|
||||
* Fix publishing issue where .npmignore was not properly excluding undesired content (#389)
|
||||
|
@@ -8,10 +8,18 @@ This repository contains a Javascript library that makes it easy to interact wit
|
||||
yarn add @0xproject/connect
|
||||
```
|
||||
|
||||
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
|
||||
|
||||
```
|
||||
"include": [
|
||||
"./node_modules/web3-typescript-typings/index.d.ts",
|
||||
]
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
* [Docs](https://0xproject.com/docs/connect)
|
||||
* [Tutorials](https://0xproject.com/wiki#connect)
|
||||
* [Docs](https://0xproject.com/docs/connect)
|
||||
* [Tutorials](https://0xproject.com/wiki#connect)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/connect",
|
||||
"version": "0.5.7",
|
||||
"version": "0.6.3",
|
||||
"description": "A javascript library for interacting with the standard relayer api",
|
||||
"keywords": [
|
||||
"connect",
|
||||
@@ -15,7 +15,7 @@
|
||||
"build:watch": "tsc -w",
|
||||
"build": "tsc",
|
||||
"clean": "shx rm -rf _bundles lib test_temp",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
|
||||
"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",
|
||||
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
|
||||
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x.js.git"
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"author": "Brandon Millman",
|
||||
"license": "Apache-2.0",
|
||||
@@ -33,20 +33,20 @@
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x.js/issues"
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/connect/README.md",
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^0.0.18",
|
||||
"@0xproject/json-schemas": "^0.7.10",
|
||||
"@0xproject/utils": "^0.3.2",
|
||||
"@0xproject/assert": "^0.2.0",
|
||||
"@0xproject/json-schemas": "^0.7.14",
|
||||
"@0xproject/utils": "^0.4.1",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"lodash": "^4.17.4",
|
||||
"query-string": "^5.0.1",
|
||||
"websocket": "^1.0.25"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.4.8",
|
||||
"@0xproject/tslint-config": "^0.4.10",
|
||||
"@types/fetch-mock": "^5.12.1",
|
||||
"@types/lodash": "^4.14.86",
|
||||
"@types/mocha": "^2.2.42",
|
||||
@@ -54,8 +54,8 @@
|
||||
"@types/websocket": "^0.0.34",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-as-promised-typescript-typings": "^0.0.9",
|
||||
"chai-typescript-typings": "^0.0.3",
|
||||
"chai-as-promised-typescript-typings": "^0.0.10",
|
||||
"chai-typescript-typings": "^0.0.4",
|
||||
"copyfiles": "^1.2.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"fetch-mock": "^5.13.1",
|
||||
@@ -65,6 +65,6 @@
|
||||
"tslint": "5.8.0",
|
||||
"typedoc": "~0.8.0",
|
||||
"typescript": "2.7.1",
|
||||
"web3-typescript-typings": "^0.9.10"
|
||||
"web3-typescript-typings": "^0.10.0"
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,16 @@
|
||||
const execAsync = require('async-child-process').execAsync;
|
||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
|
||||
const packageJSON = require('../package.json');
|
||||
const tsConfig = require('../tsconfig.json');
|
||||
|
||||
const cwd = __dirname + '/..';
|
||||
const subPackageName = packageJSON.name;
|
||||
const S3BucketPath = 's3://connect-docs-jsons/';
|
||||
// Include any external packages that are part of the @0xproject/connect public interface
|
||||
// to this array so that TypeDoc picks it up and adds it to the Docs JSON
|
||||
const fileIncludes = [...tsConfig.include];
|
||||
const fileIncludesAdjusted = postpublish_utils.adjustFileIncludePaths(fileIncludes, __dirname);
|
||||
const projectFiles = fileIncludesAdjusted.join(' ');
|
||||
|
||||
let tag;
|
||||
let version;
|
||||
@@ -14,12 +20,12 @@ postpublish_utils
|
||||
tag = result.tag;
|
||||
version = result.version;
|
||||
const releaseName = postpublish_utils.getReleaseName(subPackageName, version);
|
||||
return postpublish_utils.publishReleaseNotes(tag, releaseName);
|
||||
return postpublish_utils.publishReleaseNotesAsync(tag, releaseName);
|
||||
})
|
||||
.then(function(release) {
|
||||
console.log('POSTPUBLISH: Release successful, generating docs...');
|
||||
const jsonFilePath = __dirname + '/../' + postpublish_utils.generatedDocsDirectoryName + '/index.json';
|
||||
return execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_DIR=' + __dirname + '/.. yarn docs:json', {
|
||||
return execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_FILES="' + projectFiles + '" yarn docs:json', {
|
||||
cwd,
|
||||
});
|
||||
})
|
||||
|
30
packages/connect/scripts/stagedocs.js
Normal file
30
packages/connect/scripts/stagedocs.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const execAsync = require('async-child-process').execAsync;
|
||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
|
||||
const tsConfig = require('../tsconfig.json');
|
||||
|
||||
const cwd = __dirname + '/..';
|
||||
const S3BucketPath = 's3://staging-connect-docs-jsons/';
|
||||
const jsonFilePath = __dirname + '/../' + postpublish_utils.generatedDocsDirectoryName + '/index.json';
|
||||
const version = process.env.DOCS_VERSION;
|
||||
// Include any external packages that are part of the @0xproject/connect public interface
|
||||
// to this array so that TypeDoc picks it up and adds it to the Docs JSON
|
||||
const fileIncludes = [...tsConfig.include];
|
||||
const fileIncludesAdjusted = postpublish_utils.adjustFileIncludePaths(fileIncludes, __dirname);
|
||||
const projectFiles = fileIncludesAdjusted.join(' ');
|
||||
|
||||
execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_FILES="' + projectFiles + '" yarn docs:json', {
|
||||
cwd,
|
||||
})
|
||||
.then(function(result) {
|
||||
if (result.stderr !== '') {
|
||||
throw new Error(result.stderr);
|
||||
}
|
||||
const fileName = 'v' + version + '.json';
|
||||
const s3Url = S3BucketPath + fileName;
|
||||
return execAsync('S3_URL=' + s3Url + ' yarn upload_docs_json', {
|
||||
cwd,
|
||||
});
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log(err);
|
||||
});
|
@@ -13,59 +13,88 @@ import {
|
||||
HttpRequestType,
|
||||
OrderbookRequest,
|
||||
OrderbookResponse,
|
||||
OrdersRequest,
|
||||
OrdersRequestOpts,
|
||||
PagedRequestOpts,
|
||||
SignedOrder,
|
||||
TokenPairsItem,
|
||||
TokenPairsRequest,
|
||||
TokenPairsRequestOpts,
|
||||
} from './types';
|
||||
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
|
||||
|
||||
const TRAILING_SLASHES_REGEX = /\/+$/;
|
||||
const DEFAULT_PAGED_REQUEST_OPTS: PagedRequestOpts = {
|
||||
page: 1,
|
||||
perPage: 100,
|
||||
};
|
||||
/**
|
||||
* This mapping defines how an option property name gets converted into an HTTP request query field
|
||||
*/
|
||||
const OPTS_TO_QUERY_FIELD_MAP = {
|
||||
perPage: 'per_page',
|
||||
};
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with a set of HTTP endpoints
|
||||
* that implement the standard relayer API v0
|
||||
*/
|
||||
export class HttpClient implements Client {
|
||||
private _apiEndpointUrl: string;
|
||||
/**
|
||||
* Format parameters to be appended to http requests into query string form
|
||||
*/
|
||||
private static _buildQueryStringFromHttpParams(params?: object): string {
|
||||
// if params are undefined or empty, return an empty string
|
||||
if (_.isUndefined(params) || _.isEmpty(params)) {
|
||||
return '';
|
||||
}
|
||||
// format params into a form the api expects
|
||||
const formattedParams = _.mapKeys(params, (value: any, key: string) => {
|
||||
return _.get(OPTS_TO_QUERY_FIELD_MAP, key, key);
|
||||
});
|
||||
// stringify the formatted object
|
||||
const stringifiedParams = queryString.stringify(formattedParams);
|
||||
return `?${stringifiedParams}`;
|
||||
}
|
||||
/**
|
||||
* Instantiates a new HttpClient instance
|
||||
* @param url The relayer API base HTTP url you would like to interact with
|
||||
* @return An instance of HttpClient
|
||||
*/
|
||||
constructor(url: string) {
|
||||
assert.isHttpUrl('url', url);
|
||||
assert.isWebUri('url', url);
|
||||
this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes
|
||||
}
|
||||
/**
|
||||
* Retrieve token pair info from the API
|
||||
* @param request A TokenPairsRequest instance describing specific token information
|
||||
* to retrieve
|
||||
* @param requestOpts Options specifying token information to retrieve and page information, defaults to { page: 1, perPage: 100 }
|
||||
* @return The resulting TokenPairsItems that match the request
|
||||
*/
|
||||
public async getTokenPairsAsync(request?: TokenPairsRequest): Promise<TokenPairsItem[]> {
|
||||
if (!_.isUndefined(request)) {
|
||||
assert.doesConformToSchema('request', request, clientSchemas.relayerTokenPairsRequestSchema);
|
||||
public async getTokenPairsAsync(requestOpts?: TokenPairsRequestOpts & PagedRequestOpts): Promise<TokenPairsItem[]> {
|
||||
if (!_.isUndefined(requestOpts)) {
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.tokenPairsRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||
}
|
||||
const requestOpts = {
|
||||
params: request,
|
||||
const httpRequestOpts = {
|
||||
params: _.defaults({}, requestOpts, DEFAULT_PAGED_REQUEST_OPTS),
|
||||
};
|
||||
const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, requestOpts);
|
||||
const responseJson = await this._requestAsync('/token_pairs', HttpRequestType.Get, httpRequestOpts);
|
||||
const tokenPairs = relayerResponseJsonParsers.parseTokenPairsJson(responseJson);
|
||||
return tokenPairs;
|
||||
}
|
||||
/**
|
||||
* Retrieve orders from the API
|
||||
* @param request An OrdersRequest instance describing specific orders to retrieve
|
||||
* @param requestOpts Options specifying orders to retrieve and page information, defaults to { page: 1, perPage: 100 }
|
||||
* @return The resulting SignedOrders that match the request
|
||||
*/
|
||||
public async getOrdersAsync(request?: OrdersRequest): Promise<SignedOrder[]> {
|
||||
if (!_.isUndefined(request)) {
|
||||
assert.doesConformToSchema('request', request, clientSchemas.relayerOrdersRequestSchema);
|
||||
public async getOrdersAsync(requestOpts?: OrdersRequestOpts & PagedRequestOpts): Promise<SignedOrder[]> {
|
||||
if (!_.isUndefined(requestOpts)) {
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.ordersRequestOptsSchema);
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||
}
|
||||
const requestOpts = {
|
||||
params: request,
|
||||
const httpRequestOpts = {
|
||||
params: _.defaults({}, requestOpts, DEFAULT_PAGED_REQUEST_OPTS),
|
||||
};
|
||||
const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, requestOpts);
|
||||
const responseJson = await this._requestAsync(`/orders`, HttpRequestType.Get, httpRequestOpts);
|
||||
const orders = relayerResponseJsonParsers.parseOrdersJson(responseJson);
|
||||
return orders;
|
||||
}
|
||||
@@ -82,15 +111,22 @@ export class HttpClient implements Client {
|
||||
}
|
||||
/**
|
||||
* Retrieve an orderbook from the API
|
||||
* @param request An OrderbookRequest instance describing the specific orderbook to retrieve
|
||||
* @param request An OrderbookRequest instance describing the specific orderbook to retrieve
|
||||
* @param requestOpts Options specifying page information, defaults to { page: 1, perPage: 100 }
|
||||
* @return The resulting OrderbookResponse that matches the request
|
||||
*/
|
||||
public async getOrderbookAsync(request: OrderbookRequest): Promise<OrderbookResponse> {
|
||||
assert.doesConformToSchema('request', request, clientSchemas.relayerOrderBookRequestSchema);
|
||||
const requestOpts = {
|
||||
params: request,
|
||||
public async getOrderbookAsync(
|
||||
request: OrderbookRequest,
|
||||
requestOpts?: PagedRequestOpts,
|
||||
): Promise<OrderbookResponse> {
|
||||
assert.doesConformToSchema('request', request, clientSchemas.orderBookRequestSchema);
|
||||
if (!_.isUndefined(requestOpts)) {
|
||||
assert.doesConformToSchema('requestOpts', requestOpts, clientSchemas.pagedRequestOptsSchema);
|
||||
}
|
||||
const httpRequestOpts = {
|
||||
params: _.defaults({}, request, requestOpts, DEFAULT_PAGED_REQUEST_OPTS),
|
||||
};
|
||||
const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, requestOpts);
|
||||
const responseJson = await this._requestAsync('/orderbook', HttpRequestType.Get, httpRequestOpts);
|
||||
const orderbook = relayerResponseJsonParsers.parseOrderbookResponseJson(responseJson);
|
||||
return orderbook;
|
||||
}
|
||||
@@ -100,11 +136,11 @@ export class HttpClient implements Client {
|
||||
* @return The resulting FeesResponse that matches the request
|
||||
*/
|
||||
public async getFeesAsync(request: FeesRequest): Promise<FeesResponse> {
|
||||
assert.doesConformToSchema('request', request, schemas.relayerApiFeesPayloadSchema);
|
||||
const requestOpts = {
|
||||
assert.doesConformToSchema('request', request, clientSchemas.feesRequestSchema);
|
||||
const httpRequestOpts = {
|
||||
payload: request,
|
||||
};
|
||||
const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, requestOpts);
|
||||
const responseJson = await this._requestAsync('/fees', HttpRequestType.Post, httpRequestOpts);
|
||||
const fees = relayerResponseJsonParsers.parseFeesResponseJson(responseJson);
|
||||
return fees;
|
||||
}
|
||||
@@ -126,11 +162,7 @@ export class HttpClient implements Client {
|
||||
): Promise<any> {
|
||||
const params = _.get(requestOptions, 'params');
|
||||
const payload = _.get(requestOptions, 'payload');
|
||||
let query = '';
|
||||
if (!_.isUndefined(params) && !_.isEmpty(params)) {
|
||||
const stringifiedParams = queryString.stringify(params);
|
||||
query = `?${stringifiedParams}`;
|
||||
}
|
||||
const query = HttpClient._buildQueryStringFromHttpParams(params);
|
||||
const url = `${this._apiEndpointUrl}${path}${query}`;
|
||||
const headers = new Headers({
|
||||
'content-type': 'application/json',
|
||||
@@ -140,13 +172,12 @@ export class HttpClient implements Client {
|
||||
body: JSON.stringify(payload),
|
||||
headers,
|
||||
});
|
||||
const json = await response.json();
|
||||
const text = await response.text();
|
||||
if (!response.ok) {
|
||||
const errorString = `${response.status} - ${response.statusText}\n${requestType} ${url}\n${JSON.stringify(
|
||||
json,
|
||||
)}`;
|
||||
const errorString = `${response.status} - ${response.statusText}\n${requestType} ${url}\n${text}`;
|
||||
throw Error(errorString);
|
||||
}
|
||||
return json;
|
||||
const result = !_.isEmpty(text) ? JSON.parse(text) : undefined;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@@ -11,9 +11,11 @@ export {
|
||||
OrderbookChannelSubscriptionOpts,
|
||||
OrderbookRequest,
|
||||
OrderbookResponse,
|
||||
OrdersRequest,
|
||||
OrdersRequestOpts,
|
||||
PagedRequestOpts,
|
||||
SignedOrder,
|
||||
TokenPairsItem,
|
||||
TokenPairsRequest,
|
||||
TokenPairsRequestOpts,
|
||||
TokenTradeInfo,
|
||||
WebSocketOrderbookChannelConfig,
|
||||
} from './types';
|
||||
|
26
packages/connect/src/schemas/fees_request_schema.ts
Normal file
26
packages/connect/src/schemas/fees_request_schema.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export const feesRequestSchema = {
|
||||
id: '/FeesRequest',
|
||||
type: 'object',
|
||||
properties: {
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
||||
maker: { $ref: '/Address' },
|
||||
taker: { $ref: '/Address' },
|
||||
makerTokenAddress: { $ref: '/Address' },
|
||||
takerTokenAddress: { $ref: '/Address' },
|
||||
makerTokenAmount: { $ref: '/Number' },
|
||||
takerTokenAmount: { $ref: '/Number' },
|
||||
expirationUnixTimestampSec: { $ref: '/Number' },
|
||||
salt: { $ref: '/Number' },
|
||||
},
|
||||
required: [
|
||||
'exchangeContractAddress',
|
||||
'maker',
|
||||
'taker',
|
||||
'makerTokenAddress',
|
||||
'takerTokenAddress',
|
||||
'makerTokenAmount',
|
||||
'takerTokenAmount',
|
||||
'expirationUnixTimestampSec',
|
||||
'salt',
|
||||
],
|
||||
};
|
@@ -1,8 +1,9 @@
|
||||
export const relayerOrderBookRequestSchema = {
|
||||
id: '/RelayerOrderBookRequest',
|
||||
export const orderBookRequestSchema = {
|
||||
id: '/OrderBookRequest',
|
||||
type: 'object',
|
||||
properties: {
|
||||
baseTokenAddress: { $ref: '/Address' },
|
||||
quoteTokenAddress: { $ref: '/Address' },
|
||||
},
|
||||
required: ['baseTokenAddress', 'quoteTokenAddress'],
|
||||
};
|
@@ -1,5 +1,5 @@
|
||||
export const relayerOrdersRequestSchema = {
|
||||
id: '/RelayerOrdersRequest',
|
||||
export const ordersRequestOptsSchema = {
|
||||
id: '/OrdersRequestOpts',
|
||||
type: 'object',
|
||||
properties: {
|
||||
exchangeContractAddress: { $ref: '/Address' },
|
@@ -0,0 +1,8 @@
|
||||
export const pagedRequestOptsSchema = {
|
||||
id: '/PagedRequestOpts',
|
||||
type: 'object',
|
||||
properties: {
|
||||
page: { type: 'number' },
|
||||
perPage: { type: 'number' },
|
||||
},
|
||||
};
|
@@ -1,8 +0,0 @@
|
||||
export const relayerOrderBookRequestSchema = {
|
||||
id: '/RelayerOrderBookRequest',
|
||||
type: 'object',
|
||||
properties: {
|
||||
baseTokenAddress: { $ref: '/Address' },
|
||||
quoteTokenAddress: { $ref: '/Address' },
|
||||
},
|
||||
};
|
@@ -1,9 +1,15 @@
|
||||
import { relayerOrderBookRequestSchema } from './relayer_orderbook_request_schema';
|
||||
import { relayerOrdersRequestSchema } from './relayer_orders_request_schema';
|
||||
import { relayerTokenPairsRequestSchema } from './relayer_token_pairs_request_schema';
|
||||
import { feesRequestSchema } from './fees_request_schema';
|
||||
import { orderBookRequestSchema } from './orderbook_request_schema';
|
||||
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
|
||||
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
|
||||
import { tokenPairsRequestOptsSchema } from './token_pairs_request_opts_schema';
|
||||
import { webSocketOrderbookChannelConfigSchema } from './websocket_orderbook_channel_config_schema';
|
||||
|
||||
export const schemas = {
|
||||
relayerOrderBookRequestSchema,
|
||||
relayerOrdersRequestSchema,
|
||||
relayerTokenPairsRequestSchema,
|
||||
feesRequestSchema,
|
||||
orderBookRequestSchema,
|
||||
ordersRequestOptsSchema,
|
||||
pagedRequestOptsSchema,
|
||||
tokenPairsRequestOptsSchema,
|
||||
webSocketOrderbookChannelConfigSchema,
|
||||
};
|
||||
|
@@ -1,5 +1,5 @@
|
||||
export const relayerTokenPairsRequestSchema = {
|
||||
id: '/RelayerTokenPairsRequest',
|
||||
export const tokenPairsRequestOptsSchema = {
|
||||
id: '/TokenPairsRequestOpts',
|
||||
type: 'object',
|
||||
properties: {
|
||||
tokenA: { $ref: '/Address' },
|
@@ -0,0 +1,10 @@
|
||||
export const webSocketOrderbookChannelConfigSchema = {
|
||||
id: '/WebSocketOrderbookChannelConfig',
|
||||
type: 'object',
|
||||
properties: {
|
||||
heartbeatIntervalMs: {
|
||||
type: 'number',
|
||||
minimum: 10,
|
||||
},
|
||||
},
|
||||
};
|
@@ -30,10 +30,10 @@ export interface ECSignature {
|
||||
}
|
||||
|
||||
export interface Client {
|
||||
getTokenPairsAsync: (request?: TokenPairsRequest) => Promise<TokenPairsItem[]>;
|
||||
getOrdersAsync: (request?: OrdersRequest) => Promise<SignedOrder[]>;
|
||||
getTokenPairsAsync: (requestOpts?: TokenPairsRequestOpts & PagedRequestOpts) => Promise<TokenPairsItem[]>;
|
||||
getOrdersAsync: (requestOpts?: OrdersRequestOpts & PagedRequestOpts) => Promise<SignedOrder[]>;
|
||||
getOrderAsync: (orderHash: string) => Promise<SignedOrder>;
|
||||
getOrderbookAsync: (request: OrderbookRequest) => Promise<OrderbookResponse>;
|
||||
getOrderbookAsync: (request: OrderbookRequest, requestOpts?: PagedRequestOpts) => Promise<OrderbookResponse>;
|
||||
getFeesAsync: (request: FeesRequest) => Promise<FeesResponse>;
|
||||
submitOrderAsync: (signedOrder: SignedOrder) => Promise<void>;
|
||||
}
|
||||
@@ -43,6 +43,13 @@ export interface OrderbookChannel {
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
/*
|
||||
* heartbeatInterval: Interval in milliseconds that the orderbook channel should ping the underlying websocket. Default: 15000
|
||||
*/
|
||||
export interface WebSocketOrderbookChannelConfig {
|
||||
heartbeatIntervalMs?: number;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -111,7 +118,7 @@ export enum WebsocketClientEventType {
|
||||
ConnectFailed = 'connectFailed',
|
||||
}
|
||||
|
||||
export interface TokenPairsRequest {
|
||||
export interface TokenPairsRequestOpts {
|
||||
tokenA?: string;
|
||||
tokenB?: string;
|
||||
}
|
||||
@@ -128,7 +135,7 @@ export interface TokenTradeInfo {
|
||||
precision: number;
|
||||
}
|
||||
|
||||
export interface OrdersRequest {
|
||||
export interface OrdersRequestOpts {
|
||||
exchangeContractAddress?: string;
|
||||
tokenAddress?: string;
|
||||
makerTokenAddress?: string;
|
||||
@@ -167,6 +174,11 @@ export interface FeesResponse {
|
||||
takerFee: BigNumber;
|
||||
}
|
||||
|
||||
export interface PagedRequestOpts {
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
}
|
||||
|
||||
export interface HttpRequestOptions {
|
||||
params?: object;
|
||||
payload?: object;
|
||||
|
@@ -3,6 +3,7 @@ import { schemas } from '@0xproject/json-schemas';
|
||||
import * as _ from 'lodash';
|
||||
import * as WebSocket from 'websocket';
|
||||
|
||||
import { schemas as clientSchemas } from './schemas/schemas';
|
||||
import {
|
||||
OrderbookChannel,
|
||||
OrderbookChannelHandler,
|
||||
@@ -10,9 +11,13 @@ import {
|
||||
OrderbookChannelSubscriptionOpts,
|
||||
WebsocketClientEventType,
|
||||
WebsocketConnectionEventType,
|
||||
WebSocketOrderbookChannelConfig,
|
||||
} from './types';
|
||||
import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser';
|
||||
|
||||
const DEFAULT_HEARTBEAT_INTERVAL_MS = 15000;
|
||||
const MINIMUM_HEARTBEAT_INTERVAL_MS = 10;
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with a websocket endpoint
|
||||
* that implements the standard relayer API v0
|
||||
@@ -21,15 +26,25 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
||||
private _apiEndpointUrl: string;
|
||||
private _client: WebSocket.client;
|
||||
private _connectionIfExists?: WebSocket.connection;
|
||||
private _heartbeatTimerIfExists?: NodeJS.Timer;
|
||||
private _subscriptionCounter = 0;
|
||||
private _heartbeatIntervalMs: number;
|
||||
/**
|
||||
* Instantiates a new WebSocketOrderbookChannel instance
|
||||
* @param url The relayer API base WS url you would like to interact with
|
||||
* @param config The configuration object. Look up the type for the description.
|
||||
* @return An instance of WebSocketOrderbookChannel
|
||||
*/
|
||||
constructor(url: string) {
|
||||
constructor(url: string, config?: WebSocketOrderbookChannelConfig) {
|
||||
assert.isUri('url', url);
|
||||
if (!_.isUndefined(config)) {
|
||||
assert.doesConformToSchema('config', config, clientSchemas.webSocketOrderbookChannelConfigSchema);
|
||||
}
|
||||
this._apiEndpointUrl = url;
|
||||
this._heartbeatIntervalMs =
|
||||
_.isUndefined(config) || _.isUndefined(config.heartbeatIntervalMs)
|
||||
? DEFAULT_HEARTBEAT_INTERVAL_MS
|
||||
: config.heartbeatIntervalMs;
|
||||
this._client = new WebSocket.client();
|
||||
}
|
||||
/**
|
||||
@@ -63,7 +78,7 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
||||
connection.on(WebsocketConnectionEventType.Error, wsError => {
|
||||
handler.onError(this, subscriptionOpts, wsError);
|
||||
});
|
||||
connection.on(WebsocketConnectionEventType.Close, () => {
|
||||
connection.on(WebsocketConnectionEventType.Close, (code: number, desc: string) => {
|
||||
handler.onClose(this, subscriptionOpts);
|
||||
});
|
||||
connection.on(WebsocketConnectionEventType.Message, message => {
|
||||
@@ -80,6 +95,9 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
||||
if (!_.isUndefined(this._connectionIfExists)) {
|
||||
this._connectionIfExists.close();
|
||||
}
|
||||
if (!_.isUndefined(this._heartbeatTimerIfExists)) {
|
||||
clearInterval(this._heartbeatTimerIfExists);
|
||||
}
|
||||
}
|
||||
private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void) {
|
||||
if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) {
|
||||
@@ -87,6 +105,20 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
||||
} else {
|
||||
this._client.on(WebsocketClientEventType.Connect, connection => {
|
||||
this._connectionIfExists = connection;
|
||||
if (this._heartbeatIntervalMs >= MINIMUM_HEARTBEAT_INTERVAL_MS) {
|
||||
this._heartbeatTimerIfExists = setInterval(() => {
|
||||
connection.ping('');
|
||||
}, this._heartbeatIntervalMs);
|
||||
} else {
|
||||
callback(
|
||||
new Error(
|
||||
`Heartbeat interval is ${
|
||||
this._heartbeatIntervalMs
|
||||
}ms which is less than the required minimum of ${MINIMUM_HEARTBEAT_INTERVAL_MS}ms`,
|
||||
),
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
callback(undefined, this._connectionIfExists);
|
||||
});
|
||||
this._client.on(WebsocketClientEventType.ConnectFailed, error => {
|
||||
|
@@ -40,19 +40,22 @@ describe('HttpClient', () => {
|
||||
});
|
||||
describe('#getTokenPairsAsync', () => {
|
||||
const url = `${relayUrl}/token_pairs`;
|
||||
it('gets token pairs', async () => {
|
||||
fetchMock.get(url, tokenPairsResponseJSON);
|
||||
it('gets token pairs with default options when none are provided', async () => {
|
||||
const urlWithQuery = `${url}?page=1&per_page=100`;
|
||||
fetchMock.get(urlWithQuery, tokenPairsResponseJSON);
|
||||
const tokenPairs = await relayerClient.getTokenPairsAsync();
|
||||
expect(tokenPairs).to.be.deep.equal(tokenPairsResponse);
|
||||
});
|
||||
it('gets specific token pairs for request', async () => {
|
||||
it('gets token pairs with specified request options', async () => {
|
||||
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
|
||||
const tokenPairsRequest = {
|
||||
const tokenPairsRequestOpts = {
|
||||
tokenA: tokenAddress,
|
||||
page: 3,
|
||||
perPage: 50,
|
||||
};
|
||||
const urlWithQuery = `${url}?tokenA=${tokenAddress}`;
|
||||
const urlWithQuery = `${url}?page=3&per_page=50&tokenA=${tokenAddress}`;
|
||||
fetchMock.get(urlWithQuery, tokenPairsResponseJSON);
|
||||
const tokenPairs = await relayerClient.getTokenPairsAsync(tokenPairsRequest);
|
||||
const tokenPairs = await relayerClient.getTokenPairsAsync(tokenPairsRequestOpts);
|
||||
expect(tokenPairs).to.be.deep.equal(tokenPairsResponse);
|
||||
});
|
||||
it('throws an error for invalid JSON response', async () => {
|
||||
@@ -62,17 +65,20 @@ describe('HttpClient', () => {
|
||||
});
|
||||
describe('#getOrdersAsync', () => {
|
||||
const url = `${relayUrl}/orders`;
|
||||
it('gets orders', async () => {
|
||||
fetchMock.get(url, ordersResponseJSON);
|
||||
it('gets orders with default options when none are provided', async () => {
|
||||
const urlWithQuery = `${url}?page=1&per_page=100`;
|
||||
fetchMock.get(urlWithQuery, ordersResponseJSON);
|
||||
const orders = await relayerClient.getOrdersAsync();
|
||||
expect(orders).to.be.deep.equal(ordersResponse);
|
||||
});
|
||||
it('gets specific orders for request', async () => {
|
||||
it('gets orders with specified request options', async () => {
|
||||
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
|
||||
const ordersRequest = {
|
||||
tokenAddress,
|
||||
page: 3,
|
||||
perPage: 50,
|
||||
};
|
||||
const urlWithQuery = `${url}?tokenAddress=${tokenAddress}`;
|
||||
const urlWithQuery = `${url}?page=3&per_page=50&tokenAddress=${tokenAddress}`;
|
||||
fetchMock.get(urlWithQuery, ordersResponseJSON);
|
||||
const orders = await relayerClient.getOrdersAsync(ordersRequest);
|
||||
expect(orders).to.be.deep.equal(ordersResponse);
|
||||
@@ -100,14 +106,27 @@ describe('HttpClient', () => {
|
||||
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
|
||||
quoteTokenAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
|
||||
};
|
||||
const url = `${relayUrl}/orderbook?baseTokenAddress=${request.baseTokenAddress}"eTokenAddress=${
|
||||
request.quoteTokenAddress
|
||||
}`;
|
||||
it('gets order book', async () => {
|
||||
fetchMock.get(url, orderbookJSON);
|
||||
const url = `${relayUrl}/orderbook`;
|
||||
it('gets orderbook with default page options when none are provided', async () => {
|
||||
const urlWithQuery = `${url}?baseTokenAddress=${
|
||||
request.baseTokenAddress
|
||||
}&page=1&per_page=100"eTokenAddress=${request.quoteTokenAddress}`;
|
||||
fetchMock.get(urlWithQuery, orderbookJSON);
|
||||
const orderbook = await relayerClient.getOrderbookAsync(request);
|
||||
expect(orderbook).to.be.deep.equal(orderbookResponse);
|
||||
});
|
||||
it('gets orderbook with specified page options', async () => {
|
||||
const urlWithQuery = `${url}?baseTokenAddress=${
|
||||
request.baseTokenAddress
|
||||
}&page=3&per_page=50"eTokenAddress=${request.quoteTokenAddress}`;
|
||||
fetchMock.get(urlWithQuery, orderbookJSON);
|
||||
const pagedRequestOptions = {
|
||||
page: 3,
|
||||
perPage: 50,
|
||||
};
|
||||
const orderbook = await relayerClient.getOrderbookAsync(request, pagedRequestOptions);
|
||||
expect(orderbook).to.be.deep.equal(orderbookResponse);
|
||||
});
|
||||
it('throws an error for invalid JSON response', async () => {
|
||||
fetchMock.get(url, { test: 'dummy' });
|
||||
expect(relayerClient.getOrderbookAsync(request)).to.be.rejected();
|
||||
|
@@ -1,15 +1,17 @@
|
||||
/**
|
||||
* This file is auto-generated using abi-gen. Don't edit directly.
|
||||
* Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates.
|
||||
* Templates can be found at https://github.com/0xProject/0x-monorepo/tree/development/packages/contract_templates.
|
||||
*/
|
||||
// tslint:disable:no-consecutive-blank-lines
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import { BaseContract } from '@0xproject/base-contract';
|
||||
import { TxData, TxDataPayable } from '@0xproject/types';
|
||||
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as ethersContracts from 'ethers-contracts';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {BaseContract} from './base_contract';
|
||||
|
||||
{{#if events}}
|
||||
export type {{contractName}}ContractEventArgs =
|
||||
{{#each events}}
|
||||
@@ -28,6 +30,7 @@ export enum {{contractName}}Events {
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
export class {{contractName}}Contract extends BaseContract {
|
||||
{{#each methods}}
|
||||
{{#this.constant}}
|
||||
@@ -37,8 +40,8 @@ export class {{contractName}}Contract extends BaseContract {
|
||||
{{> tx contractName=../contractName}}
|
||||
{{/this.constant}}
|
||||
{{/each}}
|
||||
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
|
||||
super(web3ContractInstance, defaults);
|
||||
classUtils.bindAll(this, ['_web3ContractInstance', '_defaults']);
|
||||
constructor(web3Wrapper: Web3Wrapper, abi: Web3.ContractAbi, address: string) {
|
||||
super(web3Wrapper, abi, address);
|
||||
classUtils.bindAll(this, ['_ethersInterface', 'address', 'abi', '_web3Wrapper']);
|
||||
}
|
||||
} // tslint:disable:max-file-line-count
|
3
packages/contract_templates/partials/call.handlebars
Normal file
3
packages/contract_templates/partials/call.handlebars
Normal file
@@ -0,0 +1,3 @@
|
||||
public {{this.name}} = {
|
||||
{{> callAsync}}
|
||||
};
|
30
packages/contract_templates/partials/callAsync.handlebars
Normal file
30
packages/contract_templates/partials/callAsync.handlebars
Normal file
@@ -0,0 +1,30 @@
|
||||
{{#hasReturnValue}}
|
||||
async callAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
{{#this.payable}}
|
||||
txData: TxDataPayable = {},
|
||||
{{/this.payable}}
|
||||
{{^this.payable}}
|
||||
txData: TxData = {},
|
||||
{{/this.payable}}
|
||||
defaultBlock?: Web3.BlockParam,
|
||||
): Promise<{{> return_type outputs=outputs}}> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const inputAbi = _.find(this.abi, {name: '{{this.name}}'}).inputs;
|
||||
[{{> params inputs=inputs}}] = BaseContract._transformABIData(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(this));
|
||||
const encodedData = self._ethersInterface.functions.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
).data;
|
||||
const callData = await self._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
data: encodedData,
|
||||
}
|
||||
)
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callData, defaultBlock);
|
||||
const outputAbi = _.find(this.abi, {name: '{{this.name}}'}).outputs as Web3.DataItem[];
|
||||
const outputParamsTypes = _.map(outputAbi, 'type');
|
||||
let resultArray = ethersContracts.Interface.decodeParams(outputParamsTypes, rawCallResult) as any;
|
||||
resultArray = BaseContract._transformABIData(outputAbi, resultArray, BaseContract._lowercaseAddress.bind(this));
|
||||
return resultArray{{#singleReturnValue}}[0]{{/singleReturnValue}};
|
||||
},
|
||||
{{/hasReturnValue}}
|
@@ -1,5 +1,5 @@
|
||||
export interface {{name}}ContractEventArgs {
|
||||
{{#each inputs}}
|
||||
{{name}}: {{#returnType type}}{{/returnType}};
|
||||
{{name}}: {{#returnType type components}}{{/returnType}};
|
||||
{{/each}}
|
||||
}
|
10
packages/contract_templates/partials/return_type.handlebars
Normal file
10
packages/contract_templates/partials/return_type.handlebars
Normal file
@@ -0,0 +1,10 @@
|
||||
{{#if outputs.length}}
|
||||
{{#singleReturnValue}}
|
||||
{{#returnType outputs.0.type components}}{{/returnType}}
|
||||
{{/singleReturnValue}}
|
||||
{{^singleReturnValue}}
|
||||
[{{#each outputs}}{{#returnType type components}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||
{{/singleReturnValue}}
|
||||
{{else}}
|
||||
void
|
||||
{{/if}}
|
@@ -9,19 +9,22 @@ public {{this.name}} = {
|
||||
{{/this.payable}}
|
||||
): Promise<string> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const inputAbi = _.find(this.abi, {name: '{{this.name}}'}).inputs;
|
||||
[{{> params inputs=inputs}}] = BaseContract._transformABIData(inputAbi, [{{> params inputs=inputs}}], BaseContract._bigNumberToString.bind(this));
|
||||
const encodedData = this._ethersInterface.functions.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
).data
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||
txData,
|
||||
{
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self.{{this.name}}.estimateGasAsync.bind(
|
||||
self,
|
||||
{{> params inputs=inputs}}
|
||||
),
|
||||
);
|
||||
const txHash = await promisify<string>(
|
||||
self._web3ContractInstance.{{this.name}}, self._web3ContractInstance,
|
||||
)(
|
||||
{{> params inputs=inputs}}
|
||||
txDataWithDefaults,
|
||||
);
|
||||
const txHash = await this._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
async estimateGasAsync(
|
||||
@@ -29,15 +32,16 @@ public {{this.name}} = {
|
||||
txData: TxData = {},
|
||||
): Promise<number> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||
txData,
|
||||
);
|
||||
const gas = await promisify<number>(
|
||||
self._web3ContractInstance.{{this.name}}.estimateGas, self._web3ContractInstance,
|
||||
)(
|
||||
const encodedData = this._ethersInterface.functions.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
txDataWithDefaults,
|
||||
).data
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
...txData,
|
||||
data: encodedData,
|
||||
}
|
||||
);
|
||||
const gas = await this._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
@@ -45,7 +49,10 @@ public {{this.name}} = {
|
||||
txData: TxData = {},
|
||||
): string {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const abiEncodedTransactionData = self._web3ContractInstance.{{this.name}}.getData();
|
||||
const abiEncodedTransactionData = this._ethersInterface.functions.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
).data
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
{{> callAsync}}
|
||||
};
|
@@ -0,0 +1,3 @@
|
||||
{{#each inputs}}
|
||||
{{name}}: {{#parameterType type components}}{{/parameterType}},
|
||||
{{/each}}
|
@@ -4,11 +4,11 @@ Smart contracts that implement the 0x protocol.
|
||||
|
||||
## Usage
|
||||
|
||||
* [Docs](https://0xproject.com/docs/contracts)
|
||||
* [Overview of 0x protocol architecture](https://0xproject.com/wiki#Architecture)
|
||||
* [0x smart contract interactions](https://0xproject.com/wiki#Contract-Interactions)
|
||||
* [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses)
|
||||
* [0x protocol message format](https://0xproject.com/wiki#Message-Format)
|
||||
* [Docs](https://0xproject.com/docs/contracts)
|
||||
* [Overview of 0x protocol architecture](https://0xproject.com/wiki#Architecture)
|
||||
* [0x smart contract interactions](https://0xproject.com/wiki#Contract-Interactions)
|
||||
* [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses)
|
||||
* [0x protocol message format](https://0xproject.com/wiki#Message-Format)
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -60,7 +60,7 @@ yarn lint
|
||||
|
||||
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.js))
|
||||
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 ../..
|
||||
|
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* This file is auto-generated using abi-gen. Don't edit directly.
|
||||
* Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates.
|
||||
*/
|
||||
// tslint:disable:async-suffix member-ordering no-consecutive-blank-lines
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import { TxData, TxDataPayable } from '@0xproject/types';
|
||||
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {BaseContract} from './base_contract';
|
||||
|
||||
export class {{contractName}}Contract extends BaseContract {
|
||||
{{#each methods}}
|
||||
{{#this.constant}}
|
||||
{{> call contractName=../contractName}}
|
||||
{{/this.constant}}
|
||||
{{^this.constant}}
|
||||
{{> tx contractName=../contractName}}
|
||||
{{/this.constant}}
|
||||
{{/each}}
|
||||
constructor(web3ContractInstance: Web3.ContractInstance, defaults?: Partial<TxData>) {
|
||||
super(web3ContractInstance, defaults);
|
||||
classUtils.bindAll(this, ['_web3ContractInstance', '_defaults']);
|
||||
}
|
||||
} // tslint:disable:max-file-line-count
|
@@ -1,10 +0,0 @@
|
||||
public async {{this.name}}(
|
||||
{{> typed_params inputs=inputs}}
|
||||
defaultBlock?: Web3.BlockParam,
|
||||
): Promise<{{> return_type outputs=outputs}}> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const result = await self._web3ContractInstance.{{this.name}}.call(
|
||||
{{> params inputs=inputs}}
|
||||
);
|
||||
return result;
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
{{#each inputs}}
|
||||
{{name}},
|
||||
{{/each}}
|
@@ -1,10 +0,0 @@
|
||||
{{#if outputs.length}}
|
||||
{{#singleReturnValue}}
|
||||
{{#returnType outputs.0.type}}{{/returnType}}
|
||||
{{/singleReturnValue}}
|
||||
{{^singleReturnValue}}
|
||||
[{{#each outputs}}{{#returnType type}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||
{{/singleReturnValue}}
|
||||
{{else}}
|
||||
void
|
||||
{{/if}}
|
@@ -1,36 +0,0 @@
|
||||
public {{this.name}} = {
|
||||
async sendTransactionAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
{{#this.payable}}
|
||||
txData: TxDataPayable = {},
|
||||
{{/this.payable}}
|
||||
{{^this.payable}}
|
||||
txData: TxData = {},
|
||||
{{/this.payable}}
|
||||
): Promise<string> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(txData);
|
||||
const txHash = await self._web3ContractInstance.{{this.name}}(
|
||||
{{> params inputs=inputs}}
|
||||
txDataWithDefaults,
|
||||
);
|
||||
return txHash;
|
||||
},
|
||||
async callAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
{{#this.payable}}
|
||||
txData: TxDataPayable = {},
|
||||
{{/this.payable}}
|
||||
{{^this.payable}}
|
||||
txData: TxData = {},
|
||||
{{/this.payable}}
|
||||
): Promise<{{> return_type outputs=outputs}}> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(txData);
|
||||
const returnValue = await self._web3ContractInstance.{{this.name}}.call(
|
||||
{{> params inputs=inputs}}
|
||||
txDataWithDefaults,
|
||||
);
|
||||
return returnValue;
|
||||
},
|
||||
};
|
@@ -1,3 +0,0 @@
|
||||
{{#each inputs}}
|
||||
{{name}}: {{#parameterType type}}{{/parameterType}},
|
||||
{{/each}}
|
1
packages/contracts/globals.d.ts
vendored
1
packages/contracts/globals.d.ts
vendored
@@ -30,5 +30,6 @@ declare module 'web3-eth-abi' {
|
||||
|
||||
declare module 'ethereumjs-abi' {
|
||||
const soliditySHA3: (argTypes: string[], args: any[]) => Buffer;
|
||||
const soliditySHA256: (argTypes: string[], args: any[]) => Buffer;
|
||||
const methodID: (name: string, types: string[]) => Buffer;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "contracts",
|
||||
"version": "2.1.11",
|
||||
"version": "2.1.15",
|
||||
"description": "Smart contract components of 0x protocol",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
@@ -9,33 +9,35 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build:watch": "tsc -w",
|
||||
"prebuild": "run-s clean copy_artifacts generate_contract_wrappers",
|
||||
"prebuild": "run-s clean compile copy_artifacts generate_contract_wrappers",
|
||||
"copy_artifacts": "copyfiles './src/artifacts/**/*' ./lib",
|
||||
"build": "tsc",
|
||||
"test": "run-s compile build run_mocha",
|
||||
"test": "run-s build run_mocha",
|
||||
"run_mocha": "mocha 'lib/test/**/*.js' --timeout 10000 --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": "node ../deployer/lib/src/cli.js compile --contracts-dir src/contracts --artifacts-dir src/artifacts",
|
||||
"clean": "rm -rf ./lib",
|
||||
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken).json' --template contract_templates/contract.handlebars --partials 'contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated",
|
||||
"compile": "node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir src/contracts --artifacts-dir src/artifacts",
|
||||
"clean": "shx rm -rf ./lib",
|
||||
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|Arbitrage|EtherDelta|AccountLevels).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'",
|
||||
"migrate": "node ../deployer/lib/src/cli.js migrate",
|
||||
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
|
||||
"test:circleci": "yarn test"
|
||||
},
|
||||
"config": {
|
||||
"contracts": "Exchange,DummyToken,ZRXToken,Token,WETH9,TokenTransferProxy,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,MaliciousToken,TokenRegistry,Arbitrage,EtherDelta,AccountLevels"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x.js.git"
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"author": "Amir Bandeali",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x.js/issues"
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/contracts/README.md",
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/dev-utils": "^0.0.12",
|
||||
"@0xproject/tslint-config": "^0.4.8",
|
||||
"@0xproject/types": "^0.2.1",
|
||||
"@0xproject/dev-utils": "^0.2.1",
|
||||
"@0xproject/tslint-config": "^0.4.10",
|
||||
"@types/bluebird": "^3.5.3",
|
||||
"@types/lodash": "^4.14.86",
|
||||
"@types/node": "^8.0.53",
|
||||
@@ -43,31 +45,35 @@
|
||||
"@types/yargs": "^10.0.0",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-as-promised-typescript-typings": "^0.0.9",
|
||||
"chai-as-promised-typescript-typings": "^0.0.10",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"chai-typescript-typings": "^0.0.3",
|
||||
"chai-typescript-typings": "^0.0.4",
|
||||
"copyfiles": "^1.2.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ethers-typescript-typings": "^0.0.2",
|
||||
"mocha": "^4.0.1",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"solc": "^0.4.18",
|
||||
"tslint": "5.8.0",
|
||||
"types-bn": "^0.0.1",
|
||||
"types-ethereumjs-util": "0xProject/types-ethereumjs-util",
|
||||
"typescript": "2.7.1",
|
||||
"web3-typescript-typings": "^0.9.10",
|
||||
"web3-typescript-typings": "^0.10.0",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"0x.js": "^0.32.2",
|
||||
"@0xproject/deployer": "^0.0.8",
|
||||
"@0xproject/json-schemas": "^0.7.10",
|
||||
"@0xproject/utils": "^0.3.2",
|
||||
"@0xproject/web3-wrapper": "^0.1.12",
|
||||
"0x.js": "^0.33.1",
|
||||
"@0xproject/deployer": "^0.2.1",
|
||||
"@0xproject/json-schemas": "^0.7.14",
|
||||
"@0xproject/types": "^0.3.1",
|
||||
"@0xproject/utils": "^0.4.1",
|
||||
"@0xproject/web3-wrapper": "^0.2.1",
|
||||
"bluebird": "^3.5.0",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereumjs-abi": "^0.6.4",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
"ethers-contracts": "^2.2.1",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"lodash": "^4.17.4",
|
||||
"request": "^2.81.0",
|
||||
|
File diff suppressed because one or more lines are too long
@@ -1,188 +0,0 @@
|
||||
{
|
||||
"contract_name": "ERC20Token",
|
||||
"networks": {
|
||||
"50": {
|
||||
"solc_version": "0.4.18",
|
||||
"keccak256": "0x31be5b5f8d7ae32e5ac282b8740cc7aa87cdc383cabafa02292ea6f38302efcc",
|
||||
"optimizer_enabled": 0,
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"unlinked_binary":
|
||||
"0x6060604052341561000f57600080fd5b6109528061001e6000396000f300606060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063095ea7b31461007d57806318160ddd146100d757806323b872dd1461010057806370a0823114610179578063a9059cbb146101c6578063dd62ed3e14610220575b600080fd5b341561008857600080fd5b6100bd600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061028c565b604051808215151515815260200191505060405180910390f35b34156100e257600080fd5b6100ea61037e565b6040518082815260200191505060405180910390f35b341561010b57600080fd5b61015f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610384565b604051808215151515815260200191505060405180910390f35b341561018457600080fd5b6101b0600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610677565b6040518082815260200191505060405180910390f35b34156101d157600080fd5b610206600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506106bf565b604051808215151515815260200191505060405180910390f35b341561022b57600080fd5b610276600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061089f565b6040518082815260200191505060405180910390f35b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60025481565b6000816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410158015610450575081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410155b80156104da57506000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110155b15156104e557600080fd5b816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561078d57506000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110155b151561079857600080fd5b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a72305820d9af9b2b6ffe19f00d45d30a243f833e31053a2e48142e183c9f1e6b0ead7a9e0029",
|
||||
"updated_at": 1517509619365
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,182 +0,0 @@
|
||||
{
|
||||
"contract_name": "ERC20Token_v1",
|
||||
"networks": {
|
||||
"50": {
|
||||
"solc_version": "0.4.11",
|
||||
"keccak256": "0x3d710b436c430d6fe49f64b091555405360d76da6454b93faa8e213eea34a96d",
|
||||
"optimizer_enabled": 0,
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"unlinked_binary":
|
||||
"0x6060604052341561000c57fe5b5b61095b8061001c6000396000f30060606040523615610076576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063095ea7b31461007857806318160ddd146100cf57806323b872dd146100f557806370a082311461016b578063a9059cbb146101b5578063dd62ed3e1461020c575bfe5b341561008057fe5b6100b5600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610275565b604051808215151515815260200191505060405180910390f35b34156100d757fe5b6100df610368565b6040518082815260200191505060405180910390f35b34156100fd57fe5b610151600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061036e565b604051808215151515815260200191505060405180910390f35b341561017357fe5b61019f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061066f565b6040518082815260200191505060405180910390f35b34156101bd57fe5b6101f2600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506106b9565b604051808215151515815260200191505060405180910390f35b341561021457fe5b61025f600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506108a7565b6040518082815260200191505060405180910390f35b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a3600190505b92915050565b60025481565b600081600060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561043b575081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410155b80156104c75750600060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110155b1561065e5781600060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a360019050610668565b60009050610668565b5b9392505050565b6000600060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b600081600060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561078a5750600060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540110155b156108975781600060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190506108a1565b600090506108a1565b5b92915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b929150505600a165627a7a72305820441601e8451e1c2d31e6cde19fc920b8f95e79f9d42dd662aeefad13fd8bcfaa0029",
|
||||
"updated_at": 1517509621756
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user