Compare commits
384 Commits
@0xproject
...
@0xproject
Author | SHA1 | Date | |
---|---|---|---|
|
6636a0861d | ||
|
5d4078bcf4 | ||
|
396e3d3ec2 | ||
|
e88b01ed5b | ||
|
3e3587c281 | ||
|
972e1675f6 | ||
|
05ee368763 | ||
|
291e2c8fa0 | ||
|
ad61fe4b54 | ||
|
439fe10e1e | ||
|
d05a36deed | ||
|
03fd73fab8 | ||
|
1d430cf62f | ||
|
9ed05f56d3 | ||
|
23aa3ec5ea | ||
|
a0f5ceddce | ||
|
3171943228 | ||
|
455f74d449 | ||
|
01bc254cd0 | ||
|
2a7cafbf20 | ||
|
bf1603839e | ||
|
8ed776e113 | ||
|
c3508dcdc6 | ||
|
3579f063d6 | ||
|
ecc6cb2b7c | ||
|
de6fe25751 | ||
|
d639a22cff | ||
|
b1f36a9024 | ||
|
d8d15149fc | ||
|
c07de97fd8 | ||
|
78eb79396e | ||
|
abce410897 | ||
|
9594185f11 | ||
|
35c20d505e | ||
|
b829d55752 | ||
|
e92d6ff84f | ||
|
0056c66d32 | ||
|
613fada49f | ||
|
b603197ae8 | ||
|
69b81836fe | ||
|
0be4e1e1b3 | ||
|
14c994ce14 | ||
|
dd39fadce7 | ||
|
5d24022209 | ||
|
c75eaca5b6 | ||
|
53798302da | ||
|
b799a8a108 | ||
|
3d6c0b75a1 | ||
|
c531d734d4 | ||
|
f239522a19 | ||
|
d1c36f50d5 | ||
|
484312e677 | ||
|
0dc5178083 | ||
|
08f2406ca2 | ||
|
41104b2d45 | ||
|
766824120a | ||
|
c39ac903a9 | ||
|
ca2bb60877 | ||
|
3c66f18a46 | ||
|
8a940a800a | ||
|
06bd5a9b03 | ||
|
93518802d6 | ||
|
75f637bd75 | ||
|
e38c7ff076 | ||
|
66fe7b88b0 | ||
|
16179d2f8e | ||
|
1316a2dd2a | ||
|
e5b5fc400a | ||
|
786ea52738 | ||
|
ed6756898f | ||
|
a5d2cbfd6f | ||
|
04268d7f4b | ||
|
156dae1d33 | ||
|
436d78eb93 | ||
|
f269ecd95e | ||
|
1e4fdcf615 | ||
|
b7004b3002 | ||
|
c6af59a3e7 | ||
|
32396b5eca | ||
|
2930537a51 | ||
|
16c91bca0a | ||
|
1f85d31663 | ||
|
684542d073 | ||
|
bab01abe27 | ||
|
c63f76dde7 | ||
|
79bd416c61 | ||
|
7710989dee | ||
|
fb0b7efc45 | ||
|
1af427e4a7 | ||
|
bb6d594ec7 | ||
|
a57dda2c2a | ||
|
a3a2df098b | ||
|
90d1c3e2c9 | ||
|
950406f1f9 | ||
|
064405126d | ||
|
6d447fd8a5 | ||
|
400228e139 | ||
|
edfae32484 | ||
|
1aed970ce3 | ||
|
445ff1e28e | ||
|
df9d3e3e16 | ||
|
4dc6694651 | ||
|
98c01c2f80 | ||
|
f698dd4077 | ||
|
0578116f1d | ||
|
abbad68eb8 | ||
|
90d274ffc4 | ||
|
449fd9f024 | ||
|
22c4ee6ef7 | ||
|
951fbc9b76 | ||
|
89f368a8b8 | ||
|
672c8acaca | ||
|
681617480a | ||
|
95dfac6f9b | ||
|
b2256679be | ||
|
9e914be975 | ||
|
edbe6915e0 | ||
|
fd3e8cd813 | ||
|
b640e2cc49 | ||
|
51af6de624 | ||
|
054c00e323 | ||
|
5664333490 | ||
|
ac78c64f9e | ||
|
1f748afed9 | ||
|
4a73c05435 | ||
|
fe8f2d87c7 | ||
|
a71a1edf2c | ||
|
87209b8f57 | ||
|
13279f1f20 | ||
|
b46dd2e0a2 | ||
|
3eb08735d4 | ||
|
c8e52882ca | ||
|
484dd4c33a | ||
|
94f40a54b4 | ||
|
818a50a3fb | ||
|
2041e9945e | ||
|
126048bac9 | ||
|
274aa50d74 | ||
|
c36d85a46c | ||
|
ac1fbeb962 | ||
|
de8c445f96 | ||
|
c23d42fea5 | ||
|
a0aa21103b | ||
|
ce242b10e2 | ||
|
6d386220d9 | ||
|
7ce1021798 | ||
|
9ad9e1204c | ||
|
a63061f5b2 | ||
|
4997331410 | ||
|
f7f4b6da8d | ||
|
c975676f6c | ||
|
d702c65a5b | ||
|
4391f9913e | ||
|
28c409fc6d | ||
|
449a04d39c | ||
|
4bcd7ba31e | ||
|
5bda301fec | ||
|
84c7c6eb12 | ||
|
a5b7980b06 | ||
|
f746f5bfa3 | ||
|
3ed2eedfda | ||
|
4ce8eaa158 | ||
|
7abb026819 | ||
|
abd55411d4 | ||
|
cb596c1413 | ||
|
6120a43fff | ||
|
02e7354b53 | ||
|
0a0d3503c0 | ||
|
105bcc6664 | ||
|
ceae51fe32 | ||
|
b054080fa1 | ||
|
565010408e | ||
|
5619780cc1 | ||
|
d69143487e | ||
|
2ef763a195 | ||
|
6ba4ed99c4 | ||
|
aec3c83191 | ||
|
19d8449981 | ||
|
91f276d925 | ||
|
6bda6a22e3 | ||
|
1fbe638950 | ||
|
1e9f23ebba | ||
|
bbb768c5cf | ||
|
5678196706 | ||
|
987637abed | ||
|
ff422ecfb2 | ||
|
1fb643cb69 | ||
|
88db8c3724 | ||
|
cf50a82ecc | ||
|
145fea5253 | ||
|
b97f140b78 | ||
|
1dda4d5f78 | ||
|
6f2cb66163 | ||
|
8b29f6f18d | ||
|
2cc410e61f | ||
|
548fda8dba | ||
|
b58bf8259d | ||
|
e6862e9739 | ||
|
7008e882c0 | ||
|
7d59faa650 | ||
|
eaa6484f24 | ||
|
6630b1d8a5 | ||
|
d0916e196c | ||
|
8e74a22c6f | ||
|
2ffcc853fd | ||
|
caeb5cb6ab | ||
|
4f72c527de | ||
|
71cb2e05d1 | ||
|
d1fb61e0de | ||
|
cb7188d473 | ||
|
02f22d9155 | ||
|
707b98849c | ||
|
d778378b37 | ||
|
f3f596b231 | ||
|
276ee9903a | ||
|
16a970b65d | ||
|
1647e45247 | ||
|
3477a84bbd | ||
|
c61fe3ce64 | ||
|
f94dc1fe44 | ||
|
1339aadf4e | ||
|
a14424ae5f | ||
|
f1e7ea118b | ||
|
9c6453e129 | ||
|
a6f9718131 | ||
|
47075edc97 | ||
|
25cee41358 | ||
|
d08d65a3af | ||
|
d14ed71191 | ||
|
f341f62b2b | ||
|
828dffffed | ||
|
af8d24d0eb | ||
|
ca85a97106 | ||
|
5eea829be9 | ||
|
e822e3562d | ||
|
f109d132e4 | ||
|
1fc1eae39a | ||
|
deb6aeae43 | ||
|
f48f126b3a | ||
|
e0d79bd332 | ||
|
5e75aab8ea | ||
|
36125c3539 | ||
|
72ced622d7 | ||
|
b362e2c28e | ||
|
2260a0a4cd | ||
|
3c64b33f5c | ||
|
5301086c68 | ||
|
5687279c8d | ||
|
6c2bf8ed26 | ||
|
f1ecdcf602 | ||
|
1eaefac12b | ||
|
be17b75ad3 | ||
|
0c23f5e07e | ||
|
86e1fa8153 | ||
|
fae0651b0c | ||
|
720641f14c | ||
|
e8495b0c7b | ||
|
e80579a605 | ||
|
5967d39ca9 | ||
|
b82b50e2f0 | ||
|
e893e8c442 | ||
|
3db5efa264 | ||
|
5401c69163 | ||
|
b7030cffd9 | ||
|
73b4b4488e | ||
|
825402b0f9 | ||
|
f23071a214 | ||
|
f1b267cc9f | ||
|
adf1afc6ba | ||
|
0abbdc6b96 | ||
|
598f1dd2d8 | ||
|
594bd2de1c | ||
|
55083316fc | ||
|
8c87394b2b | ||
|
1dba4b85d0 | ||
|
22de68205b | ||
|
f76543ebfa | ||
|
f0c27f98b8 | ||
|
da678ba018 | ||
|
86ed1b4554 | ||
|
06e348f80b | ||
|
f05e0174a0 | ||
|
6bea3ac157 | ||
|
e4d42a079c | ||
|
5bbdb7a8f7 | ||
|
3cf7cb1054 | ||
|
78274440cb | ||
|
e59934ca21 | ||
|
c93bb4ef98 | ||
|
e3763bade2 | ||
|
1ea1c02387 | ||
|
f6321a8e70 | ||
|
08168c6e7d | ||
|
b5030df4e3 | ||
|
8414c18866 | ||
|
038668efdf | ||
|
4441d76725 | ||
|
1f494feec4 | ||
|
1153fa093b | ||
|
c64ec92fb2 | ||
|
20e28d6c70 | ||
|
c0015c2c11 | ||
|
3880f2b3cc | ||
|
293847053a | ||
|
e042f49e27 | ||
|
c036b96848 | ||
|
e95dba2c25 | ||
|
9891d7aaa6 | ||
|
1ce66b4a81 | ||
|
63b1199bd5 | ||
|
47789d770d | ||
|
df58593ff4 | ||
|
e2ef7a74db | ||
|
cde52b10b1 | ||
|
43983f1bb3 | ||
|
eb4adcf797 | ||
|
32568ebf09 | ||
|
c53d195ed0 | ||
|
9b1c9ecb8b | ||
|
8cd204423a | ||
|
2abc5a88c5 | ||
|
4c0bc02c48 | ||
|
16b27c4ae8 | ||
|
dc5f4ab28b | ||
|
f88ecaa035 | ||
|
c0cf47138e | ||
|
e1127dc2e8 | ||
|
5d1b845cad | ||
|
355514ca38 | ||
|
518d0eba84 | ||
|
78fb8d2bdc | ||
|
5673b42ec4 | ||
|
438c8ff807 | ||
|
ee15143dd7 | ||
|
042caa3363 | ||
|
eb667f653c | ||
|
6cbd0d4537 | ||
|
11bf2a0e06 | ||
|
9485e4f4f3 | ||
|
865ee090c8 | ||
|
0fc356740a | ||
|
f285a46d05 | ||
|
1e1c99d8d6 | ||
|
c291419141 | ||
|
290a96d41f | ||
|
ca9518c48c | ||
|
d44d6ccfd8 | ||
|
cec0b2afe3 | ||
|
e85a69655c | ||
|
4b3e038323 | ||
|
c57190dead | ||
|
3d73167f53 | ||
|
2eefec54b4 | ||
|
ab72656fdf | ||
|
b6f2f98db6 | ||
|
c051c48600 | ||
|
04fc16587b | ||
|
f1d5a7d31f | ||
|
7197356928 | ||
|
a75d547af6 | ||
|
bdecb18e3e | ||
|
e2adcaa185 | ||
|
4193893349 | ||
|
53522a98b9 | ||
|
0e856ccfab | ||
|
6093ee7824 | ||
|
46f185bbeb | ||
|
8bfa880371 | ||
|
a7f0d03611 | ||
|
9ce899d3f3 | ||
|
e71c7fdb16 | ||
|
4258e6dab1 | ||
|
e59b683047 | ||
|
3c3033586d | ||
|
166c741beb | ||
|
629a0fa3a5 | ||
|
15ce862334 | ||
|
840557be0d | ||
|
72a00ac2df | ||
|
da0af12834 | ||
|
7617b6681c | ||
|
8e13c477a3 | ||
|
fcddd503b7 | ||
|
3472bdcfd4 |
@@ -5,7 +5,7 @@ jobs:
|
||||
docker:
|
||||
- image: circleci/node:6.12
|
||||
environment:
|
||||
CONTRACTS_COMMIT_HASH: '78fe8dd'
|
||||
CONTRACTS_COMMIT_HASH: '9ed05f5'
|
||||
steps:
|
||||
- checkout
|
||||
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
- run: wget https://s3.amazonaws.com/testrpc-shapshots/${CONTRACTS_COMMIT_HASH}.zip
|
||||
- run: unzip ${CONTRACTS_COMMIT_HASH}.zip -d testrpc_snapshot
|
||||
- run: node ./node_modules/lerna/bin/lerna.js bootstrap
|
||||
- run: yarn lerna:run bootstrap
|
||||
- run: yarn lerna:run build
|
||||
- run:
|
||||
name: testrpc
|
||||
command: npm run testrpc -- --db testrpc_snapshot
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -68,3 +68,6 @@ generated_docs/
|
||||
TODO.md
|
||||
|
||||
packages/website/public/bundle*
|
||||
|
||||
# generated binaries
|
||||
bin/
|
||||
|
@@ -42,7 +42,7 @@ We also recommend you read through the tests.
|
||||
|
||||
## Styleguide
|
||||
|
||||
We use `[tslint](https://palantir.github.io/tslint/)` with [custom configs](https://github.com/0xProject/tslint-config-0xproject) to keep our code style consistent.
|
||||
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/tslint-config-0xproject) to keep our code style consistent.
|
||||
|
||||
To lint your code just run: `yarn lint`
|
||||
|
||||
|
90
README.md
90
README.md
@@ -17,12 +17,88 @@ This repository contains all the 0x developer tools written in TypeScript. Our h
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://greenkeeper.io/)
|
||||
|
||||
### Core Packages
|
||||
### Published Packages
|
||||
|
||||
| Package | Version | Description |
|
||||
|--------|-------|------------|
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Standard type and schema assertions |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the standard relayer api |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x project TSLint rules |
|
||||
|---------|---------|-------------|
|
||||
| [`0x.js`](/packages/0x.js) | [](https://www.npmjs.com/package/0x.js) | A Javascript library for interacting with the 0x protocol |
|
||||
| [`@0xproject/abi-gen`](/packages/abi-gen) | [](https://www.npmjs.com/package/@0xproject/abi-gen) | Tool to generate TS wrappers from smart contract ABIs |
|
||||
| [`@0xproject/assert`](/packages/assert) | [](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
|
||||
| [`@0xproject/connect`](/packages/connect) | [](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the standard relayer api |
|
||||
| [`@0xproject/json-schemas`](/packages/json-schemas) | [](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
|
||||
| [`@0xproject/subproviders`](/packages/subproviders) | [](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
|
||||
| [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
|
||||
| [`@0xproject/types`](/packages/types) | [](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |
|
||||
| [`@0xproject/utils`](/packages/utils) | [](https://www.npmjs.com/package/@0xproject/utils) | Shared utilities |
|
||||
| [`@0xproject/web3-wrapper`](/packages/web3-wrapper) | [](https://www.npmjs.com/package/@0xproject/web3-wrapper) | Web3 wrapper |
|
||||
|
||||
### Private Packages
|
||||
|
||||
| Package | Description |
|
||||
|---------|-------------|
|
||||
| [`@0xproject/contracts`](/packages/contracts) | 0x solidity smart contracts & tests |
|
||||
| [`@0xproject/kovan_faucets`](/packages/kovan-faucets) | A faucet micro-service that dispenses test ERC20 tokens or Ether |
|
||||
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | Shared monorepo scripts |
|
||||
| [`@0xproject/website`](/packages/website) | 0x website & Portal DApp |
|
||||
|
||||
## Usage
|
||||
|
||||
Dedicated documentation pages:
|
||||
- [0x.js Library](https://0xproject.com/docs/0xjs)
|
||||
- [0x Connect](https://0xproject.com/docs/connect)
|
||||
- [Smart contracts](https://0xproject.com/docs/contracts)
|
||||
- [Standard Relayer API](https://github.com/0xProject/standard-relayer-api/blob/master/README.md)
|
||||
|
||||
## 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
|
||||
|
||||
Build all packages
|
||||
|
||||
```bash
|
||||
yarn lerna:run build
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
Lint all packages
|
||||
```bash
|
||||
yarn lerna:run lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
Before running the tests, you will need to spin up a [TestRPC](https://www.npmjs.com/package/ethereumjs-testrpc) instance and deploy all the 0x smart contracts.
|
||||
|
||||
In a separate terminal, start TestRPC (a convenience command is provided as part of this repo)
|
||||
```bash
|
||||
yarn testrpc
|
||||
```
|
||||
|
||||
Then in your main terminal run
|
||||
```
|
||||
cd packages/contracts
|
||||
yarn migrate
|
||||
cd ..
|
||||
```
|
||||
|
||||
And finally from the root project directory run
|
||||
```bash
|
||||
yarn lerna:run test
|
||||
```
|
||||
|
12
package.json
12
package.json
@@ -7,16 +7,18 @@
|
||||
"scripts": {
|
||||
"testrpc": "testrpc -p 8545 --networkId 50 -m \"${npm_package_config_mnemonic}\"",
|
||||
"lerna:run": "lerna run",
|
||||
"lerna:publish": "lerna run clean; lerna run build; lerna publish --registry=https://registry.npmjs.org/"
|
||||
"lerna:rebuild": "lerna run clean; lerna run build;",
|
||||
"lerna:publish": "yarn install; lerna run clean; lerna run build; lerna publish --registry=https://registry.npmjs.org/"
|
||||
},
|
||||
"config": {
|
||||
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
|
||||
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lerna": "^2.5.1",
|
||||
"@0xproject/utils": "^0.1.0",
|
||||
"async-child-process": "^1.1.1",
|
||||
"semver-sort": "^0.0.4",
|
||||
"ethereumjs-testrpc": "6.0.3",
|
||||
"lerna": "^2.5.1",
|
||||
"publish-release": "0xproject/publish-release",
|
||||
"es6-promisify": "^5.0.0"
|
||||
"semver-sort": "^0.0.4"
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,21 @@
|
||||
# CHANGELOG
|
||||
|
||||
v0.28.0 - _December 20, 2017_
|
||||
------------------------
|
||||
* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken` (#267)
|
||||
* Removed accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry` (#267)
|
||||
* Removed `etherTokenContractAddress` from `ZeroEx` constructor arg `ZeroExConfig` (#267)
|
||||
* Rename `SubscriptionOpts` to `BlockRange` (#272)
|
||||
* Add `zeroEx.etherToken.subscribe`, `zeroEx.etherToken.unsubscribe`, `zeroEx.etherToken.unsubscribeAll` (#277)
|
||||
* Add `zeroEx.etherToken.getLogsAsync` (#277)
|
||||
* Add new public types `BlockParamLiteral`, `EtherTokenEvents`, `EtherTokenContractEventArgs`, `DepositContractEventArgs`, `WithdrawalContractEventArgs` (#277)
|
||||
* Support `Deposit` and `Withdraw` events on etherToken (#277)
|
||||
* Improve the error message when taker is not a string (#278)
|
||||
|
||||
v0.27.1 - _November 28, 2017_
|
||||
------------------------
|
||||
* Export `TransactionOpts` type
|
||||
|
||||
v0.27.0 - _November 28, 2017_
|
||||
------------------------
|
||||
* Make `ZeroExConfig` required parameter of `ZeroEx` constructor (#233)
|
||||
|
26
packages/0x.js/contract_templates/contract.mustache
Normal file
26
packages/0x.js/contract_templates/contract.mustache
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* This file is auto-generated using abi-gen. Don't edit directly.
|
||||
* Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates.
|
||||
*/
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import {TxData, TxDataPayable} from '@0xproject/types';
|
||||
import {classUtils, promisify} from '@0xproject/utils';
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {BaseContract} from './base_contract';
|
||||
|
||||
export class {{contractName}}Contract extends BaseContract {
|
||||
{{#each methods}}
|
||||
{{#this.constant}}
|
||||
{{> call contractName=../contractName}}
|
||||
{{/this.constant}}
|
||||
{{^this.constant}}
|
||||
{{> tx contractName=../contractName}}
|
||||
{{/this.constant}}
|
||||
{{/each}}
|
||||
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
|
||||
super(web3ContractInstance, defaults);
|
||||
classUtils.bindAll(this, ['web3ContractInstance', 'defaults']);
|
||||
}
|
||||
} // tslint:disable:max-file-line-count
|
15
packages/0x.js/contract_templates/partials/call.mustache
Normal file
15
packages/0x.js/contract_templates/partials/call.mustache
Normal file
@@ -0,0 +1,15 @@
|
||||
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;
|
||||
},
|
||||
};
|
@@ -0,0 +1,3 @@
|
||||
{{#each inputs}}
|
||||
{{name}},
|
||||
{{/each}}
|
@@ -0,0 +1,6 @@
|
||||
{{#singleReturnValue}}
|
||||
{{#returnType outputs.0.type}}{{/returnType}}
|
||||
{{/singleReturnValue}}
|
||||
{{^singleReturnValue}}
|
||||
[{{#each outputs}}{{#returnType type}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||
{{/singleReturnValue}}
|
51
packages/0x.js/contract_templates/partials/tx.mustache
Normal file
51
packages/0x.js/contract_templates/partials/tx.mustache
Normal file
@@ -0,0 +1,51 @@
|
||||
public {{this.name}} = {
|
||||
async sendTransactionAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
{{#this.payable}}
|
||||
txData: TxDataPayable = {},
|
||||
{{/this.payable}}
|
||||
{{^this.payable}}
|
||||
txData: TxData = {},
|
||||
{{/this.payable}}
|
||||
): Promise<string> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const txDataWithDefaults = await self.applyDefaultsToTxDataAsync(
|
||||
txData,
|
||||
self.{{this.name}}.estimateGasAsync.bind(
|
||||
self,
|
||||
{{> params inputs=inputs}}
|
||||
),
|
||||
);
|
||||
const txHash = await promisify<string>(
|
||||
self.web3ContractInstance.{{this.name}}, self.web3ContractInstance,
|
||||
)(
|
||||
{{> params inputs=inputs}}
|
||||
txDataWithDefaults,
|
||||
);
|
||||
return txHash;
|
||||
},
|
||||
async estimateGasAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
txData: TxData = {},
|
||||
): Promise<number> {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const txDataWithDefaults = await self.applyDefaultsToTxDataAsync(
|
||||
txData,
|
||||
);
|
||||
const gas = await promisify<number>(
|
||||
self.web3ContractInstance.{{this.name}}.estimateGas, self.web3ContractInstance,
|
||||
)(
|
||||
{{> params inputs=inputs}}
|
||||
txDataWithDefaults,
|
||||
);
|
||||
return gas;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
{{> typed_params inputs=inputs}}
|
||||
txData: TxData = {},
|
||||
): string {
|
||||
const self = this as {{contractName}}Contract;
|
||||
const abiEncodedTransactionData = self.web3ContractInstance.{{this.name}}.getData();
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
@@ -0,0 +1,3 @@
|
||||
{{#each inputs}}
|
||||
{{name}}: {{#parameterType type}}{{/parameterType}},
|
||||
{{/each}}
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "0x.js",
|
||||
"version": "0.26.1",
|
||||
"version": "0.27.2",
|
||||
"description": "A javascript library for interacting with the 0x protocol",
|
||||
"keywords": [
|
||||
"0x.js",
|
||||
@@ -12,10 +12,11 @@
|
||||
"main": "lib/src/index.js",
|
||||
"types": "lib/src/index.d.ts",
|
||||
"scripts": {
|
||||
"prebuild": "npm run clean",
|
||||
"prebuild": "run-s clean generate_contract_wrappers",
|
||||
"build": "run-p build:umd:prod build:commonjs; exit 0;",
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR",
|
||||
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json",
|
||||
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abiGlob 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --templates contract_templates --output src/contract_wrappers/generated",
|
||||
"lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'",
|
||||
"test:circleci": "run-s test:coverage report_test_coverage && if [ $CIRCLE_BRANCH = \"development\" ]; then yarn test:umd; fi",
|
||||
"test": "run-s clean test:commonjs",
|
||||
@@ -30,7 +31,7 @@
|
||||
"test:commonjs": "run-s build:commonjs run_mocha",
|
||||
"pretest:umd": "run-s clean build:umd:dev build:commonjs",
|
||||
"substitute_umd_bundle": "shx mv _bundles/* lib/src",
|
||||
"run_mocha": "mocha lib/test/**/*_test.js --timeout 5000 --bail --exit"
|
||||
"run_mocha": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit"
|
||||
},
|
||||
"config": {
|
||||
"artifacts": "TokenTransferProxy Exchange TokenRegistry Token EtherToken"
|
||||
@@ -44,27 +45,29 @@
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.1.1",
|
||||
"@0xproject/abi-gen": "^0.0.2",
|
||||
"@0xproject/tslint-config": "^0.2.1",
|
||||
"@0xproject/types": "^0.1.0",
|
||||
"@0xproject/dev-utils": "^0.0.1",
|
||||
"@types/bintrees": "^1.0.2",
|
||||
"@types/jsonschema": "^1.1.1",
|
||||
"@types/lodash": "^4.14.64",
|
||||
"@types/mocha": "^2.2.41",
|
||||
"@types/node": "^8.0.1",
|
||||
"@types/lodash": "^4.14.86",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/node": "^8.0.53",
|
||||
"@types/sinon": "^2.2.2",
|
||||
"@types/uuid": "^3.4.2",
|
||||
"awesome-typescript-loader": "^3.1.3",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-as-promised-typescript-typings": "0.0.3",
|
||||
"chai-as-promised-typescript-typings": "^0.0.3",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"chai-typescript-typings": "^0.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"coveralls": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ethereumjs-testrpc": "6.0.3",
|
||||
"json-loader": "^0.5.4",
|
||||
"mocha": "^4.0.0",
|
||||
"npm-run-all": "^4.0.2",
|
||||
"mocha": "^4.0.1",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"opn-cli": "^3.1.0",
|
||||
"request": "^2.81.0",
|
||||
@@ -75,21 +78,20 @@
|
||||
"truffle-hdwallet-provider": "^0.0.3",
|
||||
"tslint": "5.8.0",
|
||||
"typedoc": "~0.8.0",
|
||||
"types-bn": "^0.0.1",
|
||||
"types-ethereumjs-util": "0xProject/types-ethereumjs-util",
|
||||
"typescript": "~2.6.1",
|
||||
"web3-provider-engine": "^13.0.1",
|
||||
"web3-typescript-typings": "^0.7.1",
|
||||
"web3-typescript-typings": "^0.7.2",
|
||||
"webpack": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^0.0.5",
|
||||
"@0xproject/json-schemas": "^0.6.8",
|
||||
"@0xproject/assert": "^0.0.7",
|
||||
"@0xproject/json-schemas": "^0.6.10",
|
||||
"@0xproject/utils": "^0.1.0",
|
||||
"@0xproject/web3-wrapper": "^0.1.0",
|
||||
"bignumber.js": "~4.1.0",
|
||||
"bintrees": "^1.0.2",
|
||||
"bn.js": "4.11.8",
|
||||
"bn.js": "^4.11.8",
|
||||
"compare-versions": "^3.0.1",
|
||||
"es6-promisify": "^5.0.0",
|
||||
"ethereumjs-abi": "^0.6.4",
|
||||
"ethereumjs-blockstream": "^2.0.6",
|
||||
"ethereumjs-util": "^5.1.1",
|
||||
|
@@ -1,10 +1,11 @@
|
||||
import {schemas, SchemaValidator} from '@0xproject/json-schemas';
|
||||
import {bigNumberConfigs, intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from './artifacts';
|
||||
import {bigNumberConfigs} from './bignumber_config';
|
||||
import {EtherTokenWrapper} from './contract_wrappers/ether_token_wrapper';
|
||||
import {ExchangeWrapper} from './contract_wrappers/exchange_wrapper';
|
||||
import {TokenRegistryWrapper} from './contract_wrappers/token_registry_wrapper';
|
||||
@@ -15,7 +16,6 @@ import {zeroExConfigSchema} from './schemas/zero_ex_config_schema';
|
||||
import {
|
||||
ECSignature,
|
||||
Order,
|
||||
OrderStateWatcherConfig,
|
||||
SignedOrder,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
Web3Provider,
|
||||
@@ -25,11 +25,9 @@ import {
|
||||
import {AbiDecoder} from './utils/abi_decoder';
|
||||
import {assert} from './utils/assert';
|
||||
import {constants} from './utils/constants';
|
||||
import {intervalUtils} from './utils/interval_utils';
|
||||
import {OrderStateUtils} from './utils/order_state_utils';
|
||||
import {decorators} from './utils/decorators';
|
||||
import {signatureUtils} from './utils/signature_utils';
|
||||
import {utils} from './utils/utils';
|
||||
import {Web3Wrapper} from './web3_wrapper';
|
||||
|
||||
// Customize our BigNumber instances
|
||||
bigNumberConfigs.configure();
|
||||
@@ -158,6 +156,7 @@ export class ZeroEx {
|
||||
* @param order An object that conforms to the Order or SignedOrder interface definitions.
|
||||
* @return The resulting orderHash from hashing the supplied order.
|
||||
*/
|
||||
@decorators.syncZeroExErrorHandler
|
||||
public static getOrderHashHex(order: Order|SignedOrder): string {
|
||||
assert.doesConformToSchema('order', order, schemas.orderSchema);
|
||||
const orderHashHex = utils.getOrderHashHex(order);
|
||||
@@ -179,24 +178,31 @@ export class ZeroEx {
|
||||
const defaults = {
|
||||
gasPrice: config.gasPrice,
|
||||
};
|
||||
this._web3Wrapper = new Web3Wrapper(provider, config.networkId, defaults);
|
||||
this._web3Wrapper = new Web3Wrapper(provider, defaults);
|
||||
this.proxy = new TokenTransferProxyWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
config.tokenTransferProxyContractAddress,
|
||||
);
|
||||
this.token = new TokenWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
this._abiDecoder,
|
||||
this.proxy,
|
||||
);
|
||||
this.exchange = new ExchangeWrapper(
|
||||
this._web3Wrapper,
|
||||
config.networkId,
|
||||
this._abiDecoder,
|
||||
this.token,
|
||||
config.exchangeContractAddress,
|
||||
);
|
||||
this.tokenRegistry = new TokenRegistryWrapper(this._web3Wrapper, config.tokenRegistryContractAddress);
|
||||
this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.token, config.etherTokenContractAddress);
|
||||
this.tokenRegistry = new TokenRegistryWrapper(
|
||||
this._web3Wrapper, config.networkId, config.tokenRegistryContractAddress,
|
||||
);
|
||||
this.etherToken = new EtherTokenWrapper(
|
||||
this._web3Wrapper, config.networkId, this._abiDecoder, this.token,
|
||||
);
|
||||
this.orderStateWatcher = new OrderStateWatcher(
|
||||
this._web3Wrapper, this._abiDecoder, this.token, this.exchange, config.orderWatcherConfig,
|
||||
);
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import * as DummyTokenArtifact from './artifacts/DummyToken.json';
|
||||
import * as EtherTokenArtifact from './artifacts/EtherToken.json';
|
||||
import * as ExchangeArtifact from './artifacts/Exchange.json';
|
||||
import * as TokenArtifact from './artifacts/Token.json';
|
||||
@@ -8,6 +9,7 @@ import {Artifact} from './types';
|
||||
|
||||
export const artifacts = {
|
||||
ZRXArtifact: ZRXArtifact as any as Artifact,
|
||||
DummyTokenArtifact: DummyTokenArtifact as any as Artifact,
|
||||
TokenArtifact: TokenArtifact as any as Artifact,
|
||||
ExchangeArtifact: ExchangeArtifact as any as Artifact,
|
||||
EtherTokenArtifact: EtherTokenArtifact as any as Artifact,
|
||||
|
23
packages/0x.js/src/artifacts/DummyToken.json
Normal file
23
packages/0x.js/src/artifacts/DummyToken.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"contract_name": "DummyToken",
|
||||
"abi":
|
||||
[
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_target",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "setBalance",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
}
|
@@ -231,20 +231,54 @@
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Deposit",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Withdrawal",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"networks": {
|
||||
"1": {
|
||||
"address": "0x2956356cd2a2bf3202f771f50d3d14a367b48070"
|
||||
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
|
||||
},
|
||||
"3": {
|
||||
"address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
|
||||
},
|
||||
"42": {
|
||||
"address": "0x05d090b51c40b020eab3bfcb6a2dff130df22e9c"
|
||||
"address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
|
||||
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -601,7 +601,7 @@
|
||||
"address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
|
||||
},
|
||||
"50": {
|
||||
"address": "0xb69e673309512a9d726f87304c6984054f87a93b"
|
||||
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -178,7 +178,7 @@
|
||||
"address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
|
||||
"address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
|
||||
},
|
||||
"50": {
|
||||
"address": "0x25b8fe1de9daf8ba351890744ff28cf7dfa8f5e3"
|
||||
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import {Block, BlockAndLogStreamer} from 'ethereumjs-blockstream';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
@@ -5,6 +7,7 @@ import * as Web3 from 'web3';
|
||||
import {
|
||||
Artifact,
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
ContractEventArgs,
|
||||
ContractEvents,
|
||||
EventCallback,
|
||||
@@ -12,37 +15,42 @@ import {
|
||||
InternalZeroExError,
|
||||
LogWithDecodedArgs,
|
||||
RawLog,
|
||||
SubscriptionOpts,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {constants} from '../utils/constants';
|
||||
import {filterUtils} from '../utils/filter_utils';
|
||||
import {intervalUtils} from '../utils/interval_utils';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {[contractName: string]: ZeroExError} = {
|
||||
ZRX: ZeroExError.ZRXContractDoesNotExist,
|
||||
EtherToken: ZeroExError.EtherTokenContractDoesNotExist,
|
||||
Token: ZeroExError.TokenContractDoesNotExist,
|
||||
TokenRegistry: ZeroExError.TokenRegistryContractDoesNotExist,
|
||||
TokenTransferProxy: ZeroExError.TokenTransferProxyContractDoesNotExist,
|
||||
Exchange: ZeroExError.ExchangeContractDoesNotExist,
|
||||
};
|
||||
|
||||
export class ContractWrapper {
|
||||
protected _web3Wrapper: Web3Wrapper;
|
||||
private _networkId: number;
|
||||
private _abiDecoder?: AbiDecoder;
|
||||
private _blockAndLogStreamer: BlockAndLogStreamer|undefined;
|
||||
private _blockAndLogStreamerIfExists: BlockAndLogStreamer|undefined;
|
||||
private _blockAndLogStreamInterval: NodeJS.Timer;
|
||||
private _filters: {[filterToken: string]: Web3.FilterObject};
|
||||
private _filterCallbacks: {[filterToken: string]: EventCallback<ContractEventArgs>};
|
||||
private _onLogAddedSubscriptionToken: string|undefined;
|
||||
private _onLogRemovedSubscriptionToken: string|undefined;
|
||||
constructor(web3Wrapper: Web3Wrapper, abiDecoder?: AbiDecoder) {
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder?: AbiDecoder) {
|
||||
this._web3Wrapper = web3Wrapper;
|
||||
this._networkId = networkId;
|
||||
this._abiDecoder = abiDecoder;
|
||||
this._filters = {};
|
||||
this._filterCallbacks = {};
|
||||
this._blockAndLogStreamer = undefined;
|
||||
this._blockAndLogStreamerIfExists = undefined;
|
||||
this._onLogAddedSubscriptionToken = undefined;
|
||||
this._onLogRemovedSubscriptionToken = undefined;
|
||||
}
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
protected unsubscribeAll(): void {
|
||||
const filterTokens = _.keys(this._filterCallbacks);
|
||||
_.each(filterTokens, filterToken => {
|
||||
this._unsubscribe(filterToken);
|
||||
@@ -66,7 +74,7 @@ export class ContractWrapper {
|
||||
address: string, eventName: ContractEvents, indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi,
|
||||
callback: EventCallback<ArgsType>): string {
|
||||
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi);
|
||||
if (_.isUndefined(this._blockAndLogStreamer)) {
|
||||
if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
||||
this._startBlockAndLogStream();
|
||||
}
|
||||
const filterToken = filterUtils.generateUUID();
|
||||
@@ -75,9 +83,9 @@ export class ContractWrapper {
|
||||
return filterToken;
|
||||
}
|
||||
protected async _getLogsAsync<ArgsType extends ContractEventArgs>(
|
||||
address: string, eventName: ContractEvents, subscriptionOpts: SubscriptionOpts,
|
||||
address: string, eventName: ContractEvents, blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, subscriptionOpts);
|
||||
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange);
|
||||
const logs = await this._web3Wrapper.getLogsAsync(filter);
|
||||
const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
|
||||
return logsWithDecodedArguments;
|
||||
@@ -90,16 +98,30 @@ export class ContractWrapper {
|
||||
const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
|
||||
return logWithDecodedArgs;
|
||||
}
|
||||
protected async _instantiateContractIfExistsAsync<ContractType extends Web3.ContractInstance>(
|
||||
artifact: Artifact, addressIfExists?: string): Promise<ContractType> {
|
||||
const contractInstance =
|
||||
await this._web3Wrapper.getContractInstanceFromArtifactAsync<ContractType>(artifact, addressIfExists);
|
||||
protected async _instantiateContractIfExistsAsync(
|
||||
artifact: Artifact, addressIfExists?: string,
|
||||
): Promise<Web3.ContractInstance> {
|
||||
let contractAddress: string;
|
||||
if (_.isUndefined(addressIfExists)) {
|
||||
if (_.isUndefined(artifact.networks[this._networkId])) {
|
||||
throw new Error(ZeroExError.ContractNotDeployedOnNetwork);
|
||||
}
|
||||
contractAddress = artifact.networks[this._networkId].address.toLowerCase();
|
||||
} else {
|
||||
contractAddress = addressIfExists;
|
||||
}
|
||||
const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(contractAddress);
|
||||
if (!doesContractExist) {
|
||||
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
|
||||
}
|
||||
const contractInstance = this._web3Wrapper.getContractInstance(
|
||||
artifact.abi, contractAddress,
|
||||
);
|
||||
return contractInstance;
|
||||
}
|
||||
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
|
||||
if (_.isUndefined(addressIfExists)) {
|
||||
const networkId = this._web3Wrapper.getNetworkId();
|
||||
const contractAddress = artifact.networks[networkId].address;
|
||||
const contractAddress = artifact.networks[this._networkId].address;
|
||||
if (_.isUndefined(contractAddress)) {
|
||||
throw new Error(ZeroExError.ExchangeContractDoesNotExist);
|
||||
}
|
||||
@@ -121,39 +143,43 @@ export class ContractWrapper {
|
||||
});
|
||||
}
|
||||
private _startBlockAndLogStream(): void {
|
||||
this._blockAndLogStreamer = new BlockAndLogStreamer(
|
||||
if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
||||
throw new Error(ZeroExError.SubscriptionAlreadyPresent);
|
||||
}
|
||||
this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
|
||||
this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
|
||||
this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
|
||||
);
|
||||
const catchAllLogFilter = {};
|
||||
this._blockAndLogStreamer.addLogFilter(catchAllLogFilter);
|
||||
this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
|
||||
this._blockAndLogStreamInterval = intervalUtils.setAsyncExcludingInterval(
|
||||
this._reconcileBlockAsync.bind(this), constants.DEFAULT_BLOCK_POLLING_INTERVAL,
|
||||
);
|
||||
let isRemoved = false;
|
||||
this._onLogAddedSubscriptionToken = this._blockAndLogStreamer.subscribeToOnLogAdded(
|
||||
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
|
||||
this._onLogStateChanged.bind(this, isRemoved),
|
||||
);
|
||||
isRemoved = true;
|
||||
this._onLogRemovedSubscriptionToken = this._blockAndLogStreamer.subscribeToOnLogRemoved(
|
||||
this._onLogRemovedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogRemoved(
|
||||
this._onLogStateChanged.bind(this, isRemoved),
|
||||
);
|
||||
}
|
||||
private _stopBlockAndLogStream(): void {
|
||||
(this._blockAndLogStreamer as BlockAndLogStreamer).unsubscribeFromOnLogAdded(
|
||||
this._onLogAddedSubscriptionToken as string);
|
||||
(this._blockAndLogStreamer as BlockAndLogStreamer).unsubscribeFromOnLogRemoved(
|
||||
this._onLogRemovedSubscriptionToken as string);
|
||||
if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
||||
throw new Error(ZeroExError.SubscriptionNotFound);
|
||||
}
|
||||
this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string);
|
||||
this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string);
|
||||
intervalUtils.clearAsyncExcludingInterval(this._blockAndLogStreamInterval);
|
||||
delete this._blockAndLogStreamer;
|
||||
delete this._blockAndLogStreamerIfExists;
|
||||
}
|
||||
private async _reconcileBlockAsync(): Promise<void> {
|
||||
try {
|
||||
const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
|
||||
// We need to coerce to Block type cause Web3.Block includes types for mempool blocks
|
||||
if (!_.isUndefined(this._blockAndLogStreamer)) {
|
||||
if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
|
||||
// If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
|
||||
await this._blockAndLogStreamer.reconcileNewBlock(latestBlock as any as Block);
|
||||
await this._blockAndLogStreamerIfExists.reconcileNewBlock(latestBlock as any as Block);
|
||||
}
|
||||
} catch (err) {
|
||||
const filterTokens = _.keys(this._filterCallbacks);
|
||||
|
@@ -1,12 +1,24 @@
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import {EtherTokenContract, TransactionOpts, ZeroExError} from '../types';
|
||||
import {
|
||||
BlockRange,
|
||||
EtherTokenContractEventArgs,
|
||||
EtherTokenEvents,
|
||||
EventCallback,
|
||||
IndexedFilterValues,
|
||||
LogWithDecodedArgs,
|
||||
TransactionOpts,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {assert} from '../utils/assert';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {EtherTokenContract} from './generated/ether_token';
|
||||
import {TokenWrapper} from './token_wrapper';
|
||||
|
||||
/**
|
||||
@@ -14,25 +26,24 @@ import {TokenWrapper} from './token_wrapper';
|
||||
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
|
||||
*/
|
||||
export class EtherTokenWrapper extends ContractWrapper {
|
||||
private _etherTokenContractIfExists?: EtherTokenContract;
|
||||
private _etherTokenContractsByAddress: {[address: string]: EtherTokenContract} = {};
|
||||
private _tokenWrapper: TokenWrapper;
|
||||
private _contractAddressIfExists?: string;
|
||||
constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddressIfExists?: string) {
|
||||
super(web3Wrapper);
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder, tokenWrapper: TokenWrapper) {
|
||||
super(web3Wrapper, networkId, abiDecoder);
|
||||
this._tokenWrapper = tokenWrapper;
|
||||
this._contractAddressIfExists = contractAddressIfExists;
|
||||
}
|
||||
/**
|
||||
* Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens
|
||||
* to the depositor address. These wrapped ETH tokens can be used in 0x trades and are redeemable for 1-to-1
|
||||
* for ETH.
|
||||
* @param amountInWei Amount of ETH in Wei the caller wishes to deposit.
|
||||
* @param depositor The hex encoded user Ethereum address that would like to make the deposit.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @param etherTokenAddress EtherToken address you wish to deposit into.
|
||||
* @param amountInWei Amount of ETH in Wei the caller wishes to deposit.
|
||||
* @param depositor The hex encoded user Ethereum address that would like to make the deposit.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async depositAsync(
|
||||
amountInWei: BigNumber, depositor: string, txOpts: TransactionOpts = {},
|
||||
etherTokenAddress: string, amountInWei: BigNumber, depositor: string, txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||
await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
|
||||
@@ -40,7 +51,7 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(depositor);
|
||||
assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit);
|
||||
|
||||
const wethContract = await this._getEtherTokenContractAsync();
|
||||
const wethContract = await this._getEtherTokenContractAsync(etherTokenAddress);
|
||||
const txHash = await wethContract.deposit.sendTransactionAsync({
|
||||
from: depositor,
|
||||
value: amountInWei,
|
||||
@@ -52,22 +63,22 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
/**
|
||||
* Withdraw ETH to the withdrawer's address from the wrapped ETH smart contract in exchange for the
|
||||
* equivalent number of wrapped ETH tokens.
|
||||
* @param etherTokenAddress EtherToken address you wish to withdraw from.
|
||||
* @param amountInWei Amount of ETH in Wei the caller wishes to withdraw.
|
||||
* @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawl.
|
||||
* @param txOpts Transaction parameters.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
public async withdrawAsync(
|
||||
amountInWei: BigNumber, withdrawer: string, txOpts: TransactionOpts = {},
|
||||
etherTokenAddress: string, amountInWei: BigNumber, withdrawer: string, txOpts: TransactionOpts = {},
|
||||
): Promise<string> {
|
||||
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
|
||||
await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
|
||||
|
||||
const wethContractAddress = this.getContractAddress();
|
||||
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(wethContractAddress, withdrawer);
|
||||
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(etherTokenAddress, withdrawer);
|
||||
assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal);
|
||||
|
||||
const wethContract = await this._getEtherTokenContractAsync();
|
||||
const wethContract = await this._getEtherTokenContractAsync(etherTokenAddress);
|
||||
const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
|
||||
from: withdrawer,
|
||||
gas: txOpts.gasLimit,
|
||||
@@ -76,26 +87,75 @@ export class EtherTokenWrapper extends ContractWrapper {
|
||||
return txHash;
|
||||
}
|
||||
/**
|
||||
* Retrieves the Wrapped Ether token contract address
|
||||
* @return The Wrapped Ether token contract address
|
||||
* Gets historical logs without creating a subscription
|
||||
* @param etherTokenAddress An address of the ether token that emmited the logs.
|
||||
* @param eventName The ether token contract event you would like to subscribe to.
|
||||
* @param blockRange Block range to get logs from.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public getContractAddress(): string {
|
||||
const contractAddress = this._getContractAddress(
|
||||
artifacts.EtherTokenArtifact, this._contractAddressIfExists,
|
||||
public async getLogsAsync<ArgsType extends EtherTokenContractEventArgs>(
|
||||
etherTokenAddress: string, eventName: EtherTokenEvents, blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const logs = await this._getLogsAsync<ArgsType>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues, artifacts.EtherTokenArtifact.abi,
|
||||
);
|
||||
return contractAddress;
|
||||
return logs;
|
||||
}
|
||||
/**
|
||||
* Subscribe to an event type emitted by the Token contract.
|
||||
* @param etherTokenAddress The hex encoded address where the ether token is deployed.
|
||||
* @param eventName The ether token contract event you would like to subscribe to.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
|
||||
* @param callback Callback that gets called when a log is added/removed
|
||||
* @return Subscription token used later to unsubscribe
|
||||
*/
|
||||
public subscribe<ArgsType extends EtherTokenContractEventArgs>(
|
||||
etherTokenAddress: string, eventName: EtherTokenEvents, indexFilterValues: IndexedFilterValues,
|
||||
callback: EventCallback<ArgsType>): string {
|
||||
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
assert.isFunction('callback', callback);
|
||||
const subscriptionToken = this._subscribe<ArgsType>(
|
||||
etherTokenAddress, eventName, indexFilterValues, artifacts.EtherTokenArtifact.abi, callback,
|
||||
);
|
||||
return subscriptionToken;
|
||||
}
|
||||
/**
|
||||
* Cancel a subscription
|
||||
* @param subscriptionToken Subscription token returned by `subscribe()`
|
||||
*/
|
||||
public unsubscribe(subscriptionToken: string): void {
|
||||
this._unsubscribe(subscriptionToken);
|
||||
}
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
super.unsubscribeAll();
|
||||
}
|
||||
private _invalidateContractInstance(): void {
|
||||
delete this._etherTokenContractIfExists;
|
||||
this.unsubscribeAll();
|
||||
this._etherTokenContractsByAddress = {};
|
||||
}
|
||||
private async _getEtherTokenContractAsync(): Promise<EtherTokenContract> {
|
||||
if (!_.isUndefined(this._etherTokenContractIfExists)) {
|
||||
return this._etherTokenContractIfExists;
|
||||
private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<EtherTokenContract> {
|
||||
let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress];
|
||||
if (!_.isUndefined(etherTokenContract)) {
|
||||
return etherTokenContract;
|
||||
}
|
||||
const contractInstance = await this._instantiateContractIfExistsAsync<EtherTokenContract>(
|
||||
artifacts.EtherTokenArtifact, this._contractAddressIfExists,
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.EtherTokenArtifact, etherTokenAddress,
|
||||
);
|
||||
this._etherTokenContractIfExists = contractInstance;
|
||||
return this._etherTokenContractIfExists;
|
||||
const contractInstance = new EtherTokenContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
||||
etherTokenContract = contractInstance;
|
||||
this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract;
|
||||
return etherTokenContract;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
@@ -6,18 +7,16 @@ import * as Web3 from 'web3';
|
||||
import {artifacts} from '../artifacts';
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
DecodedLogArgs,
|
||||
ECSignature,
|
||||
EventCallback,
|
||||
ExchangeContract,
|
||||
ExchangeContractErrCodes,
|
||||
ExchangeContractErrs,
|
||||
ExchangeContractEventArgs,
|
||||
ExchangeEvents,
|
||||
IndexedFilterValues,
|
||||
LogCancelContractEventArgs,
|
||||
LogErrorContractEventArgs,
|
||||
LogFillContractEventArgs,
|
||||
LogWithDecodedArgs,
|
||||
MethodOpts,
|
||||
Order,
|
||||
@@ -26,9 +25,7 @@ import {
|
||||
OrderFillRequest,
|
||||
OrderTransactionOpts,
|
||||
OrderValues,
|
||||
RawLog,
|
||||
SignedOrder,
|
||||
SubscriptionOpts,
|
||||
ValidateOrderFillableOpts,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
@@ -37,9 +34,9 @@ import {decorators} from '../utils/decorators';
|
||||
import {ExchangeTransferSimulator} from '../utils/exchange_transfer_simulator';
|
||||
import {OrderValidationUtils} from '../utils/order_validation_utils';
|
||||
import {utils} from '../utils/utils';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {ExchangeContract} from './generated/exchange';
|
||||
import {TokenWrapper} from './token_wrapper';
|
||||
|
||||
const SHOULD_VALIDATE_BY_DEFAULT = true;
|
||||
@@ -84,11 +81,11 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
];
|
||||
return [orderAddresses, orderValues];
|
||||
}
|
||||
constructor(web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder,
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder,
|
||||
tokenWrapper: TokenWrapper, contractAddressIfExists?: string) {
|
||||
super(web3Wrapper, abiDecoder);
|
||||
super(web3Wrapper, networkId, abiDecoder);
|
||||
this._tokenWrapper = tokenWrapper;
|
||||
this._orderValidationUtils = new OrderValidationUtils(tokenWrapper, this);
|
||||
this._orderValidationUtils = new OrderValidationUtils(this);
|
||||
this._contractAddressIfExists = contractAddressIfExists;
|
||||
}
|
||||
/**
|
||||
@@ -165,7 +162,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.contractCallErrorHandler
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
@@ -221,7 +218,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.contractCallErrorHandler
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async fillOrdersUpToAsync(signedOrders: SignedOrder[], fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
@@ -302,7 +299,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.contractCallErrorHandler
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async batchFillOrdersAsync(orderFillRequests: OrderFillRequest[],
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
takerAddress: string,
|
||||
@@ -375,7 +372,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.contractCallErrorHandler
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async fillOrKillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
@@ -420,7 +417,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param orderTransactionOpts Optional arguments this method accepts.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.contractCallErrorHandler
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async batchFillOrKillAsync(orderFillRequests: OrderFillRequest[],
|
||||
takerAddress: string,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
@@ -488,7 +485,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param transactionOpts Optional arguments this method accepts.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.contractCallErrorHandler
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async cancelOrderAsync(order: Order|SignedOrder,
|
||||
cancelTakerTokenAmount: BigNumber,
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
@@ -529,7 +526,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
* @param transactionOpts Optional arguments this method accepts.
|
||||
* @return Transaction hash.
|
||||
*/
|
||||
@decorators.contractCallErrorHandler
|
||||
@decorators.asyncZeroExErrorHandler
|
||||
public async batchCancelOrdersAsync(orderCancellationRequests: OrderCancellationRequest[],
|
||||
orderTransactionOpts: OrderTransactionOpts = {}): Promise<string> {
|
||||
assert.doesConformToSchema('orderCancellationRequests', orderCancellationRequests,
|
||||
@@ -610,23 +607,29 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
public unsubscribe(subscriptionToken: string): void {
|
||||
this._unsubscribe(subscriptionToken);
|
||||
}
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
super.unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
* Gets historical logs without creating a subscription
|
||||
* @param eventName The exchange contract event you would like to subscribe to.
|
||||
* @param subscriptionOpts Subscriptions options that let you configure the subscription.
|
||||
* @param blockRange Block range to get logs from.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>(
|
||||
eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts, indexFilterValues: IndexedFilterValues,
|
||||
eventName: ExchangeEvents, blockRange: BlockRange, indexFilterValues: IndexedFilterValues,
|
||||
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
|
||||
assert.doesConformToSchema('subscriptionOpts', subscriptionOpts, schemas.subscriptionOptsSchema);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const exchangeContractAddress = this.getContractAddress();
|
||||
const logs = await this._getLogsAsync<ArgsType>(
|
||||
exchangeContractAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.ExchangeArtifact.abi,
|
||||
exchangeContractAddress, eventName, blockRange, indexFilterValues, artifacts.ExchangeArtifact.abi,
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
@@ -789,9 +792,10 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
if (!_.isUndefined(this._exchangeContractIfExists)) {
|
||||
return this._exchangeContractIfExists;
|
||||
}
|
||||
const contractInstance = await this._instantiateContractIfExistsAsync<ExchangeContract>(
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.ExchangeArtifact, this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new ExchangeContract(web3ContractInstance, this._web3Wrapper.getContractDefaults());
|
||||
this._exchangeContractIfExists = contractInstance;
|
||||
return this._exchangeContractIfExists;
|
||||
}
|
||||
|
6
packages/0x.js/src/contract_wrappers/generated/.gitignore
vendored
Normal file
6
packages/0x.js/src/contract_wrappers/generated/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
dummy_token.ts
|
||||
ether_token.ts
|
||||
exchange.ts
|
||||
token_registry.ts
|
||||
token_transfer_proxy.ts
|
||||
token.ts
|
@@ -0,0 +1,33 @@
|
||||
import {TxData, TxDataPayable} from '@0xproject/types';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export class BaseContract {
|
||||
protected web3ContractInstance: Web3.ContractInstance;
|
||||
protected defaults: Partial<TxData>;
|
||||
protected async applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>(
|
||||
txData: T,
|
||||
estimateGasAsync?: (txData: T) => Promise<number>,
|
||||
): Promise<TxData> {
|
||||
// Gas amount sourced with the following priorities:
|
||||
// 1. Optional param passed in to public method call
|
||||
// 2. Global config passed in at library instantiation
|
||||
// 3. Gas estimate calculation + safety margin
|
||||
const removeUndefinedProperties = _.pickBy;
|
||||
const txDataWithDefaults = {
|
||||
...removeUndefinedProperties(this.defaults),
|
||||
...removeUndefinedProperties(txData as any),
|
||||
// HACK: TS can't prove that T is spreadable.
|
||||
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
|
||||
};
|
||||
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
|
||||
const estimatedGas = await estimateGasAsync(txData);
|
||||
txDataWithDefaults.gas = estimatedGas;
|
||||
}
|
||||
return txDataWithDefaults;
|
||||
}
|
||||
constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) {
|
||||
this.web3ContractInstance = web3ContractInstance;
|
||||
this.defaults = defaults;
|
||||
}
|
||||
}
|
@@ -1,12 +1,13 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import {Token, TokenMetadata, TokenRegistryContract, ZeroExError} from '../types';
|
||||
import {Token, TokenMetadata} from '../types';
|
||||
import {assert} from '../utils/assert';
|
||||
import {constants} from '../utils/constants';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {TokenRegistryContract} from './generated/token_registry';
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with the 0x Token Registry smart contract.
|
||||
@@ -26,8 +27,8 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
};
|
||||
return token;
|
||||
}
|
||||
constructor(web3Wrapper: Web3Wrapper, contractAddressIfExists?: string) {
|
||||
super(web3Wrapper);
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
|
||||
super(web3Wrapper, networkId);
|
||||
this._contractAddressIfExists = contractAddressIfExists;
|
||||
}
|
||||
/**
|
||||
@@ -35,8 +36,6 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
* @return An array of objects that conform to the Token interface.
|
||||
*/
|
||||
public async getTokensAsync(): Promise<Token[]> {
|
||||
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
|
||||
|
||||
const addresses = await this.getTokenAddressesAsync();
|
||||
const tokenPromises: Array<Promise<Token|undefined>> = _.map(
|
||||
addresses,
|
||||
@@ -116,9 +115,12 @@ export class TokenRegistryWrapper extends ContractWrapper {
|
||||
if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
|
||||
return this._tokenRegistryContractIfExists;
|
||||
}
|
||||
const contractInstance = await this._instantiateContractIfExistsAsync<TokenRegistryContract>(
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.TokenRegistryArtifact, this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new TokenRegistryContract(
|
||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
this._tokenRegistryContractIfExists = contractInstance;
|
||||
return this._tokenRegistryContractIfExists;
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import {TokenTransferProxyContract, ZeroExError} from '../types';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {TokenTransferProxyContract} from './generated/token_transfer_proxy';
|
||||
|
||||
/**
|
||||
* This class includes the functionality related to interacting with the TokenTransferProxy contract.
|
||||
@@ -12,8 +12,8 @@ import {ContractWrapper} from './contract_wrapper';
|
||||
export class TokenTransferProxyWrapper extends ContractWrapper {
|
||||
private _tokenTransferProxyContractIfExists?: TokenTransferProxyContract;
|
||||
private _contractAddressIfExists?: string;
|
||||
constructor(web3Wrapper: Web3Wrapper, contractAddressIfExists?: string) {
|
||||
super(web3Wrapper);
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
|
||||
super(web3Wrapper, networkId);
|
||||
this._contractAddressIfExists = contractAddressIfExists;
|
||||
}
|
||||
/**
|
||||
@@ -53,9 +53,12 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
|
||||
if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
|
||||
return this._tokenTransferProxyContractIfExists;
|
||||
}
|
||||
const contractInstance = await this._instantiateContractIfExistsAsync<TokenTransferProxyContract>(
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.TokenTransferProxyArtifact, this._contractAddressIfExists,
|
||||
);
|
||||
const contractInstance = new TokenTransferProxyContract(
|
||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
this._tokenTransferProxyContractIfExists = contractInstance;
|
||||
return this._tokenTransferProxyContractIfExists;
|
||||
}
|
||||
|
@@ -1,15 +1,15 @@
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {artifacts} from '../artifacts';
|
||||
import {
|
||||
BlockRange,
|
||||
EventCallback,
|
||||
IndexedFilterValues,
|
||||
LogWithDecodedArgs,
|
||||
MethodOpts,
|
||||
SubscriptionOpts,
|
||||
TokenContract,
|
||||
TokenContractEventArgs,
|
||||
TokenEvents,
|
||||
TransactionOpts,
|
||||
@@ -18,13 +18,11 @@ import {
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {assert} from '../utils/assert';
|
||||
import {constants} from '../utils/constants';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import {TokenContract} from './generated/token';
|
||||
import {TokenTransferProxyWrapper} from './token_transfer_proxy_wrapper';
|
||||
|
||||
const ALLOWANCE_TO_ZERO_GAS_AMOUNT = 47275;
|
||||
|
||||
/**
|
||||
* This class includes all the functionality related to interacting with ERC20 token contracts.
|
||||
* All ERC20 method calls are supported, along with some convenience methods for getting/setting allowances
|
||||
@@ -34,9 +32,9 @@ export class TokenWrapper extends ContractWrapper {
|
||||
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
|
||||
private _tokenContractsByAddress: {[address: string]: TokenContract};
|
||||
private _tokenTransferProxyWrapper: TokenTransferProxyWrapper;
|
||||
constructor(web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder,
|
||||
constructor(web3Wrapper: Web3Wrapper, networkId: number, abiDecoder: AbiDecoder,
|
||||
tokenTransferProxyWrapper: TokenTransferProxyWrapper) {
|
||||
super(web3Wrapper, abiDecoder);
|
||||
super(web3Wrapper, networkId, abiDecoder);
|
||||
this._tokenContractsByAddress = {};
|
||||
this._tokenTransferProxyWrapper = tokenTransferProxyWrapper;
|
||||
}
|
||||
@@ -283,24 +281,30 @@ export class TokenWrapper extends ContractWrapper {
|
||||
public unsubscribe(subscriptionToken: string): void {
|
||||
this._unsubscribe(subscriptionToken);
|
||||
}
|
||||
/**
|
||||
* Cancels all existing subscriptions
|
||||
*/
|
||||
public unsubscribeAll(): void {
|
||||
super.unsubscribeAll();
|
||||
}
|
||||
/**
|
||||
* Gets historical logs without creating a subscription
|
||||
* @param tokenAddress An address of the token that emmited the logs.
|
||||
* @param eventName The token contract event you would like to subscribe to.
|
||||
* @param subscriptionOpts Subscriptions options that let you configure the subscription.
|
||||
* @param blockRange Block range to get logs from.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
|
||||
* @return Array of logs that match the parameters
|
||||
*/
|
||||
public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
|
||||
tokenAddress: string, eventName: TokenEvents, subscriptionOpts: SubscriptionOpts,
|
||||
tokenAddress: string, eventName: TokenEvents, blockRange: BlockRange,
|
||||
indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
|
||||
assert.isETHAddressHex('tokenAddress', tokenAddress);
|
||||
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
|
||||
assert.doesConformToSchema('subscriptionOpts', subscriptionOpts, schemas.subscriptionOptsSchema);
|
||||
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
|
||||
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
|
||||
const logs = await this._getLogsAsync<ArgsType>(
|
||||
tokenAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.TokenArtifact.abi,
|
||||
tokenAddress, eventName, blockRange, indexFilterValues, artifacts.TokenArtifact.abi,
|
||||
);
|
||||
return logs;
|
||||
}
|
||||
@@ -313,9 +317,12 @@ export class TokenWrapper extends ContractWrapper {
|
||||
if (!_.isUndefined(tokenContract)) {
|
||||
return tokenContract;
|
||||
}
|
||||
const contractInstance = await this._instantiateContractIfExistsAsync<TokenContract>(
|
||||
const web3ContractInstance = await this._instantiateContractIfExistsAsync(
|
||||
artifacts.TokenArtifact, tokenAddress,
|
||||
);
|
||||
const contractInstance = new TokenContract(
|
||||
web3ContractInstance, this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
tokenContract = contractInstance;
|
||||
this._tokenContractsByAddress[tokenAddress] = tokenContract;
|
||||
return tokenContract;
|
||||
|
6
packages/0x.js/src/globals.d.ts
vendored
6
packages/0x.js/src/globals.d.ts
vendored
@@ -39,12 +39,6 @@ declare module 'compare-versions' {
|
||||
export = compareVersions;
|
||||
}
|
||||
|
||||
// es6-promisify declarations
|
||||
declare function promisify(original: any, settings?: any): ((...arg: any[]) => Promise<any>);
|
||||
declare module 'es6-promisify' {
|
||||
export = promisify;
|
||||
}
|
||||
|
||||
declare module 'ethereumjs-abi' {
|
||||
const soliditySHA3: (argTypes: string[], args: any[]) => Buffer;
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ export {ZeroEx} from './0x';
|
||||
|
||||
export {
|
||||
Order,
|
||||
BlockParamLiteral,
|
||||
SignedOrder,
|
||||
ECSignature,
|
||||
ZeroExError,
|
||||
@@ -12,7 +13,7 @@ export {
|
||||
ExchangeEvents,
|
||||
TokenEvents,
|
||||
IndexedFilterValues,
|
||||
SubscriptionOpts,
|
||||
BlockRange,
|
||||
BlockParam,
|
||||
OrderCancellationRequest,
|
||||
OrderFillRequest,
|
||||
@@ -23,15 +24,19 @@ export {
|
||||
TransferContractEventArgs,
|
||||
ApprovalContractEventArgs,
|
||||
TokenContractEventArgs,
|
||||
EtherTokenContractEventArgs,
|
||||
WithdrawalContractEventArgs,
|
||||
DepositContractEventArgs,
|
||||
ContractEventArgs,
|
||||
ContractEventArg,
|
||||
Web3Provider,
|
||||
ZeroExConfig,
|
||||
TransactionReceipt,
|
||||
EtherTokenEvents,
|
||||
TransactionReceiptWithDecodedLogs,
|
||||
LogWithDecodedArgs,
|
||||
MethodOpts,
|
||||
OrderTransactionOpts,
|
||||
TransactionOpts,
|
||||
FilterObject,
|
||||
LogEvent,
|
||||
DecodedLogEvent,
|
||||
@@ -41,3 +46,7 @@ export {
|
||||
OrderStateInvalid,
|
||||
OrderState,
|
||||
} from './types';
|
||||
|
||||
export {
|
||||
TransactionReceipt,
|
||||
} from '@0xproject/types';
|
||||
|
@@ -1,17 +1,14 @@
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
BlockParamLiteral,
|
||||
EventCallback,
|
||||
EventWatcherCallback,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {assert} from '../utils/assert';
|
||||
import {intervalUtils} from '../utils/interval_utils';
|
||||
import {utils} from '../utils/utils';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200;
|
||||
|
||||
|
@@ -1,10 +1,9 @@
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import {RBTree} from 'bintrees';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ZeroEx} from '../0x';
|
||||
import {SignedOrder, ZeroExError} from '../types';
|
||||
import {intervalUtils} from '../utils/interval_utils';
|
||||
import {ZeroExError} from '../types';
|
||||
import {utils} from '../utils/utils';
|
||||
|
||||
const DEFAULT_EXPIRATION_MARGIN_MS = 0;
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {intervalUtils} from '@0xproject/utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {ZeroEx} from '../0x';
|
||||
import {artifacts} from '../artifacts';
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
||||
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
|
||||
@@ -11,6 +12,8 @@ import {
|
||||
ApprovalContractEventArgs,
|
||||
BlockParamLiteral,
|
||||
ContractEventArgs,
|
||||
DepositContractEventArgs,
|
||||
EtherTokenEvents,
|
||||
ExchangeContractErrs,
|
||||
ExchangeEvents,
|
||||
LogCancelContractEventArgs,
|
||||
@@ -23,15 +26,13 @@ import {
|
||||
SignedOrder,
|
||||
TokenEvents,
|
||||
TransferContractEventArgs,
|
||||
Web3Provider,
|
||||
WithdrawalContractEventArgs,
|
||||
ZeroExError,
|
||||
} from '../types';
|
||||
import {AbiDecoder} from '../utils/abi_decoder';
|
||||
import {assert} from '../utils/assert';
|
||||
import {intervalUtils} from '../utils/interval_utils';
|
||||
import {OrderStateUtils} from '../utils/order_state_utils';
|
||||
import {utils} from '../utils/utils';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
import {EventWatcher} from './event_watcher';
|
||||
import {ExpirationWatcher} from './expiration_watcher';
|
||||
@@ -245,6 +246,36 @@ export class OrderStateWatcher {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EtherTokenEvents.Deposit:
|
||||
{
|
||||
// Invalidate cache
|
||||
const args = decodedLog.args as DepositContractEventArgs;
|
||||
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
|
||||
// Revalidate orders
|
||||
makerToken = decodedLog.address;
|
||||
makerAddress = args._owner;
|
||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EtherTokenEvents.Withdrawal:
|
||||
{
|
||||
// Invalidate cache
|
||||
const args = decodedLog.args as WithdrawalContractEventArgs;
|
||||
this._balanceAndProxyAllowanceLazyStore.deleteBalance(decodedLog.address, args._owner);
|
||||
// Revalidate orders
|
||||
makerToken = decodedLog.address;
|
||||
makerAddress = args._owner;
|
||||
if (!_.isUndefined(this._dependentOrderHashes[makerAddress]) &&
|
||||
!_.isUndefined(this._dependentOrderHashes[makerAddress][makerToken])) {
|
||||
const orderHashes = Array.from(this._dependentOrderHashes[makerAddress][makerToken]);
|
||||
await this._emitRevalidateOrdersAsync(orderHashes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExchangeEvents.LogFill:
|
||||
{
|
||||
// Invalidate cache
|
||||
|
@@ -8,7 +8,6 @@ export const zeroExConfigSchema = {
|
||||
gasPrice: {$ref: '/Number'},
|
||||
exchangeContractAddress: {$ref: '/Address'},
|
||||
tokenRegistryContractAddress: {$ref: '/Address'},
|
||||
etherTokenContractAddress: {$ref: '/Address'},
|
||||
orderWatcherConfig: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
||||
import {BlockParamLiteral} from '../types';
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {BlockParamLiteral} from '../types';
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import {TransactionReceipt} from '@0xproject/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
@@ -27,6 +28,7 @@ export enum ZeroExError {
|
||||
export enum InternalZeroExError {
|
||||
NoAbiDecoder = 'NO_ABI_DECODER',
|
||||
ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY',
|
||||
WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,156 +54,6 @@ export interface DecodedLogEvent<ArgsType> {
|
||||
export type EventCallback<ArgsType> = (err: null|Error, log?: DecodedLogEvent<ArgsType>) => void;
|
||||
export type EventWatcherCallback = (log: LogEvent) => void;
|
||||
|
||||
export interface ExchangeContract extends Web3.ContractInstance {
|
||||
isValidSignature: {
|
||||
callAsync: (signerAddressHex: string, dataHex: string, v: number, r: string, s: string,
|
||||
txOpts?: TxOpts) => Promise<boolean>;
|
||||
};
|
||||
ZRX_TOKEN_CONTRACT: {
|
||||
callAsync: () => Promise<string>;
|
||||
};
|
||||
TOKEN_TRANSFER_PROXY_CONTRACT: {
|
||||
callAsync: () => Promise<string>;
|
||||
};
|
||||
getUnavailableTakerTokenAmount: {
|
||||
callAsync: (orderHash: string, defaultBlock?: Web3.BlockParam) => Promise<BigNumber>;
|
||||
};
|
||||
isRoundingError: {
|
||||
callAsync: (takerTokenFillAmount: BigNumber, takerTokenAmount: BigNumber,
|
||||
makerTokenAmount: BigNumber, txOpts?: TxOpts) => Promise<boolean>;
|
||||
};
|
||||
fillOrder: {
|
||||
sendTransactionAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
v: number, r: string, s: string, txOpts?: TxOpts) => Promise<string>;
|
||||
estimateGasAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
v: number, r: string, s: string, txOpts?: TxOpts) => Promise<number>;
|
||||
};
|
||||
batchFillOrders: {
|
||||
sendTransactionAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
|
||||
fillTakerTokenAmounts: BigNumber[],
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<string>;
|
||||
estimateGasAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
|
||||
fillTakerTokenAmounts: BigNumber[],
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
|
||||
};
|
||||
fillOrdersUpTo: {
|
||||
sendTransactionAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<string>;
|
||||
estimateGasAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
|
||||
v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
|
||||
};
|
||||
cancelOrder: {
|
||||
sendTransactionAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
|
||||
cancelTakerTokenAmount: BigNumber, txOpts?: TxOpts) => Promise<string>;
|
||||
estimateGasAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
|
||||
cancelTakerTokenAmount: BigNumber,
|
||||
txOpts?: TxOpts) => Promise<number>;
|
||||
};
|
||||
batchCancelOrders: {
|
||||
sendTransactionAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
|
||||
cancelTakerTokenAmounts: BigNumber[], txOpts?: TxOpts) => Promise<string>;
|
||||
estimateGasAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
|
||||
cancelTakerTokenAmounts: BigNumber[],
|
||||
txOpts?: TxOpts) => Promise<number>;
|
||||
};
|
||||
fillOrKillOrder: {
|
||||
sendTransactionAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
v: number, r: string, s: string, txOpts?: TxOpts) => Promise<string>;
|
||||
estimateGasAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
v: number, r: string, s: string, txOpts?: TxOpts) => Promise<number>;
|
||||
};
|
||||
batchFillOrKillOrders: {
|
||||
sendTransactionAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
|
||||
fillTakerTokenAmounts: BigNumber[],
|
||||
v: number[], r: string[], s: string[], txOpts: TxOpts) => Promise<string>;
|
||||
estimateGasAsync: (orderAddresses: OrderAddresses[], orderValues: OrderValues[],
|
||||
fillTakerTokenAmounts: BigNumber[],
|
||||
v: number[], r: string[], s: string[], txOpts?: TxOpts) => Promise<number>;
|
||||
};
|
||||
filled: {
|
||||
callAsync: (orderHash: string, defaultBlock?: Web3.BlockParam) => Promise<BigNumber>;
|
||||
};
|
||||
cancelled: {
|
||||
callAsync: (orderHash: string, defaultBlock?: Web3.BlockParam) => Promise<BigNumber>;
|
||||
};
|
||||
getOrderHash: {
|
||||
callAsync: (orderAddresses: OrderAddresses, orderValues: OrderValues) => Promise<string>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface TokenContract extends Web3.ContractInstance {
|
||||
balanceOf: {
|
||||
callAsync: (address: string, defaultBlock?: Web3.BlockParam) => Promise<BigNumber>;
|
||||
};
|
||||
allowance: {
|
||||
callAsync: (ownerAddress: string, allowedAddress: string,
|
||||
defaultBlock?: Web3.BlockParam) => Promise<BigNumber>;
|
||||
};
|
||||
transfer: {
|
||||
sendTransactionAsync: (toAddress: string, amountInBaseUnits: BigNumber,
|
||||
txOpts?: TxOpts) => Promise<string>;
|
||||
};
|
||||
transferFrom: {
|
||||
sendTransactionAsync: (fromAddress: string, toAddress: string, amountInBaseUnits: BigNumber,
|
||||
txOpts?: TxOpts) => Promise<string>;
|
||||
};
|
||||
approve: {
|
||||
sendTransactionAsync: (proxyAddress: string, amountInBaseUnits: BigNumber,
|
||||
txOpts?: TxOpts) => Promise<string>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface TokenRegistryContract extends Web3.ContractInstance {
|
||||
getTokenMetaData: {
|
||||
callAsync: (address: string) => Promise<TokenMetadata>;
|
||||
};
|
||||
getTokenAddresses: {
|
||||
callAsync: () => Promise<string[]>;
|
||||
};
|
||||
getTokenAddressBySymbol: {
|
||||
callAsync: (symbol: string) => Promise<string>;
|
||||
};
|
||||
getTokenAddressByName: {
|
||||
callAsync: (name: string) => Promise<string>;
|
||||
};
|
||||
getTokenBySymbol: {
|
||||
callAsync: (symbol: string) => Promise<TokenMetadata>;
|
||||
};
|
||||
getTokenByName: {
|
||||
callAsync: (name: string) => Promise<TokenMetadata>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface EtherTokenContract extends Web3.ContractInstance {
|
||||
deposit: {
|
||||
sendTransactionAsync: (txOpts: TxOpts) => Promise<string>;
|
||||
};
|
||||
withdraw: {
|
||||
sendTransactionAsync: (amount: BigNumber, txOpts: TxOpts) => Promise<string>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface TokenTransferProxyContract extends Web3.ContractInstance {
|
||||
getAuthorizedAddresses: {
|
||||
callAsync: () => Promise<string[]>;
|
||||
};
|
||||
authorized: {
|
||||
callAsync: (address: string) => Promise<boolean>;
|
||||
};
|
||||
}
|
||||
|
||||
export enum SolidityTypes {
|
||||
Address = 'address',
|
||||
Uint256 = 'uint256',
|
||||
@@ -295,8 +147,17 @@ export interface ApprovalContractEventArgs {
|
||||
_spender: string;
|
||||
_value: BigNumber;
|
||||
}
|
||||
export interface DepositContractEventArgs {
|
||||
_owner: string;
|
||||
_value: BigNumber;
|
||||
}
|
||||
export interface WithdrawalContractEventArgs {
|
||||
_owner: string;
|
||||
_value: BigNumber;
|
||||
}
|
||||
export type TokenContractEventArgs = TransferContractEventArgs|ApprovalContractEventArgs;
|
||||
export type ContractEventArgs = ExchangeContractEventArgs|TokenContractEventArgs;
|
||||
export type EtherTokenContractEventArgs = TokenContractEventArgs|DepositContractEventArgs|WithdrawalContractEventArgs;
|
||||
export type ContractEventArgs = ExchangeContractEventArgs|TokenContractEventArgs|EtherTokenContractEventArgs;
|
||||
export type ContractEventArg = string|BigNumber;
|
||||
|
||||
export interface Order {
|
||||
@@ -350,7 +211,14 @@ export enum TokenEvents {
|
||||
Approval = 'Approval',
|
||||
}
|
||||
|
||||
export type ContractEvents = TokenEvents|ExchangeEvents;
|
||||
export enum EtherTokenEvents {
|
||||
Transfer = 'Transfer',
|
||||
Approval = 'Approval',
|
||||
Deposit = 'Deposit',
|
||||
Withdrawal = 'Withdrawal',
|
||||
}
|
||||
|
||||
export type ContractEvents = TokenEvents|ExchangeEvents|EtherTokenEvents;
|
||||
|
||||
export interface IndexedFilterValues {
|
||||
[index: string]: ContractEventArg;
|
||||
@@ -366,7 +234,7 @@ export enum BlockParamLiteral {
|
||||
|
||||
export type BlockParam = BlockParamLiteral|number;
|
||||
|
||||
export interface SubscriptionOpts {
|
||||
export interface BlockRange {
|
||||
fromBlock: BlockParam;
|
||||
toBlock: BlockParam;
|
||||
}
|
||||
@@ -384,6 +252,7 @@ export interface OrderFillRequest {
|
||||
}
|
||||
|
||||
export type AsyncMethod = (...args: any[]) => Promise<any>;
|
||||
export type SyncMethod = (...args: any[]) => any;
|
||||
|
||||
/**
|
||||
* We re-export the `Web3.Provider` type specified in the Web3 Typescript typings
|
||||
@@ -393,10 +262,6 @@ export type AsyncMethod = (...args: any[]) => Promise<any>;
|
||||
*/
|
||||
export type Web3Provider = Web3.Provider;
|
||||
|
||||
export interface ExchangeContractByAddress {
|
||||
[address: string]: ExchangeContract;
|
||||
}
|
||||
|
||||
export interface JSONRPCPayload {
|
||||
params: any[];
|
||||
method: string;
|
||||
@@ -421,7 +286,6 @@ export interface OrderStateWatcherConfig {
|
||||
* gasPrice: Gas price to use with every transaction
|
||||
* exchangeContractAddress: The address of an exchange contract to use
|
||||
* tokenRegistryContractAddress: The address of a token registry contract to use
|
||||
* etherTokenContractAddress: The address of an ether token contract to use
|
||||
* tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use
|
||||
* orderWatcherConfig: All the configs related to the orderWatcher
|
||||
*/
|
||||
@@ -430,7 +294,6 @@ export interface ZeroExConfig {
|
||||
gasPrice?: BigNumber;
|
||||
exchangeContractAddress?: string;
|
||||
tokenRegistryContractAddress?: string;
|
||||
etherTokenContractAddress?: string;
|
||||
tokenTransferProxyContractAddress?: string;
|
||||
orderWatcherConfig?: OrderStateWatcherConfig;
|
||||
}
|
||||
@@ -539,17 +402,4 @@ export interface OrderStateInvalid {
|
||||
export type OrderState = OrderStateValid|OrderStateInvalid;
|
||||
|
||||
export type OnOrderStateChangeCallback = (orderState: OrderState) => void;
|
||||
|
||||
export interface TransactionReceipt {
|
||||
blockHash: string;
|
||||
blockNumber: number;
|
||||
transactionHash: string;
|
||||
transactionIndex: number;
|
||||
from: string;
|
||||
to: string;
|
||||
status: null|0|1;
|
||||
cumulativeGasUsed: number;
|
||||
gasUsed: number;
|
||||
contractAddress: string|null;
|
||||
logs: Web3.LogEntry[];
|
||||
} // tslint:disable:max-file-line-count
|
||||
// tslint:disable:max-file-line-count
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import {assert as sharedAssert} from '@0xproject/assert';
|
||||
import {Schema, SchemaValidator} from '@0xproject/json-schemas';
|
||||
import BigNumber from 'bignumber.js';
|
||||
// We need those two unused imports because they're actually used by sharedAssert which gets injected here
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import {Schema} from '@0xproject/json-schemas';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import * as BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ECSignature} from '../types';
|
||||
import {signatureUtils} from '../utils/signature_utils';
|
||||
import {Web3Wrapper} from '../web3_wrapper';
|
||||
|
||||
const HEX_REGEX = /^0x[0-9A-F]*$/i;
|
||||
|
||||
export const assert = {
|
||||
...sharedAssert,
|
||||
|
@@ -6,6 +6,7 @@ export const constants = {
|
||||
MAX_DIGITS_IN_UNSIGNED_256_INT: 78,
|
||||
INVALID_JUMP_PATTERN: 'invalid JUMP at',
|
||||
OUT_OF_GAS_PATTERN: 'out of gas',
|
||||
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
|
||||
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
|
||||
DEFAULT_BLOCK_POLLING_INTERVAL: 1000,
|
||||
};
|
||||
|
@@ -1,17 +1,37 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import {AsyncMethod, ZeroExError} from '../types';
|
||||
import {AsyncMethod, SyncMethod, ZeroExError} from '../types';
|
||||
|
||||
import {constants} from './constants';
|
||||
|
||||
export const decorators = {
|
||||
/**
|
||||
* Source: https://stackoverflow.com/a/29837695/3546986
|
||||
*/
|
||||
contractCallErrorHandler(target: object,
|
||||
key: string|symbol,
|
||||
descriptor: TypedPropertyDescriptor<AsyncMethod>,
|
||||
): TypedPropertyDescriptor<AsyncMethod> {
|
||||
type ErrorTransformer = (err: Error) => Error;
|
||||
|
||||
const contractCallErrorTransformer = (error: Error) => {
|
||||
if (_.includes(error.message, constants.INVALID_JUMP_PATTERN)) {
|
||||
return new Error(ZeroExError.InvalidJump);
|
||||
}
|
||||
if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) {
|
||||
return new Error(ZeroExError.OutOfGas);
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
const schemaErrorTransformer = (error: Error) => {
|
||||
if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
const errMsg = 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
return new Error(errMsg);
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
/**
|
||||
* Source: https://stackoverflow.com/a/29837695/3546986
|
||||
*/
|
||||
const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
||||
const asyncErrorHandlingDecorator = (
|
||||
target: object, key: string|symbol, descriptor: TypedPropertyDescriptor<AsyncMethod>,
|
||||
) => {
|
||||
const originalMethod = (descriptor.value as AsyncMethod);
|
||||
|
||||
// Do not use arrow syntax here. Use a function expression in
|
||||
@@ -22,16 +42,46 @@ export const decorators = {
|
||||
const result = await originalMethod.apply(this, args);
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (_.includes(error.message, constants.INVALID_JUMP_PATTERN)) {
|
||||
throw new Error(ZeroExError.InvalidJump);
|
||||
}
|
||||
if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) {
|
||||
throw new Error(ZeroExError.OutOfGas);
|
||||
}
|
||||
throw error;
|
||||
const transformedError = errorTransformer(error);
|
||||
throw transformedError;
|
||||
}
|
||||
};
|
||||
|
||||
return descriptor;
|
||||
},
|
||||
};
|
||||
|
||||
return asyncErrorHandlingDecorator;
|
||||
};
|
||||
|
||||
const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
|
||||
const syncErrorHandlingDecorator = (
|
||||
target: object, key: string|symbol, descriptor: TypedPropertyDescriptor<SyncMethod>,
|
||||
) => {
|
||||
const originalMethod = (descriptor.value as SyncMethod);
|
||||
|
||||
// Do not use arrow syntax here. Use a function expression in
|
||||
// order to use the correct value of `this` in this method
|
||||
// tslint:disable-next-line:only-arrow-functions
|
||||
descriptor.value = function(...args: any[]) {
|
||||
try {
|
||||
const result = originalMethod.apply(this, args);
|
||||
return result;
|
||||
} catch (error) {
|
||||
const transformedError = errorTransformer(error);
|
||||
throw transformedError;
|
||||
}
|
||||
};
|
||||
|
||||
return descriptor;
|
||||
};
|
||||
|
||||
return syncErrorHandlingDecorator;
|
||||
};
|
||||
|
||||
// _.flow(f, g) = f ∘ g
|
||||
const zeroExErrorTransformer = _.flow(schemaErrorTransformer, contractCallErrorTransformer);
|
||||
|
||||
export const decorators = {
|
||||
asyncZeroExErrorHandler: asyncErrorHandlerFactory(zeroExErrorTransformer),
|
||||
syncZeroExErrorHandler: syncErrorHandlerFactory(zeroExErrorTransformer),
|
||||
};
|
||||
|
@@ -4,7 +4,7 @@ import * as _ from 'lodash';
|
||||
import * as uuid from 'uuid/v4';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ContractEvents, IndexedFilterValues, SubscriptionOpts} from '../types';
|
||||
import {BlockRange, ContractEvents, IndexedFilterValues} from '../types';
|
||||
|
||||
const TOPIC_LENGTH = 32;
|
||||
|
||||
@@ -14,7 +14,7 @@ export const filterUtils = {
|
||||
},
|
||||
getFilter(address: string, eventName: ContractEvents,
|
||||
indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi,
|
||||
subscriptionOpts?: SubscriptionOpts): Web3.FilterObject {
|
||||
blockRange?: BlockRange): Web3.FilterObject {
|
||||
const eventAbi = _.find(abi, {name: eventName}) as Web3.EventAbi;
|
||||
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi, eventName);
|
||||
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
|
||||
@@ -24,9 +24,9 @@ export const filterUtils = {
|
||||
address,
|
||||
topics,
|
||||
};
|
||||
if (!_.isUndefined(subscriptionOpts)) {
|
||||
if (!_.isUndefined(blockRange)) {
|
||||
filter = {
|
||||
...subscriptionOpts,
|
||||
...blockRange,
|
||||
...filter,
|
||||
};
|
||||
}
|
||||
|
@@ -1,24 +1,19 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as _ from 'lodash';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ZeroEx} from '../0x';
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
||||
import {RemainingFillableCalculator} from '../order_watcher/remaining_fillable_calculator';
|
||||
import {BalanceAndProxyAllowanceLazyStore} from '../stores/balance_proxy_allowance_lazy_store';
|
||||
import {OrderFilledCancelledLazyStore} from '../stores/order_filled_cancelled_lazy_store';
|
||||
import {
|
||||
ExchangeContractErrs,
|
||||
MethodOpts,
|
||||
OrderRelevantState,
|
||||
OrderState,
|
||||
OrderStateInvalid,
|
||||
OrderStateValid,
|
||||
SignedOrder,
|
||||
} from '../types';
|
||||
import {constants} from '../utils/constants';
|
||||
import {utils} from '../utils/utils';
|
||||
|
||||
const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
|
||||
|
||||
|
@@ -3,7 +3,6 @@ import * as _ from 'lodash';
|
||||
|
||||
import {ZeroEx} from '../0x';
|
||||
import {ExchangeWrapper} from '../contract_wrappers/exchange_wrapper';
|
||||
import {TokenWrapper} from '../contract_wrappers/token_wrapper';
|
||||
import {ExchangeContractErrs, Order, SignedOrder, TradeSide, TransferType, ZeroExError} from '../types';
|
||||
import {constants} from '../utils/constants';
|
||||
import {utils} from '../utils/utils';
|
||||
@@ -11,7 +10,6 @@ import {utils} from '../utils/utils';
|
||||
import {ExchangeTransferSimulator} from './exchange_transfer_simulator';
|
||||
|
||||
export class OrderValidationUtils {
|
||||
private tokenWrapper: TokenWrapper;
|
||||
private exchangeWrapper: ExchangeWrapper;
|
||||
public static validateCancelOrderThrowIfInvalid(
|
||||
order: Order, cancelTakerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
|
||||
@@ -84,8 +82,7 @@ export class OrderValidationUtils {
|
||||
.round(0);
|
||||
return fillMakerTokenAmount;
|
||||
}
|
||||
constructor(tokenWrapper: TokenWrapper, exchangeWrapper: ExchangeWrapper) {
|
||||
this.tokenWrapper = tokenWrapper;
|
||||
constructor(exchangeWrapper: ExchangeWrapper) {
|
||||
this.exchangeWrapper = exchangeWrapper;
|
||||
}
|
||||
public async validateOrderFillableOrThrowAsync(
|
||||
|
@@ -1,18 +1,18 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
|
||||
import {ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx, ZeroExError} from '../src';
|
||||
import {ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx} from '../src';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
@@ -82,9 +82,9 @@ describe('ZeroEx library', () => {
|
||||
it('should return true if the signature does pertain to the dataHex & address', async () => {
|
||||
const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address);
|
||||
expect(isValidSignatureLocal).to.be.true();
|
||||
const isValidSignatureOnContract = await (zeroEx.exchange as any)
|
||||
._isValidSignatureUsingContractCallAsync(dataHex, signature, address);
|
||||
return expect(isValidSignatureOnContract).to.be.true();
|
||||
return expect(
|
||||
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address),
|
||||
).to.become(true);
|
||||
});
|
||||
});
|
||||
describe('#generateSalt', () => {
|
||||
@@ -152,6 +152,15 @@ describe('ZeroEx library', () => {
|
||||
const orderHash = ZeroEx.getOrderHashHex(order);
|
||||
expect(orderHash).to.be.equal(expectedOrderHash);
|
||||
});
|
||||
it('throws a readable error message if taker format is invalid', async () => {
|
||||
const orderWithInvalidtakerFormat = {
|
||||
...order,
|
||||
taker: null as any as string,
|
||||
};
|
||||
// tslint:disable-next-line:max-line-length
|
||||
const expectedErrorMessage = 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
|
||||
expect(() => ZeroEx.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage);
|
||||
});
|
||||
});
|
||||
describe('#signOrderHashAsync', () => {
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
@@ -244,14 +253,6 @@ describe('ZeroEx library', () => {
|
||||
const zeroExWithWrongExchangeAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
|
||||
});
|
||||
it('allows to specify ether token contract address', async () => {
|
||||
const zeroExConfig = {
|
||||
etherTokenContractAddress: ZeroEx.NULL_ADDRESS,
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const zeroExWithWrongEtherTokenAddress = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||
expect(zeroExWithWrongEtherTokenAddress.etherToken.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
|
||||
});
|
||||
it('allows to specify token registry token contract address', async () => {
|
||||
const zeroExConfig = {
|
||||
tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS,
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import * as chai from 'chai';
|
||||
import * as fs from 'fs';
|
||||
import HDWalletProvider = require('truffle-hdwallet-provider');
|
||||
|
||||
@@ -8,7 +7,6 @@ import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
// Those tests are slower cause they're talking to a remote node
|
||||
const TIMEOUT = 10000;
|
||||
|
@@ -1,18 +1,33 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ZeroEx, ZeroExError} from '../src';
|
||||
import {
|
||||
ApprovalContractEventArgs,
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
DecodedLogEvent,
|
||||
DepositContractEventArgs,
|
||||
EtherTokenEvents,
|
||||
Token,
|
||||
TransferContractEventArgs,
|
||||
WithdrawalContractEventArgs,
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {artifacts} from '../src/artifacts';
|
||||
import {DoneCallback} from '../src/types';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
// Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction,
|
||||
// a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between
|
||||
@@ -23,24 +38,32 @@ const MAX_REASONABLE_GAS_COST_IN_WEI = 62517;
|
||||
describe('EtherTokenWrapper', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let tokens: Token[];
|
||||
let userAddresses: string[];
|
||||
let addressWithETH: string;
|
||||
let wethContractAddress: string;
|
||||
let depositWeiAmount: BigNumber;
|
||||
let decimalPlaces: number;
|
||||
let addressWithoutFunds: string;
|
||||
const gasPrice = new BigNumber(1);
|
||||
const zeroExConfig = {
|
||||
gasPrice,
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
const transferAmount = new BigNumber(42);
|
||||
const allowanceAmount = new BigNumber(42);
|
||||
const depositAmount = new BigNumber(42);
|
||||
const withdrawalAmount = new BigNumber(42);
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider, zeroExConfig);
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
addressWithETH = userAddresses[0];
|
||||
wethContractAddress = zeroEx.etherToken.getContractAddress();
|
||||
wethContractAddress = (zeroEx.etherToken as any)._getContractAddress(artifacts.EtherTokenArtifact);
|
||||
depositWeiAmount = (zeroEx as any)._web3Wrapper.toWei(new BigNumber(5));
|
||||
decimalPlaces = 7;
|
||||
addressWithoutFunds = userAddresses[1];
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
@@ -55,7 +78,7 @@ describe('EtherTokenWrapper', () => {
|
||||
expect(preETHBalance).to.be.bignumber.gt(0);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(0);
|
||||
|
||||
const txHash = await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH);
|
||||
const txHash = await zeroEx.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const postETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
@@ -73,7 +96,7 @@ describe('EtherTokenWrapper', () => {
|
||||
const overETHBalanceinWei = preETHBalance.add(extraETHBalance);
|
||||
|
||||
return expect(
|
||||
zeroEx.etherToken.depositAsync(overETHBalanceinWei, addressWithETH),
|
||||
zeroEx.etherToken.depositAsync(wethContractAddress, overETHBalanceinWei, addressWithETH),
|
||||
).to.be.rejectedWith(ZeroExError.InsufficientEthBalanceForDeposit);
|
||||
});
|
||||
});
|
||||
@@ -81,7 +104,7 @@ describe('EtherTokenWrapper', () => {
|
||||
it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => {
|
||||
const ETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
|
||||
await zeroEx.etherToken.depositAsync(depositWeiAmount, addressWithETH);
|
||||
await zeroEx.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH);
|
||||
|
||||
const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount);
|
||||
const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
@@ -90,7 +113,7 @@ describe('EtherTokenWrapper', () => {
|
||||
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
|
||||
expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount);
|
||||
|
||||
const txHash = await zeroEx.etherToken.withdrawAsync(depositWeiAmount, addressWithETH);
|
||||
const txHash = await zeroEx.etherToken.withdrawAsync(wethContractAddress, depositWeiAmount, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
|
||||
const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH);
|
||||
@@ -108,8 +131,213 @@ describe('EtherTokenWrapper', () => {
|
||||
const overWETHBalance = preWETHBalance.add(999999999);
|
||||
|
||||
return expect(
|
||||
zeroEx.etherToken.withdrawAsync(overWETHBalance, addressWithETH),
|
||||
zeroEx.etherToken.withdrawAsync(wethContractAddress, overWETHBalance, addressWithETH),
|
||||
).to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal);
|
||||
});
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
let etherTokenAddress: string;
|
||||
before(() => {
|
||||
const tokenUtils = new TokenUtils(tokens);
|
||||
const etherToken = tokenUtils.getWethTokenOrThrow();
|
||||
etherTokenAddress = etherToken.address;
|
||||
});
|
||||
afterEach(() => {
|
||||
zeroEx.etherToken.unsubscribeAll();
|
||||
});
|
||||
// Hack: Mocha does not allow a test to be both async and have a `done` callback
|
||||
// Since we need to await the receipt of the event in the `subscribe` callback,
|
||||
// we do need both. A hack is to make the top-level async fn w/ a done callback and then
|
||||
// wrap the rest of the test in an async block
|
||||
// Source: https://github.com/mochajs/mocha/issues/2407
|
||||
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
|
||||
expect(err).to.be.null();
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
expect(logEvent.log.logIndex).to.be.equal(0);
|
||||
expect(logEvent.log.transactionIndex).to.be.equal(0);
|
||||
expect(logEvent.log.blockNumber).to.be.a('number');
|
||||
const args = logEvent.log.args;
|
||||
expect(args._from).to.be.equal(addressWithETH);
|
||||
expect(args._to).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(transferAmount);
|
||||
done();
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
expect(err).to.be.null();
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._spender).to.be.equal(addressWithoutFunds);
|
||||
expect(args._value).to.be.bignumber.equal(allowanceAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback);
|
||||
await zeroEx.token.setAllowanceAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, allowanceAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<DepositContractEventArgs>) => {
|
||||
expect(err).to.be.null();
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
done();
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback);
|
||||
await zeroEx.etherToken.depositAsync(
|
||||
etherTokenAddress, depositAmount, addressWithETH,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callback = (err: Error, logEvent: DecodedLogEvent<WithdrawalContractEventArgs>) => {
|
||||
expect(err).to.be.null();
|
||||
expect(logEvent).to.not.be.undefined();
|
||||
expect(logEvent.isRemoved).to.be.false();
|
||||
const args = logEvent.log.args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
done();
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(
|
||||
etherTokenAddress, depositAmount, addressWithETH,
|
||||
);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Withdrawal, indexFilterValues, callback);
|
||||
await zeroEx.etherToken.withdrawAsync(
|
||||
etherTokenAddress, withdrawalAmount, addressWithETH,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled,
|
||||
);
|
||||
const callbackToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done();
|
||||
};
|
||||
const newProvider = web3Factory.getRpcProvider();
|
||||
zeroEx.setProvider(newProvider, constants.TESTRPC_NETWORK_ID);
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackToBeCalled,
|
||||
);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const callbackNeverToBeCalled = (err: Error, logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
};
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
|
||||
const subscriptionToken = zeroEx.etherToken.subscribe(
|
||||
etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled);
|
||||
zeroEx.etherToken.unsubscribe(subscriptionToken);
|
||||
await zeroEx.token.transferAsync(
|
||||
etherTokenAddress, addressWithETH, addressWithoutFunds, transferAmount,
|
||||
);
|
||||
done();
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
describe('#getLogsAsync', () => {
|
||||
let etherTokenAddress: string;
|
||||
let tokenTransferProxyAddress: string;
|
||||
const blockRange: BlockRange = {
|
||||
fromBlock: 0,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
let txHash: string;
|
||||
before(() => {
|
||||
addressWithETH = userAddresses[0];
|
||||
const tokenUtils = new TokenUtils(tokens);
|
||||
const etherToken = tokenUtils.getWethTokenOrThrow();
|
||||
etherTokenAddress = etherToken.address;
|
||||
tokenTransferProxyAddress = zeroEx.proxy.getContractAddress();
|
||||
});
|
||||
it('should get logs with decoded args emitted by Approval', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = EtherTokenEvents.Approval;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._spender).to.be.equal(tokenTransferProxyAddress);
|
||||
expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
it('should get logs with decoded args emitted by Deposit', async () => {
|
||||
await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
|
||||
const eventName = EtherTokenEvents.Deposit;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<DepositContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
expect(args._value).to.be.bignumber.equal(depositAmount);
|
||||
});
|
||||
it('should only get the logs with the correct event name', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const differentEventName = EtherTokenEvents.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync(
|
||||
etherTokenAddress, differentEventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithoutFunds);
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = EtherTokenEvents.Approval;
|
||||
const indexFilterValues = {
|
||||
_owner: addressWithETH,
|
||||
};
|
||||
const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>(
|
||||
etherTokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
expect(args._owner).to.be.equal(addressWithETH);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
@@ -6,16 +6,12 @@ import * as Sinon from 'sinon';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
DecodedLogEvent,
|
||||
LogEvent,
|
||||
ZeroEx,
|
||||
} from '../src';
|
||||
import {EventWatcher} from '../src/order_watcher/event_watcher';
|
||||
import {DoneCallback} from '../src/types';
|
||||
import {Web3Wrapper} from '../src/web3_wrapper';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
@@ -26,7 +22,6 @@ describe('EventWatcher', () => {
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
let eventWatcher: EventWatcher;
|
||||
let web3Wrapper: Web3Wrapper;
|
||||
const numConfirmations = 0;
|
||||
const logA: Web3.LogEntry = {
|
||||
address: '0x71d271f8b14adef568f8f28f1587ce7271ac4ca5',
|
||||
blockHash: null,
|
||||
@@ -60,7 +55,7 @@ describe('EventWatcher', () => {
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
const pollingIntervalMs = 10;
|
||||
web3Wrapper = new Web3Wrapper(web3.currentProvider, constants.TESTRPC_NETWORK_ID);
|
||||
web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
||||
eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalMs);
|
||||
});
|
||||
afterEach(() => {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
|
||||
@@ -5,14 +6,13 @@ import {ExchangeContractErrs, Token, ZeroEx} from '../src';
|
||||
import {BlockParamLiteral, TradeSide, TransferType} from '../src/types';
|
||||
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('ExchangeTransferSimulator', () => {
|
||||
const web3 = web3Factory.create();
|
||||
|
@@ -1,25 +1,24 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
BlockRange,
|
||||
DecodedLogEvent,
|
||||
ExchangeContractErrs,
|
||||
ExchangeEvents,
|
||||
LogCancelContractEventArgs,
|
||||
LogEvent,
|
||||
LogFillContractEventArgs,
|
||||
OrderCancellationRequest,
|
||||
OrderFillRequest,
|
||||
SignedOrder,
|
||||
SubscriptionOpts,
|
||||
Token,
|
||||
ZeroEx,
|
||||
} from '../src';
|
||||
import {BlockParamLiteral, DoneCallback} from '../src/types';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
@@ -28,7 +27,7 @@ import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
const NON_EXISTENT_ORDER_HASH = '0x79370342234e7acd6bbeac335bd3bb1d368383294b64b8160a00f4060e4d3777';
|
||||
|
||||
@@ -53,6 +52,7 @@ describe('ExchangeWrapper', () => {
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
await fillScenarios.initTokenBalancesAsync();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
@@ -71,7 +71,7 @@ describe('ExchangeWrapper', () => {
|
||||
before(async () => {
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
@@ -201,7 +201,7 @@ describe('ExchangeWrapper', () => {
|
||||
before(async () => {
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
@@ -436,7 +436,7 @@ describe('ExchangeWrapper', () => {
|
||||
const cancelAmount = new BigNumber(3);
|
||||
beforeEach(async () => {
|
||||
[coinbase, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
@@ -557,7 +557,8 @@ describe('ExchangeWrapper', () => {
|
||||
let orderHash: string;
|
||||
before(() => {
|
||||
takerAddress = userAddresses[1];
|
||||
const [makerToken, takerToken] = tokens;
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
@@ -633,7 +634,7 @@ describe('ExchangeWrapper', () => {
|
||||
const cancelTakerAmountInBaseUnits = new BigNumber(1);
|
||||
before(() => {
|
||||
[coinbase, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokens;
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
@@ -731,7 +732,7 @@ describe('ExchangeWrapper', () => {
|
||||
const fillableAmount = new BigNumber(5);
|
||||
before(async () => {
|
||||
[, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
@@ -759,14 +760,14 @@ describe('ExchangeWrapper', () => {
|
||||
let takerAddress: string;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
const subscriptionOpts: SubscriptionOpts = {
|
||||
const blockRange: BlockRange = {
|
||||
fromBlock: 0,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
let txHash: string;
|
||||
before(async () => {
|
||||
[, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
@@ -780,7 +781,7 @@ describe('ExchangeWrapper', () => {
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const eventName = ExchangeEvents.LogFill;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.exchange.getLogsAsync(eventName, subscriptionOpts, indexFilterValues);
|
||||
const logs = await zeroEx.exchange.getLogsAsync(eventName, blockRange, indexFilterValues);
|
||||
expect(logs).to.have.length(1);
|
||||
expect(logs[0].event).to.be.equal(eventName);
|
||||
});
|
||||
@@ -794,7 +795,7 @@ describe('ExchangeWrapper', () => {
|
||||
await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
const differentEventName = ExchangeEvents.LogCancel;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.exchange.getLogsAsync(differentEventName, subscriptionOpts, indexFilterValues);
|
||||
const logs = await zeroEx.exchange.getLogsAsync(differentEventName, blockRange, indexFilterValues);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
it('should only get the logs with the correct indexed fields', async () => {
|
||||
@@ -820,7 +821,7 @@ describe('ExchangeWrapper', () => {
|
||||
maker: differentMakerAddress,
|
||||
};
|
||||
const logs = await zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
|
||||
eventName, subscriptionOpts, indexFilterValues,
|
||||
eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
@@ -10,10 +11,9 @@ 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 {Web3Wrapper} from '../src/web3_wrapper';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants as testConstants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
@@ -21,7 +21,7 @@ import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(testConstants.RPC_URL);
|
||||
|
||||
describe('ExpirationWatcher', () => {
|
||||
let web3: Web3;
|
||||
@@ -56,7 +56,7 @@ describe('ExpirationWatcher', () => {
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
});
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
@@ -5,23 +6,17 @@ import 'mocha';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
DecodedLogEvent,
|
||||
ExchangeContractErrs,
|
||||
LogEvent,
|
||||
OrderState,
|
||||
OrderStateInvalid,
|
||||
OrderStateValid,
|
||||
SignedOrder,
|
||||
Token,
|
||||
ZeroEx,
|
||||
ZeroExConfig,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {OrderStateWatcher} from '../src/order_watcher/order_state_watcher';
|
||||
import {DoneCallback} from '../src/types';
|
||||
import {Web3Wrapper} from '../src/web3_wrapper';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
@@ -33,7 +28,7 @@ const TIMEOUT_MS = 150;
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('OrderStateWatcher', () => {
|
||||
let web3: Web3;
|
||||
@@ -48,7 +43,6 @@ describe('OrderStateWatcher', () => {
|
||||
let takerToken: Token;
|
||||
let maker: string;
|
||||
let taker: string;
|
||||
let web3Wrapper: Web3Wrapper;
|
||||
let signedOrder: SignedOrder;
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
@@ -65,8 +59,8 @@ describe('OrderStateWatcher', () => {
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
[makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
web3Wrapper = (zeroEx as any)._web3Wrapper;
|
||||
await fillScenarios.initTokenBalancesAsync();
|
||||
[makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
@@ -141,7 +135,6 @@ describe('OrderStateWatcher', () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
throw new Error('OrderState callback fired for irrelevant order');
|
||||
@@ -150,7 +143,6 @@ describe('OrderStateWatcher', () => {
|
||||
const notTheMaker = userAddresses[0];
|
||||
const anyRecipient = taker;
|
||||
const transferAmount = new BigNumber(2);
|
||||
const notTheMakerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, notTheMaker);
|
||||
await zeroEx.token.transferAsync(makerToken.address, notTheMaker, anyRecipient, transferAmount);
|
||||
setTimeout(() => {
|
||||
done();
|
||||
@@ -207,8 +199,6 @@ describe('OrderStateWatcher', () => {
|
||||
);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
const takerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, taker);
|
||||
|
||||
const fillAmountInBaseUnits = new BigNumber(2);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -241,11 +231,10 @@ describe('OrderStateWatcher', () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker, taker, fillableAmount,
|
||||
taker);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
done();
|
||||
});
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0));
|
||||
})().catch(done);
|
||||
@@ -259,8 +248,6 @@ describe('OrderStateWatcher', () => {
|
||||
makerToken.address, takerToken.address, maker, taker, makerFillableAmount,
|
||||
takerFillableAmount,
|
||||
);
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
const takerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, taker);
|
||||
const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -288,8 +275,6 @@ describe('OrderStateWatcher', () => {
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
|
||||
const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
@@ -342,8 +327,6 @@ describe('OrderStateWatcher', () => {
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
|
||||
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
||||
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
@@ -369,10 +352,7 @@ describe('OrderStateWatcher', () => {
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
|
||||
const remainingFeeAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||
const transferFeeAmount = makerFee.sub(remainingFeeAmount);
|
||||
|
||||
const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals);
|
||||
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
||||
@@ -400,7 +380,6 @@ describe('OrderStateWatcher', () => {
|
||||
makerToken.address, takerToken.address, makerFee, takerFee, maker,
|
||||
taker, fillableAmount, feeRecipient);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
||||
const callback = reportCallbackErrors(done)((orderState: OrderState) => {
|
||||
@@ -433,7 +412,6 @@ describe('OrderStateWatcher', () => {
|
||||
});
|
||||
zeroEx.orderStateWatcher.subscribe(callback);
|
||||
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount);
|
||||
})().catch(done);
|
||||
});
|
||||
@@ -465,9 +443,6 @@ describe('OrderStateWatcher', () => {
|
||||
makerToken.address, takerToken.address, maker, taker, fillableAmount,
|
||||
);
|
||||
|
||||
const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker);
|
||||
const takerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, taker);
|
||||
|
||||
const cancelAmountInBaseUnits = new BigNumber(2);
|
||||
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
|
||||
zeroEx.orderStateWatcher.addOrder(signedOrder);
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import * as Sinon from 'sinon';
|
||||
@@ -8,7 +9,6 @@ import {BlockParamLiteral, TradeSide, TransferType} from '../src/types';
|
||||
import {ExchangeTransferSimulator} from '../src/utils/exchange_transfer_simulator';
|
||||
import {OrderValidationUtils} from '../src/utils/order_validation_utils';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {FillScenarios} from './utils/fill_scenarios';
|
||||
@@ -17,7 +17,7 @@ import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('OrderValidation', () => {
|
||||
let web3: Web3;
|
||||
@@ -34,7 +34,6 @@ describe('OrderValidation', () => {
|
||||
let makerAddress: string;
|
||||
let takerAddress: string;
|
||||
let feeRecipient: string;
|
||||
let orderValidationUtils: OrderValidationUtils;
|
||||
const fillableAmount = new BigNumber(5);
|
||||
const fillTakerAmount = new BigNumber(5);
|
||||
const config = {
|
||||
@@ -50,10 +49,9 @@ describe('OrderValidation', () => {
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
orderValidationUtils = new OrderValidationUtils(zeroEx.token, zeroEx.exchange);
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
@@ -181,17 +179,15 @@ describe('OrderValidation', () => {
|
||||
});
|
||||
describe('validateCancelOrderAndThrowIfInvalidAsync', () => {
|
||||
let signedOrder: SignedOrder;
|
||||
let orderHashHex: string;
|
||||
const cancelAmount = new BigNumber(3);
|
||||
beforeEach(async () => {
|
||||
[coinbase, makerAddress, takerAddress] = userAddresses;
|
||||
const [makerToken, takerToken] = tokenUtils.getNonProtocolTokens();
|
||||
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
|
||||
makerTokenAddress = makerToken.address;
|
||||
takerTokenAddress = takerToken.address;
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
|
||||
);
|
||||
orderHashHex = ZeroEx.getOrderHashHex(signedOrder);
|
||||
});
|
||||
it('should throw when cancel amount is zero', async () => {
|
||||
const zeroCancelAmount = new BigNumber(0);
|
||||
@@ -204,7 +200,6 @@ describe('OrderValidation', () => {
|
||||
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress,
|
||||
fillableAmount, expirationInPast,
|
||||
);
|
||||
orderHashHex = ZeroEx.getOrderHashHex(expiredSignedOrder);
|
||||
return expect(zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount))
|
||||
.to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
|
||||
});
|
||||
|
@@ -2,12 +2,11 @@ import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import 'mocha';
|
||||
|
||||
import { ZeroEx } from '../src/0x';
|
||||
import { RemainingFillableCalculator } from '../src/order_watcher/remaining_fillable_calculator';
|
||||
import { ECSignature, SignedOrder } from '../src/types';
|
||||
import {ZeroEx} from '../src/0x';
|
||||
import {RemainingFillableCalculator} from '../src/order_watcher/remaining_fillable_calculator';
|
||||
import {ECSignature, SignedOrder} from '../src/types';
|
||||
|
||||
import { chaiSetup } from './utils/chai_setup';
|
||||
import { TokenUtils } from './utils/token_utils';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
@@ -27,7 +26,7 @@ describe('RemainingFillableCalculator', () => {
|
||||
const decimals: number = 4;
|
||||
const zero: BigNumber = new BigNumber(0);
|
||||
const zeroAddress = '0x0';
|
||||
const signature: ECSignature = { v: 27, r: '', s: ''};
|
||||
const signature: ECSignature = {v: 27, r: '', s: ''};
|
||||
beforeEach(async () => {
|
||||
[makerAmount, takerAmount, makerFeeAmount] = [ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals),
|
||||
ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals),
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import promisify = require('es6-promisify');
|
||||
import * as _ from 'lodash';
|
||||
import 'mocha';
|
||||
import * as Sinon from 'sinon';
|
||||
@@ -12,27 +12,23 @@ import {
|
||||
Token,
|
||||
TokenEvents,
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {BlockParamLiteral, DoneCallback} from '../src/types';
|
||||
import {DoneCallback} from '../src/types';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {reportCallbackErrors} from './utils/report_callback_errors';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('SubscriptionTest', () => {
|
||||
let web3: Web3;
|
||||
let zeroEx: ZeroEx;
|
||||
let userAddresses: string[];
|
||||
let tokens: Token[];
|
||||
let tokenUtils: TokenUtils;
|
||||
let coinbase: string;
|
||||
let addressWithoutFunds: string;
|
||||
const config = {
|
||||
@@ -43,7 +39,6 @@ describe('SubscriptionTest', () => {
|
||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
coinbase = userAddresses[0];
|
||||
addressWithoutFunds = userAddresses[1];
|
||||
});
|
||||
@@ -55,9 +50,7 @@ describe('SubscriptionTest', () => {
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
let tokenAddress: string;
|
||||
const transferAmount = new BigNumber(42);
|
||||
const allowanceAmount = new BigNumber(42);
|
||||
let stubs: Sinon.SinonStub[] = [];
|
||||
before(() => {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import {schemas, SchemaValidator} from '@0xproject/json-schemas';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
@@ -5,14 +6,13 @@ import 'mocha';
|
||||
|
||||
import {Token, ZeroEx} from '../src';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7;
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import * as chai from 'chai';
|
||||
|
||||
import {ZeroEx} from '../src';
|
||||
import {TokenTransferProxyWrapper} from '../src/contract_wrappers/token_transfer_proxy_wrapper';
|
||||
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
|
@@ -1,26 +1,23 @@
|
||||
import {BlockchainLifecycle} from '@0xproject/dev-utils';
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as chai from 'chai';
|
||||
import promisify = require('es6-promisify');
|
||||
import 'mocha';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {
|
||||
ApprovalContractEventArgs,
|
||||
ContractEvent,
|
||||
BlockParamLiteral,
|
||||
BlockRange,
|
||||
DecodedLogEvent,
|
||||
LogEvent,
|
||||
LogWithDecodedArgs,
|
||||
SubscriptionOpts,
|
||||
Token,
|
||||
TokenContractEventArgs,
|
||||
TokenEvents,
|
||||
TransferContractEventArgs,
|
||||
ZeroEx,
|
||||
ZeroExError,
|
||||
} from '../src';
|
||||
import {BlockParamLiteral, DoneCallback} from '../src/types';
|
||||
import {DoneCallback} from '../src/types';
|
||||
|
||||
import {BlockchainLifecycle} from './utils/blockchain_lifecycle';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import {constants} from './utils/constants';
|
||||
import {TokenUtils} from './utils/token_utils';
|
||||
@@ -28,7 +25,7 @@ import {web3Factory} from './utils/web3_factory';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle();
|
||||
const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL);
|
||||
|
||||
describe('TokenWrapper', () => {
|
||||
let web3: Web3;
|
||||
@@ -38,12 +35,14 @@ describe('TokenWrapper', () => {
|
||||
let tokenUtils: TokenUtils;
|
||||
let coinbase: string;
|
||||
let addressWithoutFunds: string;
|
||||
let web3Wrapper: Web3Wrapper;
|
||||
const config = {
|
||||
networkId: constants.TESTRPC_NETWORK_ID,
|
||||
};
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider, config);
|
||||
web3Wrapper = new Web3Wrapper(web3.currentProvider);
|
||||
userAddresses = await zeroEx.getAvailableAddressesAsync();
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
@@ -68,8 +67,7 @@ describe('TokenWrapper', () => {
|
||||
const toAddress = addressWithoutFunds;
|
||||
const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
expect(preBalance).to.be.bignumber.equal(0);
|
||||
const txHash = await zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount);
|
||||
const receipt = await zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
await zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount);
|
||||
const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress);
|
||||
return expect(postBalance).to.be.bignumber.equal(transferAmount);
|
||||
});
|
||||
@@ -237,8 +235,10 @@ describe('TokenWrapper', () => {
|
||||
await zeroEx.token.setAllowanceAsync(zrx.address, coinbase, userWithNormalAllowance, transferAmount);
|
||||
await zeroEx.token.setUnlimitedAllowanceAsync(zrx.address, coinbase, userWithUnlimitedAllowance);
|
||||
|
||||
const initBalanceWithNormalAllowance = await promisify(web3.eth.getBalance)(userWithNormalAllowance);
|
||||
const initBalanceWithUnlimitedAllowance = await promisify(web3.eth.getBalance)(userWithUnlimitedAllowance);
|
||||
const initBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
||||
const initBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
|
||||
userWithUnlimitedAllowance,
|
||||
);
|
||||
|
||||
await zeroEx.token.transferFromAsync(
|
||||
zrx.address, coinbase, userWithNormalAllowance, userWithNormalAllowance, transferAmount,
|
||||
@@ -247,8 +247,10 @@ describe('TokenWrapper', () => {
|
||||
zrx.address, coinbase, userWithUnlimitedAllowance, userWithUnlimitedAllowance, transferAmount,
|
||||
);
|
||||
|
||||
const finalBalanceWithNormalAllowance = await promisify(web3.eth.getBalance)(userWithNormalAllowance);
|
||||
const finalBalanceWithUnlimitedAllowance = await promisify(web3.eth.getBalance)(userWithUnlimitedAllowance);
|
||||
const finalBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
|
||||
const finalBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
|
||||
userWithUnlimitedAllowance,
|
||||
);
|
||||
|
||||
const normalGasCost = initBalanceWithNormalAllowance.minus(finalBalanceWithNormalAllowance);
|
||||
const unlimitedGasCost = initBalanceWithUnlimitedAllowance.minus(finalBalanceWithUnlimitedAllowance);
|
||||
@@ -347,7 +349,6 @@ describe('TokenWrapper', () => {
|
||||
});
|
||||
describe('#subscribe', () => {
|
||||
const indexFilterValues = {};
|
||||
const shouldThrowOnInsufficientBalanceOrAllowance = true;
|
||||
let tokenAddress: string;
|
||||
const transferAmount = new BigNumber(42);
|
||||
const allowanceAmount = new BigNumber(42);
|
||||
@@ -433,7 +434,7 @@ describe('TokenWrapper', () => {
|
||||
describe('#getLogsAsync', () => {
|
||||
let tokenAddress: string;
|
||||
let tokenTransferProxyAddress: string;
|
||||
const subscriptionOpts: SubscriptionOpts = {
|
||||
const blockRange: BlockRange = {
|
||||
fromBlock: 0,
|
||||
toBlock: BlockParamLiteral.Latest,
|
||||
};
|
||||
@@ -449,7 +450,7 @@ describe('TokenWrapper', () => {
|
||||
const eventName = TokenEvents.Approval;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
||||
tokenAddress, eventName, subscriptionOpts, indexFilterValues,
|
||||
tokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
@@ -464,7 +465,7 @@ describe('TokenWrapper', () => {
|
||||
const differentEventName = TokenEvents.Transfer;
|
||||
const indexFilterValues = {};
|
||||
const logs = await zeroEx.token.getLogsAsync(
|
||||
tokenAddress, differentEventName, subscriptionOpts, indexFilterValues,
|
||||
tokenAddress, differentEventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(0);
|
||||
});
|
||||
@@ -478,7 +479,7 @@ describe('TokenWrapper', () => {
|
||||
_owner: coinbase,
|
||||
};
|
||||
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
|
||||
tokenAddress, eventName, subscriptionOpts, indexFilterValues,
|
||||
tokenAddress, eventName, blockRange, indexFilterValues,
|
||||
);
|
||||
expect(logs).to.have.length(1);
|
||||
const args = logs[0].args;
|
||||
|
@@ -1,12 +1,11 @@
|
||||
export const constants = {
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
RPC_HOST: 'localhost',
|
||||
RPC_PORT: 8545,
|
||||
RPC_URL: 'http://localhost:8545/',
|
||||
ROPSTEN_NETWORK_ID: 3,
|
||||
KOVAN_NETWORK_ID: 42,
|
||||
TESTRPC_NETWORK_ID: 50,
|
||||
KOVAN_RPC_URL: 'https://kovan.infura.io',
|
||||
ROPSTEN_RPC_URL: 'https://ropsten.infura.io',
|
||||
KOVAN_RPC_URL: 'https://kovan.infura.io/',
|
||||
ROPSTEN_RPC_URL: 'https://ropsten.infura.io/',
|
||||
ZRX_DECIMALS: 18,
|
||||
GAS_ESTIMATE: 500000,
|
||||
};
|
||||
|
@@ -1,10 +1,15 @@
|
||||
import {Web3Wrapper} from '@0xproject/web3-wrapper';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import {SignedOrder, Token, ZeroEx} from '../../src';
|
||||
import {artifacts} from '../../src/artifacts';
|
||||
import {DummyTokenContract} from '../../src/contract_wrappers/generated/dummy_token';
|
||||
import {orderFactory} from '../utils/order_factory';
|
||||
|
||||
import {constants} from './constants';
|
||||
|
||||
const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100);
|
||||
|
||||
export class FillScenarios {
|
||||
private zeroEx: ZeroEx;
|
||||
private userAddresses: string[];
|
||||
@@ -21,6 +26,23 @@ export class FillScenarios {
|
||||
this.zrxTokenAddress = zrxTokenAddress;
|
||||
this.exchangeContractAddress = exchangeContractAddress;
|
||||
}
|
||||
public async initTokenBalancesAsync() {
|
||||
const web3Wrapper = (this.zeroEx as any)._web3Wrapper as Web3Wrapper;
|
||||
for (const token of this.tokens) {
|
||||
if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') {
|
||||
const contractInstance = web3Wrapper.getContractInstance(
|
||||
artifacts.DummyTokenArtifact.abi, token.address,
|
||||
);
|
||||
const defaults = {};
|
||||
const dummyToken = new DummyTokenContract(contractInstance, defaults);
|
||||
const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals);
|
||||
const txHash = await dummyToken.setBalance.sendTransactionAsync(this.coinbase, tokenSupply, {
|
||||
from: this.coinbase,
|
||||
});
|
||||
await this.zeroEx.awaitTransactionMinedAsync(txHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
|
||||
makerAddress: string, takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { DoneCallback } from '../../src/types';
|
||||
import {DoneCallback} from '../../src/types';
|
||||
|
||||
export const reportCallbackErrors = (done: DoneCallback) => {
|
||||
return (f: (...args: any[]) => void) => {
|
||||
|
@@ -3,6 +3,7 @@ import * as _ from 'lodash';
|
||||
import {InternalZeroExError, Token} from '../../src/types';
|
||||
|
||||
const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
|
||||
const WETH_TOKEN_SYMBOL = 'WETH';
|
||||
|
||||
export class TokenUtils {
|
||||
private tokens: Token[];
|
||||
@@ -16,10 +17,17 @@ export class TokenUtils {
|
||||
}
|
||||
return zrxToken;
|
||||
}
|
||||
public getNonProtocolTokens(): Token[] {
|
||||
const nonProtocolTokens = _.filter(this.tokens, token => {
|
||||
return token.symbol !== PROTOCOL_TOKEN_SYMBOL;
|
||||
public getWethTokenOrThrow(): Token {
|
||||
const wethToken = _.find(this.tokens, {symbol: WETH_TOKEN_SYMBOL});
|
||||
if (_.isUndefined(wethToken)) {
|
||||
throw new Error(InternalZeroExError.WethNotInTokenRegistry);
|
||||
}
|
||||
return wethToken;
|
||||
}
|
||||
public getDummyTokens(): Token[] {
|
||||
const dummyTokens = _.filter(this.tokens, token => {
|
||||
return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol);
|
||||
});
|
||||
return nonProtocolTokens;
|
||||
return dummyTokens;
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
// we are not running in a browser env.
|
||||
// Filed issue: https://github.com/ethereum/web3.js/issues/844
|
||||
(global as any).XMLHttpRequest = undefined;
|
||||
import * as Web3 from 'web3';
|
||||
import ProviderEngine = require('web3-provider-engine');
|
||||
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
|
||||
|
||||
@@ -12,6 +11,13 @@ import {FakeGasEstimateSubprovider} from './subproviders/fake_gas_estimate_subpr
|
||||
|
||||
import {constants} from './constants';
|
||||
|
||||
// HACK: web3 leaks XMLHttpRequest into the global scope and causes requests to hang
|
||||
// because they are using the wrong XHR package.
|
||||
// importing web3 after subproviders fixes this issue
|
||||
// Filed issue: https://github.com/ethereum/web3.js/issues/844
|
||||
// tslint:disable-next-line:ordered-imports
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export const web3Factory = {
|
||||
create(hasAddresses: boolean = true): Web3 {
|
||||
const provider = this.getRpcProvider(hasAddresses);
|
||||
@@ -21,13 +27,12 @@ export const web3Factory = {
|
||||
},
|
||||
getRpcProvider(hasAddresses: boolean = true): Web3.Provider {
|
||||
const provider = new ProviderEngine();
|
||||
const rpcUrl = `http://${constants.RPC_HOST}:${constants.RPC_PORT}`;
|
||||
if (!hasAddresses) {
|
||||
provider.addProvider(new EmptyWalletSubprovider());
|
||||
}
|
||||
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_ESTIMATE));
|
||||
provider.addProvider(new RpcSubprovider({
|
||||
rpcUrl,
|
||||
rpcUrl: constants.RPC_URL,
|
||||
}));
|
||||
provider.start();
|
||||
return provider;
|
||||
|
4
packages/abi-gen/CHANGELOG.md
Normal file
4
packages/abi-gen/CHANGELOG.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# CHANGELOG
|
||||
|
||||
vx.x.x
|
||||
------------------------
|
39
packages/abi-gen/README.md
Normal file
39
packages/abi-gen/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# ABI Gen
|
||||
|
||||
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/src/contract_templates) are the templates used to generate those files.
|
||||
|
||||
## Instalation
|
||||
`yarn add -g @0xproject/abi-gen`
|
||||
## Usage
|
||||
```
|
||||
abi-gen
|
||||
Options:
|
||||
--help Show help [boolean]
|
||||
--version Show version number [boolean]
|
||||
--abiGlob Glob pattern to search for ABI JSON files [string] [required]
|
||||
--templates Folder where to search for templates [string] [required]
|
||||
--output Folder where to put the output files [string] [required]
|
||||
```
|
||||
## ABI files
|
||||
You're required to pass a [glob](https://en.wikipedia.org/wiki/Glob_(programming)) template where your abi files are located.
|
||||
TL;DR - here is the example from 0x.js.
|
||||
|
||||
`--abiGlob 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry).json`
|
||||
|
||||
We could've just used `--abiGlob 'src/artifacts/*.json` but we wanted to exclude some of the abi files.
|
||||
|
||||
The abi file should be either a [Truffle](http://truffleframework.com/) contract artifact (a JSON object with an abi key) or a JSON abi array.
|
||||
## 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/src/contract_templates) and start adjusting them for your needs.
|
||||
We use [handlebars](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.
|
||||
## Output files
|
||||
Output files will be generated within an output folder with names converted to camel case and taken from abi file names. If you already have some files in that folder they will be overwritten.
|
48
packages/abi-gen/package.json
Normal file
48
packages/abi-gen/package.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "@0xproject/abi-gen",
|
||||
"version": "0.0.2",
|
||||
"description": "Generate contract wrappers from ABI and handlebars templates",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"lint": "tslint --project . 'src/**/*.ts'",
|
||||
"clean": "shx rm -rf lib",
|
||||
"build": "tsc"
|
||||
},
|
||||
"bin": {
|
||||
"abi-gen": "lib/index.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x.js.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x.js/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/abi-gen/README.md",
|
||||
"dependencies": {
|
||||
"bignumber.js": "~4.1.0",
|
||||
"chalk": "^2.3.0",
|
||||
"glob": "^7.1.2",
|
||||
"handlebars": "^4.0.11",
|
||||
"lodash": "^4.17.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"to-snake-case": "^1.0.0",
|
||||
"web3": "^0.20.0",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.2.1",
|
||||
"@types/glob": "^5.0.33",
|
||||
"@types/handlebars": "^4.0.36",
|
||||
"@types/mkdirp": "^0.5.1",
|
||||
"@types/node": "^8.0.53",
|
||||
"@types/yargs": "^10.0.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "~2.6.1",
|
||||
"web3-typescript-typings": "^0.7.2"
|
||||
}
|
||||
}
|
14
packages/abi-gen/scripts/postpublish.js
Normal file
14
packages/abi-gen/scripts/postpublish.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const postpublish_utils = require('../../../scripts/postpublish_utils');
|
||||
const packageJSON = require('../package.json');
|
||||
|
||||
const subPackageName = packageJSON.name;
|
||||
|
||||
postpublish_utils.getLatestTagAndVersionAsync(subPackageName)
|
||||
.then(function(result) {
|
||||
const releaseName = postpublish_utils.getReleaseName(subPackageName, result.version);
|
||||
const assets = [];
|
||||
return postpublish_utils.publishReleaseNotes(result.tag, releaseName, assets);
|
||||
})
|
||||
.catch (function(err) {
|
||||
throw err;
|
||||
});
|
4
packages/abi-gen/src/globals.d.ts
vendored
Normal file
4
packages/abi-gen/src/globals.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
declare function toSnakeCase(str: string): string;
|
||||
declare module 'to-snake-case' {
|
||||
export = toSnakeCase;
|
||||
}
|
98
packages/abi-gen/src/index.ts
Normal file
98
packages/abi-gen/src/index.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import chalk from 'chalk';
|
||||
import * as fs from 'fs';
|
||||
import {sync as globSync} from 'glob';
|
||||
import * as Handlebars from 'handlebars';
|
||||
import * as _ from 'lodash';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import * as yargs from 'yargs';
|
||||
|
||||
import toSnakeCase = require('to-snake-case');
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import {ContextData, ParamKind} from './types';
|
||||
import {utils} from './utils';
|
||||
|
||||
const ABI_TYPE_METHOD = 'function';
|
||||
const MAIN_TEMPLATE_NAME = 'contract.mustache';
|
||||
|
||||
const args = yargs
|
||||
.option('abiGlob', {
|
||||
describe: 'Glob pattern to search for ABI JSON files',
|
||||
type: 'string',
|
||||
demand: true,
|
||||
})
|
||||
.option('templates', {
|
||||
describe: 'Folder where to search for templates',
|
||||
type: 'string',
|
||||
demand: true,
|
||||
})
|
||||
.option('output', {
|
||||
describe: 'Folder where to put the output files',
|
||||
type: 'string',
|
||||
demand: true,
|
||||
})
|
||||
.argv;
|
||||
|
||||
function writeOutputFile(name: string, renderedTsCode: string): void {
|
||||
const fileName = toSnakeCase(name);
|
||||
const filePath = `${args.output}/${fileName}.ts`;
|
||||
fs.writeFileSync(filePath, renderedTsCode);
|
||||
utils.log(`Created: ${chalk.bold(filePath)}`);
|
||||
}
|
||||
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output));
|
||||
const partialTemplateFileNames = globSync(`${args.templates}/partials/**/*.mustache`);
|
||||
for (const partialTemplateFileName of partialTemplateFileNames) {
|
||||
const namedContent = utils.getNamedContent(partialTemplateFileName);
|
||||
Handlebars.registerPartial(namedContent.name, namedContent.content);
|
||||
}
|
||||
|
||||
const mainTemplate = utils.getNamedContent(`${args.templates}/${MAIN_TEMPLATE_NAME}`);
|
||||
const template = Handlebars.compile<ContextData>(mainTemplate.content);
|
||||
const abiFileNames = globSync(args.abiGlob);
|
||||
if (_.isEmpty(abiFileNames)) {
|
||||
utils.log(`${chalk.red(`No ABI files found.`)}`);
|
||||
utils.log(`Please make sure you've passed the correct folder name and that the files have
|
||||
${chalk.bold('*.json')} extensions`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
utils.log(`Found ${chalk.green(`${abiFileNames.length}`)} ${chalk.bold('ABI')} files`);
|
||||
mkdirp.sync(args.output);
|
||||
}
|
||||
for (const abiFileName of abiFileNames) {
|
||||
const namedContent = utils.getNamedContent(abiFileName);
|
||||
utils.log(`Processing: ${chalk.bold(namedContent.name)}...`);
|
||||
const parsedContent = JSON.parse(namedContent.content);
|
||||
const ABI = _.isArray(parsedContent) ?
|
||||
parsedContent : // ABI file
|
||||
parsedContent.abi; // Truffle contracts file
|
||||
if (_.isUndefined(ABI)) {
|
||||
utils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`);
|
||||
utils.log(`Please make sure your ABI file is either an array with ABI entries or an object with the abi key`);
|
||||
process.exit(1);
|
||||
}
|
||||
const methodAbis = ABI.filter((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_METHOD) as Web3.MethodAbi[];
|
||||
const methodsData = _.map(methodAbis, methodAbi => {
|
||||
_.map(methodAbi.inputs, input => {
|
||||
if (_.isEmpty(input.name)) {
|
||||
// Auto-generated getters don't have parameter names
|
||||
input.name = 'index';
|
||||
}
|
||||
});
|
||||
// This will make templates simpler
|
||||
const methodData = {
|
||||
...methodAbi,
|
||||
singleReturnValue: methodAbi.outputs.length === 1,
|
||||
};
|
||||
return methodData;
|
||||
});
|
||||
const contextData = {
|
||||
contractName: namedContent.name,
|
||||
methods: methodsData,
|
||||
};
|
||||
const renderedTsCode = template(contextData);
|
||||
writeOutputFile(namedContent.name, renderedTsCode);
|
||||
}
|
15
packages/abi-gen/src/types.ts
Normal file
15
packages/abi-gen/src/types.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
export enum ParamKind {
|
||||
Input = 'input',
|
||||
Output = 'output',
|
||||
}
|
||||
|
||||
export interface Method extends Web3.MethodAbi {
|
||||
singleReturnValue: boolean;
|
||||
}
|
||||
|
||||
export interface ContextData {
|
||||
contractName: string;
|
||||
methods: Method[];
|
||||
}
|
56
packages/abi-gen/src/utils.ts
Normal file
56
packages/abi-gen/src/utils.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import * as fs from 'fs';
|
||||
import * as _ from 'lodash';
|
||||
import * as path from 'path';
|
||||
|
||||
import {ParamKind} from './types';
|
||||
|
||||
export const utils = {
|
||||
solTypeToTsType(paramKind: ParamKind, solType: string): string {
|
||||
const trailingArrayRegex = /\[\d*\]$/;
|
||||
if (solType.match(trailingArrayRegex)) {
|
||||
const arrayItemSolType = solType.replace(trailingArrayRegex, '');
|
||||
const arrayItemTsType = utils.solTypeToTsType(paramKind, arrayItemSolType);
|
||||
const arrayTsType = `${arrayItemTsType}[]`;
|
||||
return arrayTsType;
|
||||
} else {
|
||||
const solTypeRegexToTsType = [
|
||||
{regex: '^string$', tsType: 'string'},
|
||||
{regex: '^address$', tsType: 'string'},
|
||||
{regex: '^bool$', tsType: 'boolean'},
|
||||
{regex: '^u?int\\d*$', tsType: 'BigNumber'},
|
||||
{regex: '^bytes\\d*$', tsType: 'string'},
|
||||
];
|
||||
if (paramKind === ParamKind.Input) {
|
||||
// web3 allows to pass those an non-bignumbers and that's nice
|
||||
// but it always returns stuff as BigNumbers
|
||||
solTypeRegexToTsType.unshift({regex: '^u?int(8|16|32)?$', tsType: 'number|BigNumber'});
|
||||
}
|
||||
for (const regexAndTxType of solTypeRegexToTsType) {
|
||||
const {regex, tsType} = regexAndTxType;
|
||||
if (solType.match(regex)) {
|
||||
return tsType;
|
||||
}
|
||||
}
|
||||
throw new Error(`Unknown Solidity type found: ${solType}`);
|
||||
}
|
||||
},
|
||||
log(...args: any[]): void {
|
||||
console.log(...args); // tslint:disable-line:no-console
|
||||
},
|
||||
getPartialNameFromFileName(filename: string): string {
|
||||
const name = path.parse(filename).name;
|
||||
return name;
|
||||
},
|
||||
getNamedContent(filename: string): {name: string; content: string} {
|
||||
const name = utils.getPartialNameFromFileName(filename);
|
||||
try {
|
||||
const content = fs.readFileSync(filename).toString();
|
||||
return {
|
||||
name,
|
||||
content,
|
||||
};
|
||||
} catch (err) {
|
||||
throw new Error(`Failed to read ${filename}: ${err}`);
|
||||
}
|
||||
},
|
||||
};
|
17
packages/abi-gen/tsconfig.json
Normal file
17
packages/abi-gen/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"lib": ["es2015", "dom"],
|
||||
"outDir": "lib",
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*",
|
||||
"./test/**/*",
|
||||
"../../node_modules/web3-typescript-typings/index.d.ts"
|
||||
]
|
||||
}
|
5
packages/abi-gen/tslint.json
Normal file
5
packages/abi-gen/tslint.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": [
|
||||
"@0xproject/tslint-config"
|
||||
]
|
||||
}
|
@@ -1,10 +1,54 @@
|
||||
assert
|
||||
@0xproject/assert
|
||||
------
|
||||
|
||||
Standard type and schema assertions to be used across all 0x projects and packages
|
||||
|
||||
## Install
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @0xproject/assert --save
|
||||
yarn add @0xproject/assert
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import {assert} from '@0xproject/assert';
|
||||
|
||||
assert.isValidBaseUnitAmount('baseUnitAmount', baseUnitAmount);
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
We strongly encourage 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
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/assert",
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.7",
|
||||
"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",
|
||||
@@ -23,23 +23,23 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/assert/README.md",
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.1.1",
|
||||
"@types/lodash": "^4.14.78",
|
||||
"@0xproject/tslint-config": "^0.2.1",
|
||||
"@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.1",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"mocha": "^4.0.1",
|
||||
"npm-run-all": "^4.1.1",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.8.0",
|
||||
"typescript": "^2.4.2"
|
||||
"typescript": "~2.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/json-schemas": "^0.6.8",
|
||||
"@0xproject/json-schemas": "^0.6.10",
|
||||
"@0xproject/utils": "^0.1.0",
|
||||
"bignumber.js": "~4.1.0",
|
||||
"ethereum-address": "^0.0.4",
|
||||
"lodash": "^4.17.4",
|
||||
"valid-url": "^1.0.9"
|
||||
}
|
||||
|
4
packages/assert/src/globals.d.ts
vendored
4
packages/assert/src/globals.d.ts
vendored
@@ -1,5 +1 @@
|
||||
declare module 'dirty-chai';
|
||||
|
||||
declare module 'ethereum-address' {
|
||||
const isAddress: (arg: any) => boolean;
|
||||
}
|
||||
|
@@ -2,8 +2,8 @@ import {
|
||||
Schema,
|
||||
SchemaValidator,
|
||||
} from '@0xproject/json-schemas';
|
||||
import {addressUtils} from '@0xproject/utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as ethereum_address from 'ethereum-address';
|
||||
import * as _ from 'lodash';
|
||||
import * as validUrl from 'valid-url';
|
||||
|
||||
@@ -35,9 +35,9 @@ export const assert = {
|
||||
this.typeAssertionMessage(variableName, 'HexString', value));
|
||||
},
|
||||
isETHAddressHex(variableName: string, value: string): void {
|
||||
this.assert(ethereum_address.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value));
|
||||
this.assert(addressUtils.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value));
|
||||
this.assert(
|
||||
ethereum_address.isAddress(value) && value.toLowerCase() === value,
|
||||
addressUtils.isAddress(value) && value.toLowerCase() === value,
|
||||
`Checksummed addresses are not supported. Convert ${variableName} to lower case before passing`,
|
||||
);
|
||||
},
|
||||
|
@@ -25,7 +25,7 @@ describe('Assertions', () => {
|
||||
'test',
|
||||
42,
|
||||
false,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
];
|
||||
invalidInputs.forEach(input => expect(assert.isBigNumber.bind(assert, variableName, input)).to.throw());
|
||||
@@ -43,7 +43,7 @@ describe('Assertions', () => {
|
||||
'test',
|
||||
42,
|
||||
false,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
];
|
||||
invalidInputs.forEach(input => expect(assert.isUndefined.bind(assert, input, variableName)).to.throw());
|
||||
});
|
||||
@@ -60,7 +60,7 @@ describe('Assertions', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
false,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
];
|
||||
@@ -79,7 +79,7 @@ describe('Assertions', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
false,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
];
|
||||
@@ -98,7 +98,7 @@ describe('Assertions', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
false,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
'0x61a3ed31B43c8780e905a260a35faYfEc527be7516aa11c0256729b5b351bc33',
|
||||
@@ -121,7 +121,7 @@ describe('Assertions', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
false,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
'0x6FFFd0ae3f7d88c9b4925323f54c6e4b2918c5fd',
|
||||
@@ -150,7 +150,7 @@ describe('Assertions', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
false,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
];
|
||||
@@ -192,7 +192,7 @@ describe('Assertions', () => {
|
||||
it('should throw for invalid input', () => {
|
||||
const invalidInputs = [
|
||||
false,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
];
|
||||
@@ -210,7 +210,7 @@ describe('Assertions', () => {
|
||||
it('should throw for invalid input', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
];
|
||||
@@ -220,8 +220,8 @@ describe('Assertions', () => {
|
||||
describe('#isWeb3Provider', () => {
|
||||
it('should not throw for valid input', () => {
|
||||
const validInputs = [
|
||||
{ send: () => 45 },
|
||||
{ sendAsync: () => 45 },
|
||||
{send: () => 45},
|
||||
{sendAsync: () => 45},
|
||||
];
|
||||
validInputs.forEach(input =>
|
||||
expect(assert.isWeb3Provider.bind(assert, variableName, input)).to.not.throw(),
|
||||
@@ -230,7 +230,7 @@ describe('Assertions', () => {
|
||||
it('should throw for invalid input', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
];
|
||||
@@ -253,7 +253,7 @@ describe('Assertions', () => {
|
||||
it('should throw for invalid input', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
];
|
||||
@@ -277,7 +277,7 @@ describe('Assertions', () => {
|
||||
it('should throw for invalid input', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
'ws://www.api.example-relayer.net',
|
||||
@@ -309,7 +309,7 @@ describe('Assertions', () => {
|
||||
it('should throw for invalid input', () => {
|
||||
const invalidInputs = [
|
||||
42,
|
||||
{ random: 'test' },
|
||||
{random: 'test'},
|
||||
undefined,
|
||||
new BigNumber(45),
|
||||
'www.google.com',
|
||||
|
@@ -1,5 +1,16 @@
|
||||
# CHANGELOG
|
||||
|
||||
v0.3.0 - _December 8, 2017_
|
||||
------------------------
|
||||
* Expose WebSocketOrderbookChannel and associated types to public interface (#251)
|
||||
* Remove tokenA and tokenB fields from OrdersRequest (#256)
|
||||
|
||||
v0.2.0 - _November 29, 2017_
|
||||
------------------------
|
||||
* Add SignedOrder and TokenTradeInfo to the public interface
|
||||
* Add ECSignature and Order to the public interface
|
||||
* Remove dependency on 0x.js
|
||||
|
||||
v0.1.0 - _November 22, 2017_
|
||||
------------------------
|
||||
* Provide a HttpClient class for interacting with standard relayer api compliant HTTP urls
|
||||
|
@@ -1 +1,51 @@
|
||||
@0xproject/connect
|
||||
------
|
||||
|
||||
This repository contains a Javascript library that makes it easy to interact with Relayers that conform to the [Standard Relayer API](https://github.com/0xProject/standard-relayer-api)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
yarn add @0xproject/connect
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
* [Docs](https://0xproject.com/docs/connect)
|
||||
* [Tutorials](https://0xproject.com/wiki#connect)
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
### Lint
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0xproject/connect",
|
||||
"version": "0.1.0",
|
||||
"version": "0.3.0",
|
||||
"description": "A javascript library for interacting with the standard relayer api",
|
||||
"keywords": [
|
||||
"connect",
|
||||
@@ -36,9 +36,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x.js/packages/connect/README.md",
|
||||
"dependencies": {
|
||||
"0x.js": "^0.26.1",
|
||||
"@0xproject/assert": "^0.0.5",
|
||||
"@0xproject/json-schemas": "^0.6.8",
|
||||
"@0xproject/assert": "^0.0.7",
|
||||
"@0xproject/json-schemas": "^0.6.10",
|
||||
"bignumber.js": "~4.1.0",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"lodash": "^4.17.4",
|
||||
@@ -46,25 +45,25 @@
|
||||
"websocket": "^1.0.25"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/tslint-config": "^0.1.1",
|
||||
"@0xproject/tslint-config": "^0.2.1",
|
||||
"@types/fetch-mock": "^5.12.1",
|
||||
"@types/lodash": "^4.14.77",
|
||||
"@types/lodash": "^4.14.86",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/query-string": "^5.0.1",
|
||||
"@types/websocket": "^0.0.34",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-as-promised-typescript-typings": "0.0.3",
|
||||
"chai-as-promised-typescript-typings": "^0.0.3",
|
||||
"chai-typescript-typings": "^0.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"fetch-mock": "^5.13.1",
|
||||
"mocha": "^4.0.0",
|
||||
"npm-run-all": "^4.0.2",
|
||||
"mocha": "^4.0.1",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.8.0",
|
||||
"typedoc": "~0.8.0",
|
||||
"typescript": "~2.6.1",
|
||||
"web3-typescript-typings": "^0.7.1"
|
||||
"web3-typescript-typings": "^0.7.2"
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import {SignedOrder} from '0x.js';
|
||||
import {assert} from '@0xproject/assert';
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
@@ -16,6 +15,7 @@ import {
|
||||
OrderbookRequest,
|
||||
OrderbookResponse,
|
||||
OrdersRequest,
|
||||
SignedOrder,
|
||||
TokenPairsItem,
|
||||
TokenPairsRequest,
|
||||
} from './types';
|
||||
@@ -34,7 +34,7 @@ export class HttpClient implements Client {
|
||||
private apiEndpointUrl: string;
|
||||
/**
|
||||
* Instantiates a new HttpClient instance
|
||||
* @param url The base url for making API calls
|
||||
* @param url The relayer API base HTTP url you would like to interact with
|
||||
* @return An instance of HttpClient
|
||||
*/
|
||||
constructor(url: string) {
|
||||
|
@@ -1,11 +1,19 @@
|
||||
export {HttpClient} from './http_client';
|
||||
export {WebSocketOrderbookChannel} from './ws_orderbook_channel';
|
||||
export {
|
||||
Client,
|
||||
ECSignature,
|
||||
FeesRequest,
|
||||
FeesResponse,
|
||||
Order,
|
||||
OrderbookChannel,
|
||||
OrderbookChannelHandler,
|
||||
OrderbookChannelSubscriptionOpts,
|
||||
OrderbookRequest,
|
||||
OrderbookResponse,
|
||||
OrdersRequest,
|
||||
SignedOrder,
|
||||
TokenPairsItem,
|
||||
TokenPairsRequest,
|
||||
TokenTradeInfo,
|
||||
} from './types';
|
||||
|
@@ -1,6 +1,34 @@
|
||||
import {SignedOrder} from '0x.js';
|
||||
import {BigNumber} from 'bignumber.js';
|
||||
|
||||
// TODO: Consolidate Order, SignedOrder and ECSignature into a shared package instead of duplicating them from 0x.js
|
||||
export interface Order {
|
||||
maker: string;
|
||||
taker: string;
|
||||
makerFee: BigNumber;
|
||||
takerFee: BigNumber;
|
||||
makerTokenAmount: BigNumber;
|
||||
takerTokenAmount: BigNumber;
|
||||
makerTokenAddress: string;
|
||||
takerTokenAddress: string;
|
||||
salt: BigNumber;
|
||||
exchangeContractAddress: string;
|
||||
feeRecipient: string;
|
||||
expirationUnixTimestampSec: BigNumber;
|
||||
}
|
||||
|
||||
export interface SignedOrder extends Order {
|
||||
ecSignature: ECSignature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Elliptic Curve signature
|
||||
*/
|
||||
export interface ECSignature {
|
||||
v: number;
|
||||
r: string;
|
||||
s: string;
|
||||
}
|
||||
|
||||
export interface Client {
|
||||
getTokenPairsAsync: (request?: TokenPairsRequest) => Promise<TokenPairsItem[]>;
|
||||
getOrdersAsync: (request?: OrdersRequest) => Promise<SignedOrder[]>;
|
||||
@@ -29,10 +57,13 @@ export interface OrderbookChannelSubscriptionOpts {
|
||||
}
|
||||
|
||||
export interface OrderbookChannelHandler {
|
||||
onSnapshot: (channel: OrderbookChannel, snapshot: OrderbookResponse) => void;
|
||||
onUpdate: (channel: OrderbookChannel, order: SignedOrder) => void;
|
||||
onError: (channel: OrderbookChannel, err: Error) => void;
|
||||
onClose: (channel: OrderbookChannel) => void;
|
||||
onSnapshot: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts,
|
||||
snapshot: OrderbookResponse) => void;
|
||||
onUpdate: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts,
|
||||
order: SignedOrder) => void;
|
||||
onError: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts,
|
||||
err: Error) => void;
|
||||
onClose: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
|
||||
}
|
||||
|
||||
export type OrderbookChannelMessage =
|
||||
@@ -48,16 +79,19 @@ export enum OrderbookChannelMessageTypes {
|
||||
|
||||
export interface SnapshotOrderbookChannelMessage {
|
||||
type: OrderbookChannelMessageTypes.Snapshot;
|
||||
requestId: number;
|
||||
payload: OrderbookResponse;
|
||||
}
|
||||
|
||||
export interface UpdateOrderbookChannelMessage {
|
||||
type: OrderbookChannelMessageTypes.Update;
|
||||
requestId: number;
|
||||
payload: SignedOrder;
|
||||
}
|
||||
|
||||
export interface UnknownOrderbookChannelMessage {
|
||||
type: OrderbookChannelMessageTypes.Unknown;
|
||||
requestId: number;
|
||||
payload: undefined;
|
||||
}
|
||||
|
||||
@@ -94,8 +128,6 @@ export interface OrdersRequest {
|
||||
tokenAddress?: string;
|
||||
makerTokenAddress?: string;
|
||||
takerTokenAddress?: string;
|
||||
tokenA?: string;
|
||||
tokenB?: string;
|
||||
maker?: string;
|
||||
taker?: string;
|
||||
trader?: string;
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import {SignedOrder} from '0x.js';
|
||||
import {assert} from '@0xproject/assert';
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import * as _ from 'lodash';
|
||||
@@ -15,28 +14,24 @@ export const orderbookChannelMessageParsers = {
|
||||
const messageObj = JSON.parse(utf8Data);
|
||||
const type: string = _.get(messageObj, 'type');
|
||||
assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`);
|
||||
assert.isString('type', type);
|
||||
switch (type) {
|
||||
case (OrderbookChannelMessageTypes.Snapshot): {
|
||||
assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelSnapshotSchema);
|
||||
const orderbook = messageObj.payload;
|
||||
typeConverters.convertOrderbookStringFieldsToBigNumber(orderbook);
|
||||
return {
|
||||
type,
|
||||
payload: orderbook,
|
||||
};
|
||||
return messageObj;
|
||||
}
|
||||
case (OrderbookChannelMessageTypes.Update): {
|
||||
assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelUpdateSchema);
|
||||
const order = messageObj.payload;
|
||||
typeConverters.convertOrderStringFieldsToBigNumber(order);
|
||||
return {
|
||||
type,
|
||||
payload: order,
|
||||
};
|
||||
return messageObj;
|
||||
}
|
||||
default: {
|
||||
return {
|
||||
type: OrderbookChannelMessageTypes.Unknown,
|
||||
requestId: 0,
|
||||
payload: undefined,
|
||||
};
|
||||
}
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import {SignedOrder} from '0x.js';
|
||||
import {assert} from '@0xproject/assert';
|
||||
import {schemas} from '@0xproject/json-schemas';
|
||||
import * as _ from 'lodash';
|
||||
@@ -22,9 +21,10 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
||||
private apiEndpointUrl: string;
|
||||
private client: WebSocket.client;
|
||||
private connectionIfExists?: WebSocket.connection;
|
||||
private subscriptionCounter = 0;
|
||||
/**
|
||||
* Instantiates a new WebSocketOrderbookChannel instance
|
||||
* @param url The base url for making API calls
|
||||
* @param url The relayer API base WS url you would like to interact with
|
||||
* @return An instance of WebSocketOrderbookChannel
|
||||
*/
|
||||
constructor(url: string) {
|
||||
@@ -46,23 +46,25 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
||||
assert.isFunction('handler.onUpdate', _.get(handler, 'onUpdate'));
|
||||
assert.isFunction('handler.onError', _.get(handler, 'onError'));
|
||||
assert.isFunction('handler.onClose', _.get(handler, 'onClose'));
|
||||
this.subscriptionCounter += 1;
|
||||
const subscribeMessage = {
|
||||
type: 'subscribe',
|
||||
channel: 'orderbook',
|
||||
requestId: this.subscriptionCounter,
|
||||
payload: subscriptionOpts,
|
||||
};
|
||||
this._getConnection((error, connection) => {
|
||||
if (!_.isUndefined(error)) {
|
||||
handler.onError(this, error);
|
||||
handler.onError(this, subscriptionOpts, error);
|
||||
} else if (!_.isUndefined(connection) && connection.connected) {
|
||||
connection.on(WebsocketConnectionEventType.Error, wsError => {
|
||||
handler.onError(this, wsError);
|
||||
handler.onError(this, subscriptionOpts, wsError);
|
||||
});
|
||||
connection.on(WebsocketConnectionEventType.Close, () => {
|
||||
handler.onClose(this);
|
||||
handler.onClose(this, subscriptionOpts);
|
||||
});
|
||||
connection.on(WebsocketConnectionEventType.Message, message => {
|
||||
this._handleWebSocketMessage(message, handler);
|
||||
this._handleWebSocketMessage(subscribeMessage.requestId, subscriptionOpts, message, handler);
|
||||
});
|
||||
connection.sendUTF(JSON.stringify(subscribeMessage));
|
||||
}
|
||||
@@ -90,30 +92,33 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
||||
this.client.connect(this.apiEndpointUrl);
|
||||
}
|
||||
}
|
||||
private _handleWebSocketMessage(message: WebSocket.IMessage, handler: OrderbookChannelHandler): void {
|
||||
private _handleWebSocketMessage(requestId: number, subscriptionOpts: OrderbookChannelSubscriptionOpts,
|
||||
message: WebSocket.IMessage, handler: OrderbookChannelHandler): void {
|
||||
if (!_.isUndefined(message.utf8Data)) {
|
||||
try {
|
||||
const utf8Data = message.utf8Data;
|
||||
const parserResult = orderbookChannelMessageParsers.parser(utf8Data);
|
||||
const type = parserResult.type;
|
||||
switch (parserResult.type) {
|
||||
case (OrderbookChannelMessageTypes.Snapshot): {
|
||||
handler.onSnapshot(this, parserResult.payload);
|
||||
break;
|
||||
}
|
||||
case (OrderbookChannelMessageTypes.Update): {
|
||||
handler.onUpdate(this, parserResult.payload);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
handler.onError(this, new Error(`Message has missing a type parameter: ${utf8Data}`));
|
||||
if (parserResult.requestId === requestId) {
|
||||
switch (parserResult.type) {
|
||||
case (OrderbookChannelMessageTypes.Snapshot): {
|
||||
handler.onSnapshot(this, subscriptionOpts, parserResult.payload);
|
||||
break;
|
||||
}
|
||||
case (OrderbookChannelMessageTypes.Update): {
|
||||
handler.onUpdate(this, subscriptionOpts, parserResult.payload);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
handler.onError(
|
||||
this, subscriptionOpts, new Error(`Message has missing a type parameter: ${utf8Data}`));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
handler.onError(this, error);
|
||||
handler.onError(this, subscriptionOpts, error);
|
||||
}
|
||||
} else {
|
||||
handler.onError(this, new Error(`Message does not contain utf8Data`));
|
||||
handler.onError(this, subscriptionOpts, new Error(`Message does not contain utf8Data`));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,13 +5,13 @@ const orderbookJsonString = JSON.stringify(orderbookJSON);
|
||||
export const snapshotOrderbookChannelMessage = `{
|
||||
"type": "snapshot",
|
||||
"channel": "orderbook",
|
||||
"channelId": 1,
|
||||
"requestId": 1,
|
||||
"payload": ${orderbookJsonString}
|
||||
}`;
|
||||
|
||||
export const malformedSnapshotOrderbookChannelMessage = `{
|
||||
"type": "snapshot",
|
||||
"channel": "orderbook",
|
||||
"channelId": 1,
|
||||
"requestId": 1,
|
||||
"payload": {}
|
||||
}`;
|
||||
|
@@ -5,6 +5,6 @@ const orderJSONString = JSON.stringify(orderResponseJSON);
|
||||
export const unknownOrderbookChannelMessage = `{
|
||||
"type": "superGoodUpdate",
|
||||
"channel": "orderbook",
|
||||
"channelId": 1,
|
||||
"requestId": 1,
|
||||
"payload": ${orderJSONString}
|
||||
}`;
|
||||
|
@@ -5,13 +5,13 @@ const orderJSONString = JSON.stringify(orderResponseJSON);
|
||||
export const updateOrderbookChannelMessage = `{
|
||||
"type": "update",
|
||||
"channel": "orderbook",
|
||||
"channelId": 1,
|
||||
"requestId": 1,
|
||||
"payload": ${orderJSONString}
|
||||
}`;
|
||||
|
||||
export const malformedUpdateOrderbookChannelMessage = `{
|
||||
"type": "update",
|
||||
"channel": "orderbook",
|
||||
"channelId": 1,
|
||||
"requestId": 1,
|
||||
"payload": {}
|
||||
}`;
|
||||
|
@@ -61,12 +61,12 @@ describe('HttpClient', () => {
|
||||
const orders = await relayerClient.getOrdersAsync();
|
||||
expect(orders).to.be.deep.equal(ordersResponse);
|
||||
});
|
||||
it('gets specfic orders for request', async () => {
|
||||
it('gets specific orders for request', async () => {
|
||||
const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d';
|
||||
const ordersRequest = {
|
||||
tokenA: tokenAddress,
|
||||
tokenAddress,
|
||||
};
|
||||
const urlWithQuery = `${url}?tokenA=${tokenAddress}`;
|
||||
const urlWithQuery = `${url}?tokenAddress=${tokenAddress}`;
|
||||
fetchMock.get(urlWithQuery, ordersResponseJSON);
|
||||
const orders = await relayerClient.getOrdersAsync(ordersRequest);
|
||||
expect(orders).to.be.deep.equal(ordersResponse);
|
||||
|
@@ -41,12 +41,22 @@ describe('orderbookChannelMessageParsers', () => {
|
||||
it('throws when message does not include a type', () => {
|
||||
const typelessMessage = `{
|
||||
"channel": "orderbook",
|
||||
"channelId": 1,
|
||||
"requestId": 1,
|
||||
"payload": {}
|
||||
}`;
|
||||
const badCall = () => orderbookChannelMessageParsers.parser(typelessMessage);
|
||||
expect(badCall).throws(`Message is missing a type parameter: ${typelessMessage}`);
|
||||
});
|
||||
it('throws when type is not a string', () => {
|
||||
const messageWithBadType = `{
|
||||
"type": 1,
|
||||
"channel": "orderbook",
|
||||
"requestId": 1,
|
||||
"payload": {}
|
||||
}`;
|
||||
const badCall = () => orderbookChannelMessageParsers.parser(messageWithBadType);
|
||||
expect(badCall).throws('Expected type to be of type string, encountered: 1');
|
||||
});
|
||||
it('throws when snapshot message has malformed payload', () => {
|
||||
const badCall = () =>
|
||||
orderbookChannelMessageParsers.parser(malformedSnapshotOrderbookChannelMessage);
|
||||
|
51
packages/contracts/README.md
Normal file
51
packages/contracts/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
Contracts
|
||||
-----
|
||||
|
||||
## Useful 0x Wiki Articles
|
||||
|
||||
* [Architecture](https://0xproject.com/wiki#Architecture)
|
||||
* [Contract Interactions](https://0xproject.com/wiki#Contract-Interactions)
|
||||
* [Contract deployed addresses](https://0xproject.com/wiki#Deployed-Addresses)
|
||||
* [0x Protocol Message Format](https://0xproject.com/wiki#Message-Format)
|
||||
* [Bug Bounty Program](https://0xproject.com/wiki#Bug-Bounty)
|
||||
|
||||
## Setup
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
Install [Node](https://nodejs.org/en/download/releases/)
|
||||
|
||||
Install [yarn](https://yarnpkg.com/lang/en/docs/install/) in order to install the project dependencies more deterministically.
|
||||
|
||||
Install project dependencies:
|
||||
|
||||
```
|
||||
yarn
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
Start Testrpc
|
||||
|
||||
```
|
||||
yarn testrpc
|
||||
```
|
||||
|
||||
Run tests
|
||||
|
||||
```
|
||||
yarn test
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
0x protocol is intended to serve as an open technical standard for EVM blockchains and we strongly encourage our community members to help us make improvements and to determine the future direction of the protocol. To report bugs within the 0x smart contracts or unit tests, please create an issue in this repository.
|
||||
|
||||
### ZEIPs
|
||||
Significant changes to 0x protocol's smart contracts, architecture, message format or functionality should be proposed in the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository. Follow the contribution guidelines provided therein.
|
||||
|
||||
### Coding conventions
|
||||
|
||||
We use a custom set of [TSLint](https://palantir.github.io/tslint/) rules to enforce our coding conventions.
|
||||
|
||||
In order to see style violation errors, install a tslinter for your text editor. e.g Atom's [atom-typescript](https://atom.io/packages/atom-typescript).
|
344
packages/contracts/build/contracts/DummyToken.json
Normal file
344
packages/contracts/build/contracts/DummyToken.json
Normal file
File diff suppressed because one or more lines are too long
394
packages/contracts/build/contracts/EtherToken.json
Normal file
394
packages/contracts/build/contracts/EtherToken.json
Normal file
@@ -0,0 +1,394 @@
|
||||
{
|
||||
"contract_name": "EtherToken",
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [],
|
||||
"name": "deposit",
|
||||
"outputs": [],
|
||||
"payable": true,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"payable": true,
|
||||
"type": "fallback"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"unlinked_binary": "0x6060604052341561000c57fe5b5b6107598061001c6000396000f300606060405236156100935763ffffffff60e060020a60003504166306fdde0381146100a4578063095ea7b31461013457806318160ddd1461016757806323b872dd146101895780632e1a7d4d146101c2578063313ce567146101d757806370a08231146101fd57806395d89b411461022b578063a9059cbb146102bb578063d0e30db0146102ee578063dd62ed3e146102f8575b6100a25b61009f61032c565b5b565b005b34156100ac57fe5b6100b461037b565b6040805160208082528351818301528351919283929083019185019080838382156100fa575b8051825260208311156100fa57601f1990920191602091820191016100da565b505050905090810190601f1680156101265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013c57fe5b610153600160a060020a03600435166024356103a3565b604080519115158252519081900360200190f35b341561016f57fe5b61017761040e565b60408051918252519081900360200190f35b341561019157fe5b610153600160a060020a0360043581169060243516604435610414565b604080519115158252519081900360200190f35b34156101ca57fe5b6100a2600435610537565b005b34156101df57fe5b6101e76105b8565b6040805160ff9092168252519081900360200190f35b341561020557fe5b610177600160a060020a03600435166105bd565b60408051918252519081900360200190f35b341561023357fe5b6100b46105dc565b6040805160208082528351818301528351919283929083019185019080838382156100fa575b8051825260208311156100fa57601f1990920191602091820191016100da565b505050905090810190601f1680156101265780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156102c357fe5b610153600160a060020a03600435166024356105fd565b604080519115158252519081900360200190f35b6100a261032c565b005b341561030057fe5b610177600160a060020a03600435811690602435166106af565b60408051918252519081900360200190f35b600160a060020a03331660009081526020819052604090205461034f90346106dc565b600160a060020a03331660009081526020819052604090205560025461037590346106dc565b6002555b565b60408051808201909152600b815260a960020a6a22ba3432b9102a37b5b2b702602082015281565b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a03808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906104575750828110155b801561047d5750600160a060020a03841660009081526020819052604090205483810110155b1561052957600160a060020a03808516600090815260208190526040808220805487019055918716815220805484900390556000198110156104e757600160a060020a03808616600090815260016020908152604080832033909416835292905220805484900390555b83600160a060020a031685600160a060020a031660008051602061070e833981519152856040518082815260200191505060405180910390a36001915061052e565b600091505b5b509392505050565b600160a060020a03331660009081526020819052604090205461055a90826106f6565b600160a060020a03331660009081526020819052604090205560025461058090826106f6565b600255604051600160a060020a0333169082156108fc029083906000818181858888f1935050505015156105b45760006000fd5b5b50565b601281565b600160a060020a0381166000908152602081905260409020545b919050565b604080518082019091526004815260e360020a630ae8aa8902602082015281565b600160a060020a0333166000908152602081905260408120548290108015906106405750600160a060020a03831660009081526020819052604090205482810110155b156106a057600160a060020a03338116600081815260208181526040808320805488900390559387168083529184902080548701905583518681529351919360008051602061070e833981519152929081900390910190a3506001610408565b506000610408565b5b92915050565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b6000828201838110156106eb57fe5b8091505b5092915050565b60008282111561070257fe5b508082035b929150505600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a7230582036b62e75991ca24307fbb7333dc79a1493b9acb6b3e146e3c707708262cfbe430029",
|
||||
"networks": {
|
||||
"1": {
|
||||
"links": {},
|
||||
"events": {
|
||||
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": {
|
||||
"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"
|
||||
},
|
||||
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"updated_at": 1502488087000,
|
||||
"address": "0x2956356cd2a2bf3202f771f50d3d14a367b48070"
|
||||
},
|
||||
"42": {
|
||||
"links": {},
|
||||
"events": {
|
||||
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": {
|
||||
"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"
|
||||
},
|
||||
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"updated_at": 1502391794392,
|
||||
"address": "0x05d090b51c40b020eab3bfcb6a2dff130df22e9c"
|
||||
},
|
||||
"50": {
|
||||
"links": {},
|
||||
"events": {
|
||||
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": {
|
||||
"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"
|
||||
},
|
||||
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"updated_at": 1513088404209,
|
||||
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
|
||||
}
|
||||
},
|
||||
"schema_version": "0.0.5",
|
||||
"updated_at": 1513088404209
|
||||
}
|
997
packages/contracts/build/contracts/Exchange.json
Normal file
997
packages/contracts/build/contracts/Exchange.json
Normal file
File diff suppressed because one or more lines are too long
227
packages/contracts/build/contracts/MaliciousToken.json
Normal file
227
packages/contracts/build/contracts/MaliciousToken.json
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"contract_name": "MaliciousToken",
|
||||
"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": "0x60606040526003805460ff19166001179055341561001957fe5b5b610467806100296000396000f3006060604052361561005c5763ffffffff60e060020a600035041663095ea7b3811461005e57806318160ddd1461009157806323b872dd146100b357806370a08231146100ec578063a9059cbb1461011a578063dd62ed3e1461014d575bfe5b341561006657fe5b61007d600160a060020a0360043516602435610181565b604080519115158252519081900360200190f35b341561009957fe5b6100a16101ec565b60408051918252519081900360200190f35b34156100bb57fe5b61007d600160a060020a03600435811690602435166044356101f2565b604080519115158252519081900360200190f35b34156100f457fe5b6100a1600160a060020a03600435166102ee565b60408051918252519081900360200190f35b341561012257fe5b61007d600160a060020a0360043516602435610318565b604080519115158252519081900360200190f35b341561015557fe5b6100a1600160a060020a03600435811690602435166103ca565b60408051918252519081900360200190f35b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a0383166000908152602081905260408120548290108015906102425750600160a060020a0380851660009081526001602090815260408083203390941683529290522054829010155b80156102685750600160a060020a03831660009081526020819052604090205482810110155b156102e257600160a060020a03808416600081815260208181526040808320805488019055888516808452818420805489900390556001835281842033909616845294825291829020805487900390558151868152915192939260008051602061041c8339815191529281900390910190a35060016102e6565b5060005b5b9392505050565b60006102f8610402565b50600160a060020a0381166000908152602081905260409020545b919050565b600160a060020a03331660009081526020819052604081205482901080159061035b5750600160a060020a03831660009081526020819052604090205482810110155b156103bb57600160a060020a03338116600081815260208181526040808320805488900390559387168083529184902080548701905583518681529351919360008051602061041c833981519152929081900390910190a35060016101e6565b5060006101e6565b5b92915050565b60006103d4610402565b50600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b6003805460ff8082166001011660ff199091161790555b5600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a7230582078edadabd342b34dc605a47ad9eab0ab5ad8513193a546e042b2ab9c6101d5250029",
|
||||
"networks": {
|
||||
"50": {
|
||||
"links": {},
|
||||
"events": {
|
||||
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": {
|
||||
"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"
|
||||
},
|
||||
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"updated_at": 1513088404210
|
||||
}
|
||||
},
|
||||
"schema_version": "0.0.5",
|
||||
"updated_at": 1513088404210
|
||||
}
|
72
packages/contracts/build/contracts/Migrations.json
Normal file
72
packages/contracts/build/contracts/Migrations.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"contract_name": "Migrations",
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "new_address",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "upgrade",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "last_completed_migration",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "completed",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "setCompleted",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"payable": false,
|
||||
"type": "constructor"
|
||||
}
|
||||
],
|
||||
"unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101a0806100396000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610042578063445df0ac146100605780638da5cb5b14610082578063fdacd576146100ae575bfe5b341561004a57fe5b61005e600160a060020a03600435166100c3565b005b341561006857fe5b61007061013d565b60408051918252519081900360200190f35b341561008a57fe5b610092610143565b60408051600160a060020a039092168252519081900360200190f35b34156100b657fe5b61005e600435610152565b005b6000805433600160a060020a03908116911614156101375781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b151561012557fe5b6102c65a03f1151561013357fe5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561016f5760018190555b5b5b505600a165627a7a72305820721709a2522264b5277c3048b17bea0e0f660776a386bacb5f36796ba40dac1c0029",
|
||||
"networks": {
|
||||
"50": {
|
||||
"links": {},
|
||||
"events": {},
|
||||
"updated_at": 1513088404203
|
||||
}
|
||||
},
|
||||
"schema_version": "0.0.5",
|
||||
"updated_at": 1513088404203
|
||||
}
|
189
packages/contracts/build/contracts/Mintable.json
Normal file
189
packages/contracts/build/contracts/Mintable.json
Normal file
@@ -0,0 +1,189 @@
|
||||
{
|
||||
"contract_name": "Mintable",
|
||||
"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": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "mint",
|
||||
"outputs": [],
|
||||
"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": "0x6060604052341561000c57fe5b5b6105018061001c6000396000f300606060405236156100675763ffffffff60e060020a600035041663095ea7b3811461006957806318160ddd1461009c57806323b872dd146100be57806370a08231146100f7578063a0712d6814610125578063a9059cbb1461013a578063dd62ed3e1461016d575bfe5b341561007157fe5b610088600160a060020a03600435166024356101a1565b604080519115158252519081900360200190f35b34156100a457fe5b6100ac61020c565b60408051918252519081900360200190f35b34156100c657fe5b610088600160a060020a0360043581169060243516604435610212565b604080519115158252519081900360200190f35b34156100ff57fe5b6100ac600160a060020a0360043516610335565b60408051918252519081900360200190f35b341561012d57fe5b610138600435610354565b005b341561014257fe5b610088600160a060020a03600435166024356103bc565b604080519115158252519081900360200190f35b341561017557fe5b6100ac600160a060020a036004358116906024351661046e565b60408051918252519081900360200190f35b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a03808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906102555750828110155b801561027b5750600160a060020a03841660009081526020819052604090205483810110155b1561032757600160a060020a03808516600090815260208190526040808220805487019055918716815220805484900390556000198110156102e557600160a060020a03808616600090815260016020908152604080832033909416835292905220805484900390555b83600160a060020a031685600160a060020a03166000805160206104b6833981519152856040518082815260200191505060405180910390a36001915061032c565b600091505b5b509392505050565b600160a060020a0381166000908152602081905260409020545b919050565b68056bc75e2d6310000081111561036b5760006000fd5b600160a060020a03331660009081526020819052604090205461038f90829061049b565b600160a060020a0333166000908152602081905260409020556002546103b5908261049b565b6002555b50565b600160a060020a0333166000908152602081905260408120548290108015906103ff5750600160a060020a03831660009081526020819052604090205482810110155b1561045f57600160a060020a0333811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191936000805160206104b6833981519152929081900390910190a3506001610206565b506000610206565b5b92915050565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b6000828201838110156104aa57fe5b8091505b50929150505600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a72305820b1c955ed24ff28cfa482298867cac2a83e25903b0100a429152919223fdf653f0029",
|
||||
"networks": {},
|
||||
"schema_version": "0.0.5",
|
||||
"updated_at": 1513088402049
|
||||
}
|
517
packages/contracts/build/contracts/MultiSigWallet.json
Normal file
517
packages/contracts/build/contracts/MultiSigWallet.json
Normal file
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