Compare commits

..

80 Commits

Author SHA1 Message Date
Fabio Berger
dfeea78615 Publish
- 0x.js@0.38.6
 - @0xproject/abi-gen@0.3.4
 - @0xproject/assert@0.2.14
 - @0xproject/base-contract@0.3.6
 - @0xproject/connect@0.6.17
 - @0xproject/contract-wrappers@0.1.1
 - contracts@2.1.35
 - @0xproject/dev-utils@0.4.6
 - @0xproject/fill-scenarios@0.0.6
 - @0xproject/json-schemas@0.8.3
 - @0xproject/metacoin@0.0.10
 - @0xproject/migrations@0.0.10
 - @0xproject/order-utils@0.0.9
 - @0xproject/order-watcher@0.0.8
 - @0xproject/react-docs-example@0.0.15
 - @0xproject/react-docs@0.0.16
 - @0xproject/react-shared@0.2.3
 - @0xproject/sol-compiler@0.5.4
 - @0xproject/sol-cov@0.1.3
 - @0xproject/sra-report@0.1.6
 - @0xproject/subproviders@0.10.6
 - @0xproject/testnet-faucets@1.0.36
 - @0xproject/typescript-typings@0.4.3
 - @0xproject/utils@0.7.3
 - @0xproject/web3-wrapper@0.7.3
 - @0xproject/website@0.0.39
2018-07-18 15:10:58 +02:00
Fabio Berger
c8b93adcd0 Updated CHANGELOGS 2018-07-18 15:10:52 +02:00
Fabio Berger
2b02ddc588 Merge pull request #885 from 0xProject/bug-fixes
Development Bug Fixes
2018-07-18 14:21:21 +02:00
Fabio Berger
80c7c23151 Add missing dep 2018-07-18 12:55:49 +02:00
Fabio Berger
c068b574e5 Add PR nr. 2018-07-17 18:49:00 +02:00
Fabio Berger
9a20d4e1c9 Update comments 2018-07-17 18:48:53 +02:00
Fabio Berger
cca471a1ce Add back ethers-contracts types for Aquaduct 2018-07-17 17:05:37 +02:00
Fabio Berger
66d63e8f4f Add isVerbose flag to contract-wrappers subscribe methods 2018-07-17 16:55:55 +02:00
Fabio Berger
e678fed55b Fix bug where we accidentally force Blockstream to always call bound methods with latest param 2018-07-17 16:47:10 +02:00
Fabio Berger
9b10349b7c Remove stateLayer option from OrderWatcher 2018-07-17 16:46:06 +02:00
Fabio Berger
48838e1e98 Add .vscode to gitignore 2018-07-10 14:44:49 +02:00
Fabio Berger
eafd666ecd Move sol-compiler to deps to fix type error 2018-07-10 14:44:07 +02:00
Fabio Berger
599554b785 Publish
- 0x.js@0.38.5
 - @0xproject/abi-gen@0.3.3
 - @0xproject/assert@0.2.13
 - @0xproject/base-contract@0.3.5
 - @0xproject/connect@0.6.16
 - @0xproject/contract-wrappers@0.1.0
 - contracts@2.1.34
 - @0xproject/dev-utils@0.4.5
 - @0xproject/fill-scenarios@0.0.5
 - @0xproject/json-schemas@0.8.2
 - @0xproject/metacoin@0.0.9
 - @0xproject/migrations@0.0.9
 - @0xproject/monorepo-scripts@0.2.2
 - @0xproject/order-utils@0.0.8
 - @0xproject/order-watcher@0.0.7
 - @0xproject/react-docs-example@0.0.14
 - @0xproject/react-docs@0.0.15
 - @0xproject/react-shared@0.2.2
 - @0xproject/sol-compiler@0.5.3
 - @0xproject/sol-cov@0.1.2
 - @0xproject/sol-resolver@0.0.8
 - @0xproject/sra-report@0.1.5
 - @0xproject/subproviders@0.10.5
 - @0xproject/testnet-faucets@1.0.35
 - @0xproject/tslint-config@0.4.21
 - @0xproject/types@0.8.2
 - @0xproject/typescript-typings@0.4.2
 - @0xproject/utils@0.7.2
 - @0xproject/web3-wrapper@0.7.2
 - @0xproject/website@0.0.38
2018-07-09 17:24:22 +02:00
Fabio Berger
d57d282cab Updated CHANGELOGS 2018-07-09 17:24:12 +02:00
Fabio Berger
562bef98e2 reset dep cache 2018-07-09 16:57:40 +02:00
Fabio Berger
900f819be8 Use node v9 everywhere 2018-07-09 16:54:34 +02:00
Fabio Berger
e7337c2451 Update yarn.lock 2018-07-09 16:30:46 +02:00
Fabio Berger
dc81193132 Update package so works with node v9 2018-07-09 16:22:46 +02:00
Fabio Berger
fa868b4963 Bump up node version to v9 2018-07-09 16:09:31 +02:00
Fabio Berger
62945ad363 Updated contract-wrappers to use blockstream v5 and stop unsubscribing on blocksteam error 2018-07-09 15:35:08 +02:00
Fabio Berger
61c38d35be Update yarn.lock 2018-07-09 14:14:03 +02:00
Fabio Berger
4e0ec72896 Merge branch 'development' of github.com:0xProject/0x-monorepo into development
* 'development' of github.com:0xProject/0x-monorepo:
  Add missing import
  Extend from DecodedLogArgs and fix type names
  Update ethers typings & changelog
  Back-port order-watcher changes from v2-prototype
  Back-port over utils changes from v2-prototype
2018-07-09 14:10:29 +02:00
Fabio Berger
c28289e9a8 Back-port prePublish fixes 2018-07-09 14:05:29 +02:00
Fabio Berger
e7e9ddf232 remove excess new line 2018-07-09 14:03:17 +02:00
Fabio Berger
f03784ba37 update web3-provider-engine in subproviders 2018-07-09 14:01:47 +02:00
Fabio Berger
2445e23c0b Merge pull request #842 from 0xProject/back-port-v2-prototype
Back-port changes from v2-prototype in order to publish working Order-watcher
2018-07-09 13:53:15 +02:00
Fabio Berger
cd29483187 merge development 2018-07-09 13:52:21 +02:00
Fabio Berger
9bacbdab48 Add missing import 2018-07-09 13:47:33 +02:00
Fabio Berger
551d484fb7 Extend from DecodedLogArgs and fix type names 2018-07-09 13:03:53 +02:00
Fabio Berger
ff66432b83 Update ethers typings & changelog 2018-07-09 12:33:44 +02:00
Fabio Berger
a7ae82a2d1 Back-port order-watcher changes from v2-prototype 2018-07-09 12:31:06 +02:00
Fabio Berger
5f34b5a80e Back-port over utils changes from v2-prototype 2018-07-09 11:48:30 +02:00
Leonid Logvinov
8fca2a8116 Merge pull request #768 from galkin/development
Improve 'web3-provider-engine' typings
2018-06-27 09:24:33 +03:00
Nikita Galkin
5472500119 Improve 'web3-provider-engine' typings 2018-06-25 12:22:54 +03:00
Fabio Berger
8fb5c29b4b Publish
- 0x.js@0.38.4
 - @0xproject/abi-gen@0.3.2
 - @0xproject/assert@0.2.12
 - @0xproject/base-contract@0.3.4
 - @0xproject/connect@0.6.15
 - @0xproject/contract-wrappers@0.0.5
 - contracts@2.1.33
 - @0xproject/dev-utils@0.4.4
 - @0xproject/fill-scenarios@0.0.4
 - @0xproject/json-schemas@0.8.1
 - @0xproject/metacoin@0.0.8
 - @0xproject/migrations@0.0.8
 - @0xproject/monorepo-scripts@0.2.1
 - @0xproject/order-utils@0.0.7
 - @0xproject/order-watcher@0.0.6
 - @0xproject/react-docs-example@0.0.13
 - @0xproject/react-docs@0.0.14
 - @0xproject/react-shared@0.2.1
 - @0xproject/sol-compiler@0.5.2
 - @0xproject/sol-cov@0.1.1
 - @0xproject/sol-resolver@0.0.7
 - @0xproject/sra-report@0.1.4
 - @0xproject/subproviders@0.10.4
 - @0xproject/testnet-faucets@1.0.34
 - @0xproject/tslint-config@0.4.20
 - @0xproject/types@0.8.1
 - @0xproject/typescript-typings@0.4.1
 - @0xproject/utils@0.7.1
 - @0xproject/web3-wrapper@0.7.1
 - @0xproject/website@0.0.37
2018-06-19 10:48:07 +02:00
Fabio Berger
40a061a5ca Updated CHANGELOGS 2018-06-19 10:48:00 +02:00
Fabio Berger
2ef82592a3 Improve error message 2018-06-19 10:36:19 +02:00
Fabio Berger
14b5448d70 Add missing timestamp 2018-06-19 10:35:22 +02:00
Fabio Berger
e7d45e47bf Remove the hotfix for Ethersjs and instead update to the fixed version in all packages 2018-06-19 10:30:49 +02:00
Fabio Berger
28268d4355 Update versions and CHANGELOG's to account for unpublished versions on NPM 2018-06-18 23:18:42 +02:00
Fabio Berger
50fa02c1d1 Small fixes 2018-06-18 23:16:44 +02:00
Fabio Berger
b36ff9103d Merge pull request #718 from 0xProject/improvement/publishing-flow
Improve Pre-publishing flow
2018-06-18 23:01:36 +02:00
Fabio Berger
f032c2466c Use semver package instead of getNextPatchVersion 2018-06-18 19:22:31 +02:00
Fabio Berger
b63ddc9be4 Use semver external librarty instead of semverUtils 2018-06-18 19:00:39 +02:00
Fabio Berger
171430b617 small fixes 2018-06-18 17:58:17 +02:00
Fabio Berger
d561043774 Show all errors of a given kind at once rather then throwing after the first instance is encountered 2018-06-18 17:41:03 +02:00
Fabio Berger
b1871e9ddd fix package.json 2018-06-18 16:57:22 +02:00
Fabio Berger
b4a5e7258c Add the following prePublish checks:
- That package version matches latest NPM package version (including unpublished versions)
- That changelogs are properly formatted (lastEntry version >= currentVersion, no accidental timestamps)
- Checks for and removes any git tags locally and remotely that might be left-over from a previous failed publish

Moved changelog related helpers to changelogUtils and other small cleanup refactors.
2018-06-18 16:55:59 +02:00
Fabio Berger
3c75debdf9 Remove the remove_tags script 2018-06-18 16:46:54 +02:00
Fabio Berger
84d1053f73 Add missing timestamp to web3-wrapper changelog 2018-06-15 17:11:30 +02:00
Fabio Berger
f9df42f5d9 Fix incorrect merges 2018-06-15 16:58:36 +02:00
Leonid Logvinov
4414ef0a0f fix cherry-pick 2018-06-15 16:51:13 +02:00
Leonid Logvinov
b7729ada38 fix cherry-pick 2018-06-15 16:48:29 +02:00
Leonid Logvinov
3da67feeb2 Add prepublish_checks 2018-06-15 16:45:18 +02:00
Leonid Logvinov
8a0d563a32 Add CHANGELOG entry 2018-06-15 16:44:48 +02:00
Leonid Logvinov
612fc4a949 Fix cherry-pick 2018-06-15 16:44:35 +02:00
Fabio Berger
bf915ce403 Merge pull request #709 from 0xProject/feature/pin-deps
[DEVELOPMENT] Ethersjs Issue Hot Fix
2018-06-15 14:14:45 +02:00
Fabio Berger
0f9ea9773e Add lib/test and ganache.log to npmignore 2018-06-15 14:14:30 +02:00
Fabio Berger
447a3a6c26 Fix prettier 2018-06-15 13:53:26 +02:00
Fabio Berger
f1cc16c44d Export OrderWatcherConfig from 0x.js 2018-06-15 13:38:25 +02:00
Fabio Berger
aae16b6343 Add ganache.log to gitignore 2018-06-15 13:37:08 +02:00
Fabio Berger
834e1538d1 Fix typos, versions and other mistypings 2018-06-15 11:48:52 +02:00
Leonid Logvinov
afc489bc2c Pin all external dependencies 2018-06-14 21:25:36 -07:00
Leonid Logvinov
3e061e7364 Fix the is not a function bug caused by breaking patch version https://github.com/ethers-io/ethers.js/issues/201 2018-06-14 12:31:57 -07:00
Leonid Logvinov
6395c2a8b2 Update changelogs 2018-06-04 11:19:59 -07:00
Leonid Logvinov
c8225288cd v0.7.0 2018-06-04 11:15:00 -07:00
Leonid Logvinov
4a108aa67d Set default params and jsonrpc in Web3Wrapper._sendRawPayloadAsync 2018-06-04 11:11:18 -07:00
Leonid Logvinov
fd9b3e0dcf Add default jsonRpcId to raw payloads sent from web3Wrapper 2018-06-01 16:01:04 -07:00
Leonid Logvinov
f94b647e61 Publish
- 0x.js@0.38.3
 - contracts@2.1.32
 - @0xproject/order-watcher@0.0.5
 - @0xproject/sra-report@0.1.3
 - @0xproject/testnet-faucets@1.0.33
 - @0xproject/website@0.0.36
2018-05-29 11:29:07 -07:00
Leonid Logvinov
2eccc3efaf Updated CHANGELOGS 2018-05-29 11:29:01 -07:00
Leonid Logvinov
972341725e Remove UMD bundles from order-watcher 2018-05-29 11:13:50 -07:00
Leonid Logvinov
40b10fd29d Publish
- 0x.js@0.38.2
 - @0xproject/contract-wrappers@0.0.4
 - contracts@2.1.31
 - @0xproject/order-watcher@0.0.4
 - @0xproject/sra-report@0.1.2
 - @0xproject/testnet-faucets@1.0.32
 - @0xproject/website@0.0.35
2018-05-29 11:12:33 -07:00
Leonid Logvinov
b31fcffc76 Updated CHANGELOGS 2018-05-29 11:12:26 -07:00
Leonid Logvinov
ec222ea0cd Remove UMD bundles from contract-wrappers 2018-05-29 11:04:00 -07:00
Leonid Logvinov
5533220da0 Publish
- 0x.js@0.38.1
 - @0xproject/connect@0.6.14
 - @0xproject/contract-wrappers@0.0.3
 - contracts@2.1.30
 - @0xproject/fill-scenarios@0.0.3
 - @0xproject/order-utils@0.0.6
 - @0xproject/order-watcher@0.0.3
 - @0xproject/sra-report@0.1.1
 - @0xproject/testnet-faucets@1.0.31
 - @0xproject/website@0.0.34
2018-05-29 11:01:25 -07:00
Leonid Logvinov
6ee7024457 Updated CHANGELOGS 2018-05-29 11:01:18 -07:00
Fabio Berger
f839ac9c58 Merge branch 'development' of github.com:0xProject/0x-monorepo into development
* 'development' of github.com:0xProject/0x-monorepo:
  Correct documentation variable name
  Publish
  Updated CHANGELOGS
  Updated CHANGELOGS
  Change publish command name
2018-05-22 16:39:15 -07:00
Fabio Berger
1a8b1460a6 Fix signature verification test 2018-05-22 16:38:57 -07:00
Leonid Logvinov
feac0779a4 Merge pull request #608 from prettymuchbryce/docs-fix
Correct documentation variable name
2018-05-22 15:38:27 -07:00
Bryce Neal
d9eeb0421c Correct documentation variable name 2018-05-22 13:37:38 -07:00
1079 changed files with 26877 additions and 227618 deletions

View File

@@ -11,31 +11,23 @@ jobs:
- checkout
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
- restore_cache:
name: Restore Yarn Package Cache
keys:
- yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
- yarn-packages-{{ .Branch }}
- yarn-packages-master
- yarn-packages-
key: dependency-cache-v1-{{ checksum "package.json" }}
- run:
name: yarn
command: yarn --frozen-lockfile install
command: yarn --frozen-lockfile
- save_cache:
name: Save Yarn Package Cache
key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
key: dependency-cache-v1-{{ checksum "package.json" }}
paths:
- node_modules/
- run: >
if [ -z "$(git diff --name-only v2-prototype packages/website)" ]; then
yarn build --exclude website
else
yarn build
fi
- ./node_modules
- run: wget https://s3.amazonaws.com/testrpc-shapshots/${CONTRACTS_COMMIT_HASH}.zip
- run: unzip ${CONTRACTS_COMMIT_HASH}.zip -d testrpc_snapshot
- run: node ./node_modules/lerna/bin/lerna.js bootstrap
- run: yarn build
- save_cache:
key: repo-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo
test-contracts-ganache:
test-installation:
docker:
- image: circleci/node:9
working_directory: ~/repo
@@ -43,19 +35,58 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn test:installation
test-0xjs:
docker:
- image: circleci/node:9
working_directory: ~/repo
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run:
name: testrpc
command: npm run testrpc -- --db testrpc_snapshot
background: true
- run: yarn wsrun test:circleci 0x.js
- save_cache:
key: coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/0x.js/coverage/lcov.info
test-contracts:
docker:
- image: circleci/node:9
working_directory: ~/repo
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run:
name: testrpc
command: npm run testrpc -- --db testrpc_snapshot
background: true
- run: yarn wsrun test:circleci contracts
test-contracts-geth:
- save_cache:
key: coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/contracts/coverage/lcov.info
test-sol-compiler:
docker:
- image: circleci/node:9
- image: albrow/0x-devnet
working_directory: ~/repo
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
# HACK(albrow): we need to sleep 10 seconds to ensure the devnet is
# initialized
- run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test contracts
- run:
name: testrpc
command: npm run testrpc -- --db testrpc_snapshot
background: true
- run: yarn wsrun test:circleci @0xproject/sol-compiler
- save_cache:
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/sol-compiler/coverage/lcov.info
test-rest:
docker:
- image: circleci/node:9
@@ -64,46 +95,19 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci 0x.js
- run: yarn wsrun test:circleci @0xproject/abi-gen
- run: yarn wsrun test:circleci @0xproject/assert
- run: yarn wsrun test:circleci @0xproject/base-contract
- run: yarn wsrun test:circleci @0xproject/connect
- run: yarn wsrun test:circleci @0xproject/contract-wrappers
- run: yarn wsrun test:circleci @0xproject/dev-utils
- run: yarn wsrun test:circleci @0xproject/json-schemas
- run: yarn wsrun test:circleci @0xproject/metacoin
- run: yarn wsrun test:circleci @0xproject/order-utils
- run: yarn wsrun test:circleci @0xproject/order-watcher
- run: yarn wsrun test:circleci @0xproject/sol-compiler
- run: yarn wsrun test:circleci @0xproject/sol-cov
- run: yarn wsrun test:circleci @0xproject/sra-report
- run: yarn wsrun test:circleci @0xproject/subproviders
- run: yarn wsrun test:circleci @0xproject/web3-wrapper
- save_cache:
key: coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/0x.js/coverage/lcov.info
- save_cache:
key: coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/abi-gen/coverage/lcov.info
- run:
name: testrpc
command: npm run testrpc -- --db testrpc_snapshot
background: true
- run: yarn wsrun test:circleci --exclude contracts --exclude 0x.js --exclude @0xproject/sol-compiler --stages --exclude-missing
- save_cache:
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/assert/coverage/lcov.info
- save_cache:
key: coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/base-contract/coverage/lcov.info
- save_cache:
key: coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/connect/coverage/lcov.info
- save_cache:
key: coverage-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/contract-wrappers/coverage/lcov.info
- save_cache:
key: coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
paths:
@@ -113,38 +117,27 @@ jobs:
paths:
- ~/repo/packages/json-schemas/coverage/lcov.info
- save_cache:
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
key: coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/metacoin/coverage/lcov.info
- save_cache:
key: coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/order-utils/coverage/lcov.info
- save_cache:
key: coverage-order-watcher-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/order-watcher/coverage/lcov.info
- save_cache:
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/sol-compiler/coverage/lcov.info
- ~/repo/packages/subproviders/coverage/lcov.info
- save_cache:
key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/sol-cov/coverage/lcov.info
- save_cache:
key: coverage-sra-report-{{ .Environment.CIRCLE_SHA1 }}
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/sra-report/coverage/lcov.info
- save_cache:
key: coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/subproviders/coverage/lcov.info
- save_cache:
key: coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/web3-wrapper/coverage/lcov.info
static-tests:
- ~/repo/packages/metacoin/coverage/lcov.info
lint:
working_directory: ~/repo
docker:
- image: circleci/node:9
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn lerna:run lint
prettier:
working_directory: ~/repo
docker:
- image: circleci/node:9
@@ -153,7 +146,6 @@ jobs:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn prettier:ci
- run: yarn lerna:run lint
submit-coverage:
docker:
- image: circleci/node:9
@@ -164,22 +156,13 @@ jobs:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
@@ -188,49 +171,49 @@ jobs:
- coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-order-watcher-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
- coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-sra-report-{{ .Environment.CIRCLE_SHA1 }}
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn report_coverage
workflows:
version: 2
main:
jobs:
- build
- test-contracts-ganache:
- test-installation:
requires:
- build
- test-contracts-geth:
- test-0xjs:
requires:
- build
- test-contracts:
requires:
- build
- test-sol-compiler:
requires:
- build
- test-rest:
requires:
- build
- static-tests:
- prettier:
requires:
- build
- lint:
requires:
- build
- submit-coverage:
requires:
- test-0xjs
- test-sol-compiler
- test-rest
- test-contracts

16
.gitignore vendored
View File

@@ -41,7 +41,6 @@ typings/
# Optional npm cache directory
.npm
.npmrc
# Optional eslint cache
.eslintcache
@@ -82,23 +81,20 @@ packages/sol-cov/test/fixtures/artifacts/
packages/metacoin/artifacts/
packages/order-watcher/test/artifacts/
packages/contract-wrappers/test/artifacts/
packages/contract-wrappers/src/artifacts/
packages/order-watcher/src/artifacts/
# generated contract watcher
packages/0x.js/src/generated_contract_wrappers/
packages/contracts/generated_contract_wrappers/
# generated contract wrappers
packages/0x.js/src/contract_wrappers/generated/
packages/contracts/src/contract_wrappers/generated/
packages/contract-wrappers/src/contract_wrappers/generated/
packages/metacoin/src/contract_wrappers
packages/fill-scenarios/src/generated_contract_wrappers/
packages/order-watcher/src/generated_contract_wrappers/
packages/order-utils/src/generated_contract_wrappers/
packages/migrations/src/1.0.0/contract_wrappers
packages/migrations/src/2.0.0/contract_wrappers
packages/migrations/src/2.0.0-beta-testnet/contract_wrappers
packages/migrations/src/contract_wrappers
# solc-bin in sol-compiler
packages/sol-compiler/solc_bin/
# Monorepo scripts
packages/*/scripts/
ganache.log

View File

@@ -1,24 +1,10 @@
lib
.nyc_output
/packages/contract-wrappers/src/contract_wrappers/generated/
/packages/metacoin/src/contract_wrappers
/packages/0x.js/src/generated_contract_wrappers/
/packages/contracts/generated_contract_wrappers/
/packages/fill-scenarios/src/generated_contract_wrappers/
/packages/order-watcher/src/generated_contract_wrappers/
/packages/order-utils/src/generated_contract_wrappers/
/packages/migrations/src/1.0.0/contract_wrappers
/packages/migrations/src/2.0.0/contract_wrappers
/packages/migrations/src/2.0.0-beta-testnet/contract_wrappers
/packages/0x.js/src/artifacts
/packages/0x.js/test/artifacts
/packages/contracts/src/artifacts
/packages/contract-wrappers/src/artifacts
/packages/order-watcher/src/artifacts
/packages/metacoin/artifacts
/packages/contract-wrappers/test/artifacts
/packages/order-watcher/test/artifacts
/packages/migrations/artifacts/1.0.0
/packages/migrations/artifacts/2.0.0
/packages/migrations/artifacts/2.0.0-beta-testnet
package.json
scripts/postpublish_utils.js

View File

@@ -21,18 +21,6 @@ If you're adding a new public function/member, make sure you document it with Ja
If the sub-package you are modifying has a `CHANGELOG.md` file, make sure to add an entry in it for the change made to the package. For published packages, only changes that modify the public interface or behavior of the package need a CHANGELOG entry.
#### Enabling code coverage checks on your fork
If you simply fork the repo and then create a PR sourced from it, your PR will fail its test coverage check. This is because the 0x CircleCI configuration sets the `COVERALLS_REPO_TOKEN` environment variable to the token for 0xProject/0x-monorepo, but when running the check against your fork the token needs to match the repo that is your fork, rather than the 0x repo.
To facilitate this check, after creating your fork, but before creating the branch for your PR, do the following:
1. Log in to [coveralls.io](https://coveralls.io/), go to Add Repos, and enable your fork. Then go to the settings for that repo, and copy the Repo Token identifier.
2. Log in to [CircleCI](https://circleci.com/login), go to Add Projects, click the Set Up Project button corresponding to your fork, and then click Start Building. (Aside from step 3 below, no actual set up is needed, since it will use the `.circleci/config.yml` file in 0x-monorepo, so you can ignore all of the instruction/explanation given on the page with the Start Building button.)
3. In CircleCI, configure your project to add an Environment Variable, with name `COVERALLS_REPO_TOKEN`, and for the value paste in the Repo Token you copied in step 1.
Now, when you push to your branch, CircleCI will automatically run all of the checks in your own instance, and the coverage check will work since it has the proper Repo Token, and the PR will magically refer to your own checks rather than running them in the 0x CircleCI instance.
### Styleguide
We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) to keep our code style consistent.

View File

@@ -1,27 +1,41 @@
<!--- Thank you for taking the time to submit a Pull Request -->
<!--- Provide a general summary of the issue in the Title above -->
## Description
<!--- Describe your changes in detail -->
## Testing instructions
## Motivation and Context
<!--- Please describe how reviewers can test your changes -->
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->
## Types of changes
<!--- What types of changes does your code introduce? Uncomment all the bullets that apply: -->
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
<!-- * Bug fix (non-breaking change which fixes an issue) -->
<!-- * New feature (non-breaking change which adds functionality) -->
<!-- * Breaking change (fix or feature that would cause existing functionality to change) -->
* [ ] Bug fix (non-breaking change which fixes an issue)
* [ ] New feature (non-breaking change which adds functionality)
* [ ] Breaking change (fix or feature that would cause existing functionality to change)
## Checklist:
<!--- The following points should be used to indicate the progress of your PR. Put an `x` in all the boxes that apply right now, and come back over time and check them off as you make progress. If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
* [ ] Prefixed the title of this PR with `[WIP]` if it is a work in progress.
* [ ] Prefixed the title of this PR with bracketed package name(s) corresponding to the changed package(s). For example: `[sol-cov] Fixed bug`.
* [ ] Added tests to cover my changes, or decided that tests would be too impractical.
* [ ] Updated documentation, or decided that no doc change is needed.
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
* [ ] Change requires a change to the documentation.
* [ ] Added tests to cover my changes.
* [ ] Added new entries to the relevant CHANGELOG.jsons.
* [ ] Labeled this PR with the 'WIP' label if it is a work in progress.
* [ ] Labeled this PR with the labels corresponding to the changed package.

View File

@@ -6,11 +6,8 @@
This repository is a monorepo including the 0x protocol smart contracts and numerous developer tools. Each public sub-package is independently published to NPM.
If you're developing on 0x now or are interested in using 0x infrastructure in the future, please join our [developer mailing list][dev-mailing-list-url] for updates.
[website-url]: https://0xproject.com/
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
[dev-mailing-list-url]: http://eepurl.com/dx4cPf
[![CircleCI](https://circleci.com/gh/0xProject/0x-monorepo.svg?style=svg&circle-token=61bf7cd8c9b4e11b132089dfcffdd1be277d1e0c)](https://circleci.com/gh/0xProject/0x-monorepo)
[![Coverage Status](https://coveralls.io/repos/github/0xProject/0x-monorepo/badge.svg?branch=development)](https://coveralls.io/github/0xProject/0x-monorepo?branch=development)

View File

@@ -1,10 +1,15 @@
{
"lerna": "3.0.0-beta.23",
"lerna": "2.5.1",
"packages": ["packages/*"],
"version": "independent",
"command": {
"commands": {
"publish": {
"ignoreChanges": ["test/**/*", "*.md", "scripts", "lib", "tslint.json", "tsconfig.json"]
"allowBranch": "development"
}
},
"version": "independent",
"commands": {
"publish": {
"ignore": ["test/**/*", "*.md", "scripts", "lib", "tslint.json", "tsconfig.json"]
}
},
"npmClient": "yarn",

View File

@@ -2,7 +2,7 @@
"private": true,
"name": "0x-monorepo",
"engines": {
"node": ">=6.12"
"node" : ">=6.12"
},
"workspaces": [
"packages/*"
@@ -13,42 +13,34 @@
"prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}' --config .prettierrc",
"report_coverage": "lcov-result-merger 'packages/*/coverage/lcov.info' | coveralls",
"test:installation": "node ./packages/monorepo-scripts/lib/test_installation.js",
"test:installation:local": "IS_LOCAL_PUBLISH=true node ./packages/monorepo-scripts/lib/test_installation.js",
"run:publish": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild:no_website script:publish",
"run:publish:local": "IS_LOCAL_PUBLISH=true yarn run:publish",
"run:publish": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild script:publish",
"run:publish:dry": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild script:publish:dry",
"script:prepublish_checks": "node ./packages/monorepo-scripts/lib/prepublish_checks.js",
"script:publish": "node ./packages/monorepo-scripts/lib/publish.js",
"script:publish:dry": "IS_DRY_RUN=true yarn script:publish",
"install:all": "yarn install",
"wsrun": "wsrun",
"lerna": "lerna",
"watch": "wsrun watch_without_deps $PKG --fast-exit -r --stages --done-criteria='complete|successfully'",
"lerna:run": "lerna run",
"watch": "wsrun watch $PKG --fast-exit -r --stages --done-criteria='complete|successfully'",
"build": "wsrun build $PKG --fast-exit -r --stages",
"build:no_website": "wsrun build $PKG --fast-exit -r --stages --exclude @0xproject/website",
"build:monorepo_scripts": "PKG=@0xproject/monorepo-scripts yarn build",
"clean": "wsrun clean $PKG --fast-exit -r --parallel",
"remove_node_modules": "lerna clean --yes; rm -rf node_modules",
"rebuild": "run-s clean build",
"rebuild:no_website": "run-s clean build:no_website",
"test": "wsrun test $PKG --fast-exit --serial --exclude-missing",
"stage_docs": "wsrun docs:stage $PKG --fast-exit --parallel --exclude-missing",
"lint": "wsrun lint $PKG --fast-exit --parallel --exclude-missing",
"comment:postinstall": "HACK: For some reason `yarn` is not setting up symlinks properly for order-utils. We temporarily set them manually. Remove this after V2 refactor is complete."
"test": "wsrun test $PKG --serial --exclude-missing",
"stage_docs": "wsrun docs:stage $PKG --parallel --exclude-missing",
"lint": "wsrun lint $PKG --parallel --exclude-missing"
},
"config": {
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
},
"devDependencies": {
"async-child-process": "^1.1.1",
"async-child-process": "1.1.1",
"coveralls": "^3.0.0",
"ganache-cli": "6.1.3",
"ganache-cli": "^6.1.0",
"lcov-result-merger": "^3.0.0",
"@0x-lerna-fork/lerna": "3.0.0-beta.23",
"npm-run-all": "^4.1.2",
"prettier": "^1.11.1",
"source-map-support": "^0.5.6",
"lerna": "^2.5.1",
"npm-run-all": "4.1.2",
"prettier": "1.12.1",
"wsrun": "^2.2.0"
},
"resolutions": {
"ethers": "0xproject/ethers.js#eip-838-reasons"
}
}

View File

@@ -9,3 +9,5 @@ test/
/generated_docs/
/scripts/
/lib/src/monorepo_scripts/
/lib/test/
ganache.log

View File

@@ -1,81 +1,4 @@
[
{
"version": "1.0.1-rc.2",
"changes": [
{
"note": "Fixed bug caused by importing non-existent dep"
}
],
"timestamp": 1532614997
},
{
"version": "1.0.1-rc.1",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1532605697
},
{
"timestamp": 1532357734,
"version": "1.0.0",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532043100,
"version": "1.0.0-rc.2",
"changes": [
{
"note": "Remove `zeroEx.assetData` and instead re-export it's static functions directly off `ZeroEx`"
}
]
},
{
"timestamp": 1532043000,
"version": "1.0.0-rc.1",
"changes": [
{
"note": "Remove tokenRegistry wrapper",
"pr": 863
},
{
"note": "Rename `zeroEx.token` to `zeroEx.erc20Token`, and add `zeroEx.erc721Token`",
"pr": 863
},
{
"note": "Rename `zeroEx.proxy` to `zeroEx.erc20Proxy` and add `zeroEx.erc721Proxy`",
"pr": 863
},
{
"note":
"Refactored `ZeroEx.isValidSignature` to `zeroEx.isValidSignatureAsync`. It is now async so that it can verify contract-dependent signature types",
"pr": 863
},
{
"note":
"Refactored `signOrderHashAsync` to `ecSignOrderHashAsync`. There are now many non-ECSignature ways to sign orders too.",
"pr": 863
},
{
"note":
"Removed `createOrderWatcherAsync` method. Will be added back once OrderWatcher is refactored for V2",
"pr": 863
},
{
"note": "0x.js exports renamed contract events and event arg types",
"pr": 863
},
{
"note": "Export `ZeroEx.assetData` with methods to decode/encode assetData fields found in 0x orders",
"pr": 884
}
]
},
{
"timestamp": 1531919263,
"version": "0.38.6",

View File

@@ -1,37 +1,10 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.0.1-rc.2 - _July 26, 2018_
* Fixed bug caused by importing non-existent dep
## v1.0.1-rc.1 - _July 26, 2018_
* Dependencies updated
## v1.0.0 - _July 23, 2018_
* Dependencies updated
## v1.0.0-rc.2 - _July 20, 2018_
* Remove `zeroEx.assetData` and instead re-export it's static functions directly off `ZeroEx`
## v1.0.0-rc.1 - _July 20, 2018_
* Remove tokenRegistry wrapper (#863)
* Rename `zeroEx.token` to `zeroEx.erc20Token`, and add `zeroEx.erc721Token` (#863)
* Rename `zeroEx.proxy` to `zeroEx.erc20Proxy` and add `zeroEx.erc721Proxy` (#863)
* Refactored `ZeroEx.isValidSignature` to `zeroEx.isValidSignatureAsync`. It is now async so that it can verify contract-dependent signature types (#863)
* Refactored `signOrderHashAsync` to `ecSignOrderHashAsync`. There are now many non-ECSignature ways to sign orders too. (#863)
* Removed `createOrderWatcherAsync` method. Will be added back once OrderWatcher is refactored for V2 (#863)
* 0x.js exports renamed contract events and event arg types (#863)
* Export `ZeroEx.assetData` with methods to decode/encode assetData fields found in 0x orders (#884)
## v0.38.6 - _July 18, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "0x.js",
"version": "1.0.1-rc.1",
"version": "0.38.6",
"engines": {
"node": ">=6.12"
},
@@ -15,30 +15,27 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && yarn build:all && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"build:all": "run-p build:umd:prod build:commonjs; exit 0;",
"pre_build": "run-s update_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts",
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json src/artifacts; done;",
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(ZRXToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
"lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
"watch": "tsc -w",
"prebuild": "run-s clean generate_contract_wrappers",
"build": "run-p build:umd:prod build:commonjs; exit 0;",
"generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
"lint": "tslint --project .",
"test:circleci": "run-s test:coverage",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test": "run-s clean test:commonjs",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"clean": "shx rm -rf _bundles lib test_temp scripts src/generated_contract_wrappers",
"clean": "shx rm -rf _bundles lib test_temp scripts src/contract_wrappers/generated",
"build:umd:prod": "NODE_ENV=production webpack",
"build:commonjs": "tsc && yarn copy_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"build:commonjs": "tsc && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"test:commonjs": "run-s build:commonjs run_mocha",
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "node scripts/stage_docs.js",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
},
"config": {
"contracts": "ZRXToken",
"compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry",
"postpublish": {
"assets": [
"packages/0x.js/_bundles/index.js",
@@ -47,15 +44,16 @@
"docPublishConfigs": {
"extraFileIncludes": [
"../types/src/index.ts",
"../ethereum-types/src/index.ts",
"../contract-wrappers/src/types.ts",
"../contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts",
"../contract-wrappers/src/contract_wrappers/exchange_wrapper.ts",
"../contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts",
"../contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts",
"../contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts",
"../contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts",
"../order-watcher/src/order_watcher/order_watcher.ts"
"../contract-wrappers/src/contract_wrappers/token_registry_wrapper.ts",
"../contract-wrappers/src/contract_wrappers/token_transfer_proxy_wrapper.ts",
"../contract-wrappers/src/contract_wrappers/token_wrapper.ts",
"../order-watcher/src/order_watcher/order_watcher.ts",
"./src/contract_wrappers/generated/ether_token.ts",
"./src/contract_wrappers/generated/token.ts",
"./src/contract_wrappers/generated/exchange.ts"
],
"s3BucketPath": "s3://doc-jsons/0x.js/",
"s3StagingBucketPath": "s3://staging-doc-jsons/0x.js/"
@@ -68,49 +66,49 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@0xproject/abi-gen": "^1.0.2",
"@0xproject/dev-utils": "^1.0.2",
"@0xproject/migrations": "^1.0.2",
"@0xproject/monorepo-scripts": "^1.0.3",
"@0xproject/tslint-config": "^1.0.3",
"@0xproject/abi-gen": "^0.3.4",
"@0xproject/dev-utils": "^0.4.6",
"@0xproject/migrations": "^0.0.10",
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/tslint-config": "^0.4.21",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",
"@types/sinon": "^2.2.2",
"awesome-typescript-loader": "^3.1.3",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"json-loader": "^0.5.4",
"make-promises-safe": "^1.1.0",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"opn-cli": "^3.1.0",
"shx": "^0.2.2",
"sinon": "^4.0.0",
"source-map-support": "^0.5.0",
"tslint": "5.11.0",
"@types/mocha": "2.2.48",
"@types/node": "9.6.0",
"@types/sinon": "2.3.7",
"awesome-typescript-loader": "3.5.0",
"chai": "4.1.2",
"chai-as-promised": "7.1.1",
"chai-bignumber": "2.0.1",
"copyfiles": "1.2.0",
"dirty-chai": "2.0.1",
"json-loader": "0.5.7",
"make-promises-safe": "1.1.0",
"mocha": "4.1.0",
"npm-run-all": "4.1.2",
"nyc": "11.6.0",
"opn-cli": "3.1.0",
"prettier": "1.12.1",
"shx": "0.2.2",
"sinon": "4.4.9",
"source-map-support": "0.5.4",
"tslint": "5.8.0",
"typedoc": "0xProject/typedoc",
"typescript": "2.7.1",
"webpack": "^3.1.0"
"webpack": "3.11.0"
},
"dependencies": {
"@0xproject/assert": "^1.0.2",
"@0xproject/base-contract": "^1.0.2",
"@0xproject/contract-wrappers": "^1.0.1-rc.1",
"@0xproject/order-utils": "^1.0.1-rc.1",
"@0xproject/sol-compiler": "^1.0.2",
"@0xproject/subproviders": "^1.0.2",
"@0xproject/types": "^1.0.1-rc.1",
"@0xproject/typescript-typings": "^1.0.2",
"@0xproject/utils": "^1.0.2",
"@0xproject/web3-wrapper": "^1.1.0",
"ethereum-types": "^1.0.2",
"@0xproject/assert": "^0.2.14",
"@0xproject/base-contract": "^0.3.6",
"@0xproject/contract-wrappers": "^0.1.1",
"@0xproject/order-utils": "^0.0.9",
"@0xproject/order-watcher": "^0.0.8",
"@0xproject/sol-compiler": "^0.5.4",
"@0xproject/types": "^0.8.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"@0xproject/web3-wrapper": "^0.7.3",
"ethers": "3.0.22",
"lodash": "^4.17.4"
"lodash": "4.17.10"
},
"publishConfig": {
"access": "public"

View File

@@ -2,28 +2,24 @@ import { assert } from '@0xproject/assert';
import {
ContractWrappers,
ContractWrappersConfig,
ERC20ProxyWrapper,
ERC20TokenWrapper,
ERC721ProxyWrapper,
ERC721TokenWrapper,
EtherTokenWrapper,
ExchangeWrapper,
TokenRegistryWrapper,
TokenTransferProxyWrapper,
TokenWrapper,
} from '@0xproject/contract-wrappers';
import {
assetDataUtils,
ecSignOrderHashAsync,
generatePseudoRandomSalt,
isValidSignatureAsync,
MessagePrefixOpts,
orderHashUtils,
getOrderHashHex,
isValidOrderHash,
isValidSignature,
signOrderHashAsync,
} from '@0xproject/order-utils';
// HACK: Since we export assetDataUtils from ZeroEx and it has AssetProxyId, ERC20AssetData and ERC721AssetData
// in it's public interface, we need to import these types here.
// tslint:disable-next-line:no-unused-variable
import { AssetProxyId, ECSignature, ERC20AssetData, ERC721AssetData, Order, SignedOrder } from '@0xproject/types';
import { OrderWatcher, OrderWatcherConfig } from '@0xproject/order-watcher';
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { constants } from './utils/constants';
@@ -43,29 +39,25 @@ export class ZeroEx {
*/
public exchange: ExchangeWrapper;
/**
* An instance of the ERC20TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
* An instance of the TokenRegistryWrapper class containing methods for interacting with the 0x
* TokenRegistry smart contract.
*/
public erc20Token: ERC20TokenWrapper;
public tokenRegistry: TokenRegistryWrapper;
/**
* An instance of the ERC721TokenWrapper class containing methods for interacting with any ERC721 token smart contract.
* An instance of the TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
*/
public erc721Token: ERC721TokenWrapper;
public token: TokenWrapper;
/**
* An instance of the EtherTokenWrapper class containing methods for interacting with the
* wrapped ETH ERC20 token smart contract.
*/
public etherToken: EtherTokenWrapper;
/**
* An instance of the ERC20ProxyWrapper class containing methods for interacting with the
* ERC20 proxy smart contract.
* An instance of the TokenTransferProxyWrapper class containing methods for interacting with the
* tokenTransferProxy smart contract.
*/
public erc20Proxy: ERC20ProxyWrapper;
/**
* An instance of the ERC721ProxyWrapper class containing methods for interacting with the
* ERC721 proxy smart contract.
*/
public erc721Proxy: ERC721ProxyWrapper;
private readonly _contractWrappers: ContractWrappers;
public proxy: TokenTransferProxyWrapper;
private _contractWrappers: ContractWrappers;
/**
* Generates a pseudo-random 256-bit salt.
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
@@ -75,13 +67,24 @@ export class ZeroEx {
public static generatePseudoRandomSalt(): BigNumber {
return generatePseudoRandomSalt();
}
/**
* Verifies that the elliptic curve signature `signature` was generated
* by signing `data` with the private key corresponding to the `signerAddress` address.
* @param data The hex encoded data signed by the supplied signature.
* @param signature An object containing the elliptic curve signature parameters.
* @param signerAddress The hex encoded address that signed the data, producing the supplied signature.
* @return Whether the signature is valid for the supplied signerAddress and data.
*/
public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
return isValidSignature(data, signature, signerAddress);
}
/**
* Computes the orderHash for a supplied order.
* @param order An object that conforms to the Order or SignedOrder interface definitions.
* @return The resulting orderHash from hashing the supplied order.
*/
public static getOrderHashHex(order: Order | SignedOrder): string {
return orderHashUtils.getOrderHashHex(order);
return getOrderHashHex(order);
}
/**
* Checks if the supplied hex encoded order hash is valid.
@@ -91,7 +94,7 @@ export class ZeroEx {
* @return Whether the supplied orderHash has the expected format.
*/
public static isValidOrderHash(orderHash: string): boolean {
return orderHashUtils.isValidOrderHash(orderHash);
return isValidOrderHash(orderHash);
}
/**
* A unit amount is defined as the amount of a token above the specified decimal places (integer part).
@@ -121,57 +124,6 @@ export class ZeroEx {
const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, decimals);
return baseUnitAmount;
}
/**
* Encodes an ERC20 token address into a hex encoded assetData string, usable in the makerAssetData or
* takerAssetData fields in a 0x order.
* @param tokenAddress The ERC20 token address to encode
* @return The hex encoded assetData string
*/
public static encodeERC20AssetData(tokenAddress: string): string {
return assetDataUtils.encodeERC20AssetData(tokenAddress);
}
/**
* Decodes an ERC20 assetData hex string into it's corresponding ERC20 tokenAddress & assetProxyId
* @param assetData Hex encoded assetData string to decode
* @return An object containing the decoded tokenAddress & assetProxyId
*/
public static decodeERC20AssetData(assetData: string): ERC20AssetData {
return assetDataUtils.decodeERC20AssetData(assetData);
}
/**
* Encodes an ERC721 token address into a hex encoded assetData string, usable in the makerAssetData or
* takerAssetData fields in a 0x order.
* @param tokenAddress The ERC721 token address to encode
* @param tokenId The ERC721 tokenId to encode
* @return The hex encoded assetData string
*/
public static encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber): string {
return assetDataUtils.encodeERC721AssetData(tokenAddress, tokenId);
}
/**
* Decodes an ERC721 assetData hex string into it's corresponding ERC721 tokenAddress, tokenId & assetProxyId
* @param assetData Hex encoded assetData string to decode
* @return An object containing the decoded tokenAddress, tokenId & assetProxyId
*/
public static decodeERC721AssetData(assetData: string): ERC721AssetData {
return assetDataUtils.decodeERC721AssetData(assetData);
}
/**
* Decode and return the assetProxyId from the assetData
* @param assetData Hex encoded assetData string to decode
* @return The assetProxyId
*/
public static decodeAssetProxyId(assetData: string): AssetProxyId {
return assetDataUtils.decodeAssetProxyId(assetData);
}
/**
* Decode any assetData into it's corresponding assetData object
* @param assetData Hex encoded assetData string to decode
* @return Either a ERC20 or ERC721 assetData object
*/
public static decodeAssetDataOrThrow(assetData: string): ERC20AssetData | ERC721AssetData {
return assetDataUtils.decodeAssetDataOrThrow(assetData);
}
/**
* Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library.
* @param provider The Provider instance you would like the 0x.js library to use for interacting with
@@ -183,29 +135,12 @@ export class ZeroEx {
assert.isWeb3Provider('provider', provider);
this._contractWrappers = new ContractWrappers(provider, config);
this.erc20Proxy = this._contractWrappers.erc20Proxy;
this.erc721Proxy = this._contractWrappers.erc721Proxy;
this.erc20Token = this._contractWrappers.erc20Token;
this.erc721Token = this._contractWrappers.erc721Token;
this.proxy = this._contractWrappers.proxy;
this.token = this._contractWrappers.token;
this.exchange = this._contractWrappers.exchange;
this.tokenRegistry = this._contractWrappers.tokenRegistry;
this.etherToken = this._contractWrappers.etherToken;
}
/**
* Verifies that the provided signature is valid according to the 0x Protocol smart contracts
* @param data The hex encoded data signed by the supplied signature.
* @param signature The hex encoded signature.
* @param signerAddress The hex encoded address that signed the data, producing the supplied signature.
* @return Whether the signature is valid for the supplied signerAddress and data.
*/
public async isValidSignatureAsync(data: string, signature: string, signerAddress: string): Promise<boolean> {
const isValid = await isValidSignatureAsync(
this._contractWrappers.getProvider(),
data,
signature,
signerAddress,
);
return isValid;
}
/**
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
* subscriptions so you will need to re-subscribe to all events relevant to your app after this call.
@@ -238,21 +173,23 @@ export class ZeroEx {
* @param orderHash Hex encoded orderHash to sign.
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
* must be available via the Provider supplied to 0x.js.
* @param MessagePrefixOpts Options regarding the desired prefix and whether to add it before calling `eth_sign`
* @param shouldAddPersonalMessagePrefix Some signers add the personal message prefix `\x19Ethereum Signed Message`
* themselves (e.g Parity Signer, Ledger, TestRPC) and others expect it to already be done by the client
* (e.g Metamask). Depending on which signer this request is going to, decide on whether to add the prefix
* before sending the request.
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
*/
public async ecSignOrderHashAsync(
public async signOrderHashAsync(
orderHash: string,
signerAddress: string,
messagePrefixOpts: MessagePrefixOpts,
shouldAddPersonalMessagePrefix: boolean,
): Promise<ECSignature> {
const signature = await ecSignOrderHashAsync(
return signOrderHashAsync(
this._contractWrappers.getProvider(),
orderHash,
signerAddress,
messagePrefixOpts,
shouldAddPersonalMessagePrefix,
);
return signature;
}
/**
* Waits for a transaction to be mined and returns the transaction receipt.
@@ -275,4 +212,18 @@ export class ZeroEx {
);
return transactionReceiptWithDecodedLogs;
}
/**
* Instantiates and returns a new OrderWatcher instance.
* Defaults to watching the pending state.
* @param config The configuration object. Look up the type for the description.
* @return An instance of the 0x.js OrderWatcher class.
*/
public async createOrderWatcherAsync(config?: OrderWatcherConfig): Promise<OrderWatcher> {
// Hack: Get Web3Wrapper from ContractWrappers
const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
const networkId = await web3Wrapper.getNetworkIdAsync();
const provider = this._contractWrappers.getProvider();
const orderWatcher = new OrderWatcher(provider, networkId, config);
return orderWatcher;
}
}

View File

@@ -1,7 +0,0 @@
import { ContractArtifact } from '@0xproject/sol-compiler';
import * as ZRXToken from './artifacts/ZRXToken.json';
export const artifacts = {
ZRXToken: (ZRXToken as any) as ContractArtifact,
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
{
"contract_name": "DummyToken",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "_target",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "setBalance",
"outputs": [],
"payable": false,
"type": "function"
}
]
}

View File

@@ -0,0 +1,287 @@
{
"contract_name": "EtherToken",
"abi": [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "amount",
"type": "uint256"
}
],
"name": "withdraw",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "deposit",
"outputs": [],
"payable": true,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"payable": true,
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_spender",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Deposit",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Withdrawal",
"type": "event"
}
],
"networks": {
"1": {
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
},
"3": {
"address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
},
"4": {
"address": "0xc778417e063141139fce010982780140aa0cd5ab"
},
"42": {
"address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
},
"50": {
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
}
}
}

View File

@@ -0,0 +1,172 @@
{
"contract_name": "Token",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "supply",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "remaining",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_spender",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
}
]
}

View File

@@ -0,0 +1,547 @@
{
"contract_name": "TokenRegistry",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_index",
"type": "uint256"
}
],
"name": "removeToken",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_name",
"type": "string"
}
],
"name": "getTokenAddressByName",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_symbol",
"type": "string"
}
],
"name": "getTokenAddressBySymbol",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_swarmHash",
"type": "bytes"
}
],
"name": "setTokenSwarmHash",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_token",
"type": "address"
}
],
"name": "getTokenMetaData",
"outputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "uint8"
},
{
"name": "",
"type": "bytes"
},
{
"name": "",
"type": "bytes"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_name",
"type": "string"
},
{
"name": "_symbol",
"type": "string"
},
{
"name": "_decimals",
"type": "uint8"
},
{
"name": "_ipfsHash",
"type": "bytes"
},
{
"name": "_swarmHash",
"type": "bytes"
}
],
"name": "addToken",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_name",
"type": "string"
}
],
"name": "setTokenName",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "tokens",
"outputs": [
{
"name": "token",
"type": "address"
},
{
"name": "name",
"type": "string"
},
{
"name": "symbol",
"type": "string"
},
{
"name": "decimals",
"type": "uint8"
},
{
"name": "ipfsHash",
"type": "bytes"
},
{
"name": "swarmHash",
"type": "bytes"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "tokenAddresses",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_name",
"type": "string"
}
],
"name": "getTokenByName",
"outputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "uint8"
},
{
"name": "",
"type": "bytes"
},
{
"name": "",
"type": "bytes"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getTokenAddresses",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_ipfsHash",
"type": "bytes"
}
],
"name": "setTokenIpfsHash",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_symbol",
"type": "string"
}
],
"name": "getTokenBySymbol",
"outputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "uint8"
},
{
"name": "",
"type": "bytes"
},
{
"name": "",
"type": "bytes"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_symbol",
"type": "string"
}
],
"name": "setTokenSymbol",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "name",
"type": "string"
},
{
"indexed": false,
"name": "symbol",
"type": "string"
},
{
"indexed": false,
"name": "decimals",
"type": "uint8"
},
{
"indexed": false,
"name": "ipfsHash",
"type": "bytes"
},
{
"indexed": false,
"name": "swarmHash",
"type": "bytes"
}
],
"name": "LogAddToken",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "name",
"type": "string"
},
{
"indexed": false,
"name": "symbol",
"type": "string"
},
{
"indexed": false,
"name": "decimals",
"type": "uint8"
},
{
"indexed": false,
"name": "ipfsHash",
"type": "bytes"
},
{
"indexed": false,
"name": "swarmHash",
"type": "bytes"
}
],
"name": "LogRemoveToken",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "oldName",
"type": "string"
},
{
"indexed": false,
"name": "newName",
"type": "string"
}
],
"name": "LogTokenNameChange",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "oldSymbol",
"type": "string"
},
{
"indexed": false,
"name": "newSymbol",
"type": "string"
}
],
"name": "LogTokenSymbolChange",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "oldIpfsHash",
"type": "bytes"
},
{
"indexed": false,
"name": "newIpfsHash",
"type": "bytes"
}
],
"name": "LogTokenIpfsHashChange",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "oldSwarmHash",
"type": "bytes"
},
{
"indexed": false,
"name": "newSwarmHash",
"type": "bytes"
}
],
"name": "LogTokenSwarmHashChange",
"type": "event"
}
],
"networks": {
"1": {
"address": "0x926a74c5c36adf004c87399e65f75628b0f98d2c"
},
"3": {
"address": "0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed"
},
"4": {
"address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
},
"42": {
"address": "0xf18e504561f4347bea557f3d4558f559dddbae7f"
},
"50": {
"address": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082"
}
}
}

View File

@@ -0,0 +1,187 @@
{
"contract_name": "TokenTransferProxy",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "token",
"type": "address"
},
{
"name": "from",
"type": "address"
},
{
"name": "to",
"type": "address"
},
{
"name": "value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
}
],
"name": "addAuthorizedAddress",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "authorities",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
}
],
"name": "removeAuthorizedAddress",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "authorized",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getAuthorizedAddresses",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "target",
"type": "address"
},
{
"indexed": true,
"name": "caller",
"type": "address"
}
],
"name": "LogAuthorizedAddressAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "target",
"type": "address"
},
{
"indexed": true,
"name": "caller",
"type": "address"
}
],
"name": "LogAuthorizedAddressRemoved",
"type": "event"
}
],
"networks": {
"1": {
"address": "0x8da0d80f5007ef1e431dd2127178d224e32c2ef4"
},
"3": {
"address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
},
"4": {
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
},
"42": {
"address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4"
},
"50": {
"address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48"
}
}
}

View File

@@ -0,0 +1,20 @@
{
"contract_name": "ZRX",
"networks": {
"1": {
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
},
"3": {
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
},
"4": {
"address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8"
},
"42": {
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
},
"50": {
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
}
}
}

View File

@@ -1,38 +1,32 @@
export { ZeroEx } from './0x';
export { MessagePrefixType, MessagePrefixOpts } from '@0xproject/order-utils';
export { Web3ProviderEngine, RPCSubprovider } from '@0xproject/subproviders';
export {
BlockParamLiteral,
FilterObject,
BlockParam,
ContractEventArg,
ExchangeContractErrs,
LogWithDecodedArgs,
Order,
Provider,
SignedOrder,
ECSignature,
OrderStateValid,
OrderStateInvalid,
OrderState,
Token,
ERC20AssetData,
ERC721AssetData,
AssetProxyId,
} from '@0xproject/types';
export {
BlockParamLiteral,
FilterObject,
BlockParam,
LogWithDecodedArgs,
ContractEventArg,
Provider,
TransactionReceipt,
TransactionReceiptWithDecodedLogs,
} from 'ethereum-types';
} from '@0xproject/types';
export { OrderWatcherConfig } from '@0xproject/order-watcher';
export {
EventCallback,
ContractEvent,
IndexedFilterValues,
BlockRange,
OrderCancellationRequest,
OrderFillRequest,
ContractEventArgs,
MethodOpts,
@@ -42,25 +36,18 @@ export {
DecodedLogEvent,
OnOrderStateChangeCallback,
ContractWrappersError,
WETH9Events,
WETH9WithdrawalEventArgs,
WETH9ApprovalEventArgs,
WETH9EventArgs,
WETH9DepositEventArgs,
WETH9TransferEventArgs,
ERC20TokenTransferEventArgs,
ERC20TokenApprovalEventArgs,
ERC20TokenEvents,
ERC20TokenEventArgs,
ERC721TokenApprovalEventArgs,
ERC721TokenApprovalForAllEventArgs,
ERC721TokenTransferEventArgs,
ERC721TokenEvents,
ExchangeCancelUpToEventArgs,
ExchangeAssetProxyRegisteredEventArgs,
ExchangeFillEventArgs,
ExchangeCancelEventArgs,
ExchangeEventArgs,
EtherTokenContractEventArgs,
WithdrawalContractEventArgs,
DepositContractEventArgs,
EtherTokenEvents,
TransferContractEventArgs,
ApprovalContractEventArgs,
TokenContractEventArgs,
TokenEvents,
LogErrorContractEventArgs,
LogCancelContractEventArgs,
LogFillContractEventArgs,
ExchangeContractEventArgs,
ExchangeEvents,
ContractWrappersConfig,
OrderInfo,
} from '@0xproject/contract-wrappers';

View File

@@ -8,8 +8,8 @@ export const zeroExPrivateNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {
@@ -29,7 +29,7 @@ export const zeroExPrivateNetworkConfigSchema = {
'networkId',
'zrxContractAddress',
'exchangeContractAddress',
'erc20ProxyContractAddress',
'erc721ProxyContractAddress',
'tokenRegistryContractAddress',
'tokenTransferProxyContractAddress',
],
};

View File

@@ -22,8 +22,8 @@ export const zeroExPublicNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {

View File

@@ -1,3 +1,16 @@
import {
BlockParam,
BlockParamLiteral,
ContractAbi,
ContractEventArg,
ExchangeContractErrs,
FilterObject,
LogWithDecodedArgs,
Order,
OrderState,
SignedOrder,
} from '@0xproject/types';
export enum InternalZeroExError {
NoAbiDecoder = 'NO_ABI_DECODER',
ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY',

View File

@@ -1,3 +1,5 @@
import { BigNumber } from '@0xproject/utils';
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
TESTRPC_NETWORK_ID: 50,

View File

@@ -1,14 +1,18 @@
import { ContractWrappers } from '@0xproject/contract-wrappers';
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
import 'make-promises-safe';
import 'mocha';
import * as path from 'path';
import * as Sinon from 'sinon';
import { ERC20TokenApprovalEventArgs, ERC20TokenEvents, LogWithDecodedArgs, ZeroEx } from '../src';
import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { tokenUtils } from './utils/token_utils';
import { TokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
@@ -27,7 +31,9 @@ describe('ZeroEx library', () => {
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
// Instantiate the contract instances with the current provider
await (zeroEx.exchange as any)._getExchangeContractAsync();
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
// Add property to newProvider so that we can differentiate it from old provider
(provider as any).zeroExTestId = 1;
@@ -35,43 +41,52 @@ describe('ZeroEx library', () => {
// Check that contractInstances with old provider are removed after provider update
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined();
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
// Check that all nested zeroExContract/web3Wrapper instances return the updated provider
const nestedWeb3WrapperProvider = ((zeroEx as any)._contractWrappers as ContractWrappers).getProvider();
expect((nestedWeb3WrapperProvider as any).zeroExTestId).to.be.a('number');
const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getProvider();
expect(exchangeWeb3WrapperProvider.zeroExTestId).to.be.a('number');
const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getProvider();
expect(tokenRegistryWeb3WrapperProvider.zeroExTestId).to.be.a('number');
});
});
describe('#isValidSignature', () => {
// The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes
// the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size.
const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const ethSignSignature =
'0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
const signature = {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
};
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
it("should return false if the data doesn't pertain to the signature & address", async () => {
return expect((zeroEx.exchange as any).isValidSignatureAsync('0x0', address, ethSignSignature)).to.become(
false,
);
return expect(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
).to.become(false);
});
it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
return expect(
(zeroEx.exchange as any).isValidSignatureAsync(dataHex, validUnrelatedAddress, ethSignSignature),
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
dataHex,
signature,
validUnrelatedAddress,
),
).to.become(false);
});
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
const signatureArray = ethSignSignature.split('');
// tslint:disable-next-line:custom-no-magic-numbers
signatureArray[5] = 'C'; // V = 28, instead of 27
const wrongSignature = signatureArray.join('');
return expect((zeroEx.exchange as any).isValidSignatureAsync(dataHex, address, wrongSignature)).to.become(
false,
);
const wrongSignature = _.assign({}, signature, { v: 28 });
return expect(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
).to.become(false);
});
it('should return true if the signature does pertain to the dataHex & address', async () => {
return expect((zeroEx.exchange as any).isValidSignatureAsync(dataHex, address, ethSignSignature)).to.become(
true,
);
return expect(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address),
).to.become(true);
});
});
describe('#toUnitAmount', () => {
@@ -116,16 +131,17 @@ describe('ZeroEx library', () => {
it('returns transaction receipt with decoded logs', async () => {
const availableAddresses = await zeroEx.getAvailableAddressesAsync();
const coinbase = availableAddresses[0];
const zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
const erc20ProxyAddress = zeroEx.erc20Proxy.getContractAddress();
const txHash = await zeroEx.erc20Token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const tokens = await zeroEx.tokenRegistry.getTokensAsync();
const tokenUtils = new TokenUtils(tokens);
const zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
const proxyAddress = zeroEx.proxy.getContractAddress();
const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
// tslint:disable-next-line:no-unnecessary-type-assertion
const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ERC20TokenApprovalEventArgs>;
expect(log.event).to.be.equal(ERC20TokenEvents.Approval);
const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ApprovalContractEventArgs>;
expect(log.event).to.be.equal(TokenEvents.Approval);
expect(log.args._owner).to.be.equal(coinbase);
expect(log.args._spender).to.be.equal(erc20ProxyAddress);
expect(log.args._value).to.be.bignumber.equal(zeroEx.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
expect(log.args._spender).to.be.equal(proxyAddress);
expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
});
});
describe('#config', () => {
@@ -137,13 +153,15 @@ describe('ZeroEx library', () => {
const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
});
it('allows to specify erc20Proxy contract address', async () => {
it('allows to specify token registry token contract address', async () => {
const zeroExConfig = {
erc20ProxyContractAddress: ZeroEx.NULL_ADDRESS,
tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS,
networkId: constants.TESTRPC_NETWORK_ID,
};
const zeroExWithWrongERC20ProxyAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongERC20ProxyAddress.erc20Proxy.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal(
ZeroEx.NULL_ADDRESS,
);
});
});
});

View File

@@ -0,0 +1,50 @@
import { web3Factory } from '@0xproject/dev-utils';
import * as fs from 'fs';
import 'make-promises-safe';
import { ZeroEx } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
chaiSetup.configure();
// Those tests are slower cause they're talking to a remote node
const TIMEOUT = 10000;
describe('Artifacts', () => {
describe('contracts are deployed on kovan', () => {
const kovanRpcUrl = constants.KOVAN_RPC_URL;
const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider;
const config = {
networkId: constants.KOVAN_NETWORK_ID,
};
const zeroEx = new ZeroEx(provider, config);
it('token registry contract is deployed', async () => {
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
}).timeout(TIMEOUT);
it('proxy contract is deployed', async () => {
await (zeroEx.proxy as any)._getTokenTransferProxyContractAsync();
}).timeout(TIMEOUT);
it('exchange contract is deployed', async () => {
await (zeroEx.exchange as any)._getExchangeContractAsync();
}).timeout(TIMEOUT);
});
describe('contracts are deployed on ropsten', () => {
const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider;
const config = {
networkId: constants.ROPSTEN_NETWORK_ID,
};
const zeroEx = new ZeroEx(provider, config);
it('token registry contract is deployed', async () => {
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
}).timeout(TIMEOUT);
it('proxy contract is deployed', async () => {
await (zeroEx.proxy as any)._getTokenTransferProxyContractAsync();
}).timeout(TIMEOUT);
it('exchange contract is deployed', async () => {
await (zeroEx.exchange as any)._getExchangeContractAsync();
}).timeout(TIMEOUT);
});
});

View File

@@ -1,17 +1,19 @@
import { devConstants } from '@0xproject/dev-utils';
import { runV2MigrationsAsync } from '@0xproject/migrations';
import { runMigrationsAsync } from '@0xproject/migrations';
import * as path from 'path';
import { constants } from './utils/constants';
import { provider } from './utils/web3_wrapper';
before('migrate contracts', async function(): Promise<void> {
// HACK: Since the migrations take longer then our global mocha timeout limit
// we manually increase it for this before hook.
const mochaTestTimeoutMs = 20000;
this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
this.timeout(mochaTestTimeoutMs);
const txDefaults = {
gas: devConstants.GAS_LIMIT,
gas: devConstants.GAS_ESTIMATE,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const artifactsDir = `../migrations/artifacts/2.0.0`;
await runV2MigrationsAsync(provider, artifactsDir, txDefaults);
const artifactsDir = `../migrations/artifacts/1.0.0`;
await runMigrationsAsync(provider, artifactsDir, txDefaults);
});

View File

@@ -1,9 +1,34 @@
import { artifacts } from '../../src/artifacts';
import { Token } from '@0xproject/types';
import * as _ from 'lodash';
import { constants } from './constants';
import { InternalZeroExError } from '../../src/types';
export const tokenUtils = {
getProtocolTokenAddress(): string {
return artifacts.ZRXToken.networks[constants.TESTRPC_NETWORK_ID].address;
},
};
const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
const WETH_TOKEN_SYMBOL = 'WETH';
export class TokenUtils {
private _tokens: Token[];
constructor(tokens: Token[]) {
this._tokens = tokens;
}
public getProtocolTokenOrThrow(): Token {
const zrxToken = _.find(this._tokens, { symbol: PROTOCOL_TOKEN_SYMBOL });
if (_.isUndefined(zrxToken)) {
throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
}
return zrxToken;
}
public getWethTokenOrThrow(): Token {
const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL });
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 dummyTokens;
}
}

View File

@@ -1,12 +1,9 @@
import { devConstants, web3Factory } from '@0xproject/dev-utils';
import { Provider } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
const txDefaults = {
from: devConstants.TESTRPC_FIRST_ADDRESS,
gas: devConstants.GAS_LIMIT,
};
const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true });
const web3Wrapper = new Web3Wrapper(provider);
const web3 = web3Factory.create({ shouldUseInProcessGanache: true });
const provider: Provider = web3.currentProvider;
const web3Wrapper = new Web3Wrapper(web3.currentProvider);
export { provider, web3Wrapper, txDefaults };
export { provider, web3Wrapper };

View File

@@ -1,50 +1,4 @@
[
{
"timestamp": 1532614997,
"version": "1.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532605697,
"version": "1.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.1",
"changes": [
{
"note": "Fix the abi-gen entry point in package.json",
"pr": 901
}
],
"timestamp": 1532357734
},
{
"timestamp": 1532043000,
"version": "1.0.0",
"changes": [
{
"note": "Convert e_r_c to erc in generated file names",
"pr": 822
},
{
"note": "Remove the output directory before writing to it",
"pr": 822
},
{
"note": "skip generation of wrappers that are already up to date",
"pr": 788
}
]
},
{
"timestamp": 1531919263,
"version": "0.3.4",

View File

@@ -1,28 +1,10 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.0.3 - _July 26, 2018_
* Dependencies updated
## v1.0.2 - _July 26, 2018_
* Dependencies updated
## v1.0.1 - _July 23, 2018_
* Fix the abi-gen entry point in package.json (#901)
## v1.0.0 - _July 20, 2018_
* Convert e_r_c to erc in generated file names (#822)
* Remove the output directory before writing to it (#822)
* skip generation of wrappers that are already up to date (#788)
## v0.3.4 - _July 18, 2018_
* Dependencies updated

View File

@@ -4,7 +4,8 @@ This package allows you to generate TypeScript contract wrappers from ABI files.
It's heavily inspired by [Geth abigen](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) but takes a different approach.
You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions.
[Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) are the templates used to generate the contract wrappers used by 0x.js.e
For an example of the generated [wrapper files](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/src/contract_wrappers/generated) check out 0x.js.
[Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) are the templates used to generate those files.
## Installation
@@ -44,7 +45,7 @@ You need to also specify the location of your main template used for every contr
## How to write custom templates?
The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x-monorepo/tree/development/packages/contract_templates) and start adjusting them for your needs.
The best way to get started is to copy [0x.js templates](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) and start adjusting them for your needs.
We use [handlebars](http://handlebarsjs.com/) template engine under the hood.
You need to have a master template called `contract.mustache`. it will be used to generate each contract wrapper. Although - you don't need and probably shouldn't write all your logic in a single template file. You can write [partial templates](http://handlebarsjs.com/partials.html) and as long as they are within a partials folder - they will be registered and available.

View File

@@ -1,2 +1,2 @@
#!/usr/bin/env node
require('../lib/src/index.js');
require('../lib/index.js')

View File

@@ -1,22 +1,17 @@
{
"name": "@0xproject/abi-gen",
"version": "1.0.2",
"version": "0.3.4",
"engines": {
"node": ">=6.12"
},
"description": "Generate contract wrappers from ABI and handlebars templates",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"watch": "tsc -w",
"lint": "tslint --project .",
"clean": "shx rm -rf lib scripts",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"test": "yarn run_mocha",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit",
"test:circleci": "yarn test:coverage",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"bin": {
@@ -32,37 +27,30 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
"dependencies": {
"@0xproject/typescript-typings": "^1.0.2",
"@0xproject/utils": "^1.0.2",
"chalk": "^2.3.0",
"ethereum-types": "^1.0.2",
"glob": "^7.1.2",
"handlebars": "^4.0.11",
"lodash": "^4.17.4",
"mkdirp": "^0.5.1",
"sleep": "^5.1.1",
"tmp": "^0.0.33",
"to-snake-case": "^1.0.0",
"yargs": "^10.0.3"
"@0xproject/types": "^0.8.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"chalk": "2.3.2",
"glob": "7.1.1",
"handlebars": "4.0.11",
"lodash": "4.17.10",
"mkdirp": "0.5.1",
"to-snake-case": "1.0.0",
"yargs": "11.1.0"
},
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.3",
"@0xproject/tslint-config": "^1.0.3",
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/tslint-config": "^0.4.21",
"@types/glob": "5.0.35",
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",
"@types/node": "^8.0.53",
"@types/sleep": "^0.0.7",
"@types/tmp": "^0.0.33",
"@types/yargs": "^10.0.0",
"chai": "^4.1.2",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^5.2.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.11.0",
"@types/handlebars": "4.0.36",
"@types/mkdirp": "0.5.2",
"@types/node": "9.6.0",
"@types/yargs": "10.0.2",
"copyfiles": "1.2.0",
"make-promises-safe": "1.1.0",
"npm-run-all": "4.1.2",
"shx": "0.2.2",
"tslint": "5.8.0",
"typescript": "2.7.1"
},
"publishConfig": {

View File

@@ -1,15 +1,18 @@
#!/usr/bin/env node
import { AbiDefinition, ConstructorAbi, EventAbi, MethodAbi } from '@0xproject/types';
import { abiUtils, logUtils } from '@0xproject/utils';
import chalk from 'chalk';
import { AbiDefinition, ConstructorAbi, EventAbi, MethodAbi } from 'ethereum-types';
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 { ContextData, ContractsBackend, ParamKind } from './types';
import toSnakeCase = require('to-snake-case');
import { ContextData, ContractsBackend, Method, ParamKind } from './types';
import { utils } from './utils';
const ABI_TYPE_CONSTRUCTOR = 'constructor';
@@ -67,6 +70,16 @@ function registerPartials(partialsGlob: string): void {
}
}
function writeOutputFile(name: string, renderedTsCode: string): void {
let fileName = toSnakeCase(name);
if (fileName === 'z_r_x_token') {
fileName = 'zrx_token';
}
const filePath = `${args.output}/${fileName}.ts`;
fs.writeFileSync(filePath, renderedTsCode);
logUtils.log(`Created: ${chalk.bold(filePath)}`);
}
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
if (args.partials) {
@@ -105,14 +118,6 @@ for (const abiFileName of abiFileNames) {
process.exit(1);
}
const outFileName = utils.makeOutputFileName(namedContent.name);
const outFilePath = `${args.output}/${outFileName}.ts`;
if (utils.isOutputFileUpToDate(abiFileName, outFilePath)) {
logUtils.log(`Already up to date: ${chalk.bold(outFilePath)}`);
continue;
}
let ctor = ABI.find((abi: AbiDefinition) => abi.type === ABI_TYPE_CONSTRUCTOR) as ConstructorAbi;
if (_.isUndefined(ctor)) {
ctor = utils.getEmptyConstructor(); // The constructor exists, but it's implicit in JSON's ABI definition
@@ -147,6 +152,5 @@ for (const abiFileName of abiFileNames) {
events: eventAbis,
};
const renderedTsCode = template(contextData);
utils.writeOutputFile(outFilePath, renderedTsCode);
logUtils.log(`Created: ${chalk.bold(outFilePath)}`);
writeOutputFile(namedContent.name, renderedTsCode);
}

View File

@@ -1,4 +1,4 @@
import { EventAbi, MethodAbi } from 'ethereum-types';
import { EventAbi, MethodAbi } from '@0xproject/types';
export enum ParamKind {
Input = 'input',

View File

@@ -1,8 +1,7 @@
import { AbiType, ConstructorAbi, DataItem } from 'ethereum-types';
import { AbiType, ConstructorAbi, DataItem } from '@0xproject/types';
import * as fs from 'fs';
import * as _ from 'lodash';
import * as path from 'path';
import toSnakeCase = require('to-snake-case');
import { ContractsBackend, ParamKind } from './types';
@@ -57,7 +56,7 @@ export const utils = {
const componentType = `${component.name}: ${componentValueType}`;
return componentType;
});
const tsType = `{${componentsType.join(';')}}`;
const tsType = `{${componentsType}}`;
return tsType;
}
throw new Error(`Unknown Solidity type found: ${solType}`);
@@ -93,27 +92,4 @@ export const utils = {
inputs: [],
};
},
makeOutputFileName(name: string): string {
let fileName = toSnakeCase(name);
// HACK: Snake case doesn't make a lot of sense for abbreviated names but we can't reliably detect abbreviations
// so we special-case the abbreviations we use.
fileName = fileName.replace('z_r_x', 'zrx').replace('e_r_c', 'erc');
return fileName;
},
writeOutputFile(filePath: string, renderedTsCode: string): void {
fs.writeFileSync(filePath, renderedTsCode);
},
isOutputFileUpToDate(abiFile: string, outputFile: string): boolean {
const abiFileModTimeMs = fs.statSync(abiFile).mtimeMs;
try {
const outFileModTimeMs = fs.statSync(outputFile).mtimeMs;
return outFileModTimeMs > abiFileModTimeMs;
} catch (err) {
if (err.code === 'ENOENT') {
return false;
} else {
throw err;
}
}
},
};

View File

@@ -1,86 +0,0 @@
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import * as fs from 'fs';
import 'mocha';
import * as tmp from 'tmp';
import { utils } from '../src/utils';
tmp.setGracefulCleanup(); // remove tmp files even if there are failures
chai.use(dirtyChai);
const expect = chai.expect;
describe('makeOutputFileName()', () => {
it('should handle Metacoin usage', () => {
expect(utils.makeOutputFileName('Metacoin')).to.equal('metacoin');
});
it('should handle special zrx_token case', () => {
expect(utils.makeOutputFileName('ZRXToken')).to.equal('zrx_token');
});
it('should handle special erc_token case', () => {
expect(utils.makeOutputFileName('ERC20Token')).to.equal('erc20_token');
});
});
describe('writeOutputFile()', () => {
let tempFilePath: string;
before(() => {
tempFilePath = tmp.fileSync(
{ discardDescriptor: true }, // close file (so we can update it)
).name;
});
it('should write content to output file', () => {
const content = 'hello world';
utils.writeOutputFile(tempFilePath, content);
expect(fs.readFileSync(tempFilePath).toString()).to.equal(content);
});
});
describe('isOutputFileUpToDate()', () => {
it('should throw ENOENT when there is no abi file', () => {
expect(utils.isOutputFileUpToDate.bind('nonexistant1', 'nonexistant2')).to.throw('ENOENT');
});
describe('when the abi input file exists', () => {
let abiFile: string;
before(() => {
abiFile = tmp.fileSync(
{ discardDescriptor: true }, // close file (set timestamp)
).name;
});
describe('without an existing output file', () => {
it('should return false', () => {
expect(utils.isOutputFileUpToDate(abiFile, 'nonexistant_file')).to.be.false();
});
});
describe('with an existing output file', () => {
let outputFile: string;
before(() => {
outputFile = tmp.fileSync(
{ discardDescriptor: true }, // close file (set timestamp)
).name;
const abiFileModTimeMs = fs.statSync(abiFile).mtimeMs;
const outfileModTimeMs = abiFileModTimeMs + 1;
fs.utimesSync(outputFile, outfileModTimeMs, outfileModTimeMs);
});
it('should return true when output file is newer than abi file', async () => {
expect(utils.isOutputFileUpToDate(abiFile, outputFile)).to.be.true();
});
it('should return false when output file exists but is older than abi file', () => {
const outFileModTimeMs = fs.statSync(outputFile).mtimeMs;
const abiFileModTimeMs = outFileModTimeMs + 1;
fs.utimesSync(abiFile, abiFileModTimeMs, abiFileModTimeMs);
expect(utils.isOutputFileUpToDate(abiFile, outputFile)).to.be.false();
});
});
});
});

View File

@@ -1,42 +1,4 @@
[
{
"timestamp": 1532614997,
"version": "1.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532605697,
"version": "1.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532357734,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532043000,
"version": "1.0.0",
"changes": [
{
"note":
"Fix bug in string enum assertion. We erroneously were checking against the enum keys, not values",
"pr": 821
}
]
},
{
"timestamp": 1531919263,
"version": "0.2.14",

View File

@@ -1,26 +1,10 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.0.3 - _July 26, 2018_
* Dependencies updated
## v1.0.2 - _July 26, 2018_
* Dependencies updated
## v1.0.1 - _July 23, 2018_
* Dependencies updated
## v1.0.0 - _July 20, 2018_
* Fix bug in string enum assertion. We erroneously were checking against the enum keys, not values (#821)
## v0.2.14 - _July 18, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/assert",
"version": "1.0.2",
"version": "0.2.14",
"engines": {
"node": ">=6.12"
},
@@ -8,13 +8,13 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"watch": "tsc -w",
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib test_temp scripts",
"lint": "tslint --project .",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test",
"run_mocha": "mocha lib/test/**/*_test.js --exit",
"prepublishOnly": "run-p build",
"test": "run-s clean build run_mocha",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"test:circleci": "yarn test:coverage",
@@ -30,28 +30,28 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.3",
"@0xproject/tslint-config": "^1.0.3",
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/tslint-config": "^0.4.21",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/valid-url": "^1.0.2",
"chai": "^4.0.1",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
"tslint": "5.11.0",
"@types/mocha": "2.2.48",
"@types/valid-url": "1.0.2",
"chai": "4.1.2",
"copyfiles": "1.2.0",
"dirty-chai": "2.0.1",
"make-promises-safe": "1.1.0",
"mocha": "4.1.0",
"npm-run-all": "4.1.2",
"nyc": "11.6.0",
"shx": "0.2.2",
"tslint": "5.8.0",
"typescript": "2.7.1"
},
"dependencies": {
"@0xproject/json-schemas": "^1.0.1-rc.1",
"@0xproject/typescript-typings": "^1.0.2",
"@0xproject/utils": "^1.0.2",
"lodash": "^4.17.4",
"valid-url": "^1.0.9"
"@0xproject/json-schemas": "^0.8.3",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"lodash": "4.17.10",
"valid-url": "1.0.9"
},
"publishConfig": {
"access": "public"

View File

@@ -8,41 +8,41 @@ const HEX_REGEX = /^0x[0-9A-F]*$/i;
export const assert = {
isBigNumber(variableName: string, value: BigNumber): void {
const isBigNumber = _.isObject(value) && (value as any).isBigNumber;
assert.assert(isBigNumber, assert.typeAssertionMessage(variableName, 'BigNumber', value));
this.assert(isBigNumber, this.typeAssertionMessage(variableName, 'BigNumber', value));
},
isValidBaseUnitAmount(variableName: string, value: BigNumber): void {
assert.isBigNumber(variableName, value);
const isNegative = value.lessThan(0);
assert.assert(!isNegative, `${variableName} cannot be a negative number, found value: ${value.toNumber()}`);
this.assert(!isNegative, `${variableName} cannot be a negative number, found value: ${value.toNumber()}`);
const hasDecimals = value.decimalPlaces() !== 0;
assert.assert(
this.assert(
!hasDecimals,
`${variableName} should be in baseUnits (no decimals), found value: ${value.toNumber()}`,
);
},
isString(variableName: string, value: string): void {
assert.assert(_.isString(value), assert.typeAssertionMessage(variableName, 'string', value));
this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value));
},
isFunction(variableName: string, value: any): void {
assert.assert(_.isFunction(value), assert.typeAssertionMessage(variableName, 'function', value));
this.assert(_.isFunction(value), this.typeAssertionMessage(variableName, 'function', value));
},
isHexString(variableName: string, value: string): void {
assert.assert(
this.assert(
_.isString(value) && HEX_REGEX.test(value),
assert.typeAssertionMessage(variableName, 'HexString', value),
this.typeAssertionMessage(variableName, 'HexString', value),
);
},
isETHAddressHex(variableName: string, value: string): void {
assert.assert(_.isString(value), assert.typeAssertionMessage(variableName, 'string', value));
assert.assert(addressUtils.isAddress(value), assert.typeAssertionMessage(variableName, 'ETHAddressHex', value));
this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value));
this.assert(addressUtils.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value));
},
doesBelongToStringEnum(
variableName: string,
value: string,
stringEnum: any /* There is no base type for every string enum */,
): void {
const enumValues = _.values(stringEnum);
const doesBelongToStringEnum = _.includes(enumValues, value);
const doesBelongToStringEnum = !_.isUndefined(stringEnum[value]);
const enumValues = _.keys(stringEnum);
const enumValuesAsStrings = _.map(enumValues, enumValue => `'${enumValue}'`);
const enumValuesAsString = enumValuesAsStrings.join(', ');
assert.assert(
@@ -51,22 +51,19 @@ export const assert = {
);
},
hasAtMostOneUniqueValue(value: any[], errMsg: string): void {
assert.assert(_.uniq(value).length <= 1, errMsg);
this.assert(_.uniq(value).length <= 1, errMsg);
},
isNumber(variableName: string, value: number): void {
assert.assert(_.isFinite(value), assert.typeAssertionMessage(variableName, 'number', value));
this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value));
},
isBoolean(variableName: string, value: boolean): void {
assert.assert(_.isBoolean(value), assert.typeAssertionMessage(variableName, 'boolean', value));
this.assert(_.isBoolean(value), this.typeAssertionMessage(variableName, 'boolean', value));
},
isWeb3Provider(variableName: string, value: any): void {
const isWeb3Provider = _.isFunction(value.send) || _.isFunction(value.sendAsync);
assert.assert(isWeb3Provider, assert.typeAssertionMessage(variableName, 'Provider', value));
this.assert(isWeb3Provider, this.typeAssertionMessage(variableName, 'Provider', value));
},
doesConformToSchema(variableName: string, value: any, schema: Schema, subSchemas?: Schema[]): void {
if (_.isUndefined(value)) {
throw new Error(`${variableName} can't be undefined`);
}
const schemaValidator = new SchemaValidator();
if (!_.isUndefined(subSchemas)) {
_.map(subSchemas, schemaValidator.addSchema.bind(schemaValidator));
@@ -76,15 +73,15 @@ export const assert = {
const msg = `Expected ${variableName} to conform to schema ${schema.id}
Encountered: ${JSON.stringify(value, null, '\t')}
Validation errors: ${validationResult.errors.join(', ')}`;
assert.assert(!hasValidationErrors, msg);
this.assert(!hasValidationErrors, msg);
},
isWebUri(variableName: string, value: any): void {
const isValidUrl = !_.isUndefined(validUrl.isWebUri(value));
assert.assert(isValidUrl, assert.typeAssertionMessage(variableName, 'web uri', value));
this.assert(isValidUrl, this.typeAssertionMessage(variableName, 'web uri', value));
},
isUri(variableName: string, value: any): void {
const isValidUri = !_.isUndefined(validUrl.isUri(value));
assert.assert(isValidUri, assert.typeAssertionMessage(variableName, 'uri', value));
this.assert(isValidUri, this.typeAssertionMessage(variableName, 'uri', value));
},
assert(condition: boolean, message: string): void {
if (!condition) {

View File

@@ -2,6 +2,7 @@ import { schemas } from '@0xproject/json-schemas';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import 'make-promises-safe';
import 'mocha';
import { assert } from '../src/index';
@@ -49,7 +50,7 @@ describe('Assertions', () => {
});
describe('#isFunction', () => {
it('should not throw for valid input', () => {
const validInputs = [BigNumber, assert.isString.bind(assert)];
const validInputs = [BigNumber, assert.isString];
validInputs.forEach(input => expect(assert.isFunction.bind(assert, variableName, input)).to.not.throw());
});
it('should throw for invalid input', () => {

View File

@@ -1,40 +1,4 @@
[
{
"timestamp": 1532614997,
"version": "1.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532605697,
"version": "1.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532357734,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532043000,
"version": "1.0.0",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531919263,
"version": "0.3.6",

View File

@@ -1,26 +1,10 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.0.3 - _July 26, 2018_
* Dependencies updated
## v1.0.2 - _July 26, 2018_
* Dependencies updated
## v1.0.1 - _July 23, 2018_
* Dependencies updated
## v1.0.0 - _July 20, 2018_
* Dependencies updated
## v0.3.6 - _July 18, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/base-contract",
"version": "1.0.2",
"version": "0.3.6",
"engines": {
"node": ">=6.12"
},
@@ -8,16 +8,15 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"watch": "tsc -w",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib scripts",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test",
"test": "run-s clean build run_mocha",
"test:circleci": "yarn test:coverage",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit",
"run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"lint": "tslint --project . --exclude **/src/contract_wrappers/**/*",
"lint": "tslint --project .",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"license": "Apache-2.0",
@@ -30,25 +29,25 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.3",
"@0xproject/tslint-config": "^1.0.3",
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/tslint-config": "^0.4.21",
"@types/lodash": "4.14.104",
"chai": "^4.0.1",
"copyfiles": "^1.2.0",
"make-promises-safe": "^1.1.0",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.11.0",
"chai": "4.1.2",
"copyfiles": "1.2.0",
"make-promises-safe": "1.1.0",
"mocha": "4.1.0",
"npm-run-all": "4.1.2",
"shx": "0.2.2",
"tslint": "5.8.0",
"typescript": "2.7.1"
},
"dependencies": {
"@0xproject/typescript-typings": "^1.0.2",
"@0xproject/utils": "^1.0.2",
"@0xproject/web3-wrapper": "^1.1.0",
"ethereum-types": "^1.0.2",
"@0xproject/types": "^0.8.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"@0xproject/web3-wrapper": "^0.7.3",
"ethers": "3.0.22",
"lodash": "^4.17.4"
"lodash": "4.17.10"
},
"publishConfig": {
"access": "public"

View File

@@ -1,5 +1,3 @@
import { abiUtils, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import {
AbiDefinition,
AbiType,
@@ -10,7 +8,9 @@ import {
Provider,
TxData,
TxDataPayable,
} from 'ethereum-types';
} from '@0xproject/types';
import { abiUtils, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as ethers from 'ethers';
import * as _ from 'lodash';
@@ -37,14 +37,13 @@ export class BaseContract {
protected static _lowercaseAddress(type: string, value: string): string {
return type === 'address' ? value.toLowerCase() : value;
}
protected static _bigNumberToString(_type: string, value: any): any {
protected static _bigNumberToString(type: string, value: any): any {
return _.isObject(value) && value.isBigNumber ? value.toString() : value;
}
protected static _lookupConstructorAbi(abi: ContractAbi): ConstructorAbi {
const constructorAbiIfExists = _.find(
abi,
(abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Constructor,
// tslint:disable-next-line:no-unnecessary-type-assertion
) as ConstructorAbi | undefined;
if (!_.isUndefined(constructorAbiIfExists)) {
return constructorAbiIfExists;
@@ -60,7 +59,7 @@ export class BaseContract {
return defaultConstructorAbi;
}
}
protected static _bnToBigNumber(_type: string, value: any): any {
protected static _bnToBigNumber(type: string, value: any): any {
return _.isObject(value) && value._bn ? new BigNumber(value.toString()) : value;
}
protected static async _applyDefaultsToTxDataAsync<T extends Partial<TxData | TxDataPayable>>(
@@ -72,13 +71,16 @@ export class BaseContract {
// 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.bind(_);
const txDataWithDefaults = {
const removeUndefinedProperties = _.pickBy;
const txDataWithDefaults: TxData = {
...removeUndefinedProperties(txDefaults),
...removeUndefinedProperties(txData),
};
...removeUndefinedProperties(txData as any),
// HACK: TS can't prove that T is spreadable.
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
} as any;
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults);
const estimatedGas = await estimateGasAsync(txData);
txDataWithDefaults.gas = estimatedGas;
}
return txDataWithDefaults;
}

View File

@@ -1,4 +1,4 @@
import { DataItem } from 'ethereum-types';
import { DataItem } from '@0xproject/types';
import * as _ from 'lodash';
// tslint:disable-next-line:completed-docs

View File

@@ -1,5 +1,6 @@
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import 'make-promises-safe';
import 'mocha';
import { formatABIDataItem } from '../src/utils';

View File

@@ -1,41 +1,4 @@
[
{
"timestamp": 1532614997,
"version": "1.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532605697,
"version": "1.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532357734,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532043000,
"version": "1.0.0",
"changes": [
{
"note":
"Remove `WebSocketOrderbookChannel` from the public interface and replace with `orderbookChannelFactory`"
}
]
},
{
"timestamp": 1531919263,
"version": "0.6.17",

View File

@@ -1,26 +1,10 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.0.3 - _July 26, 2018_
* Dependencies updated
## v1.0.2 - _July 26, 2018_
* Dependencies updated
## v1.0.1 - _July 23, 2018_
* Dependencies updated
## v1.0.0 - _July 20, 2018_
* Remove `WebSocketOrderbookChannel` from the public interface and replace with `orderbookChannelFactory`
## v0.6.17 - _July 18, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/connect",
"version": "1.0.2",
"version": "0.6.17",
"engines": {
"node": ">=6.12"
},
@@ -15,14 +15,13 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"watch": "tsc -w",
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib test_temp scripts",
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
"lint": "tslint --project .",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
"test": "run-s copy_test_fixtures run_mocha",
"rebuild_and_test": "run-s clean build test",
"run_mocha": "mocha lib/test/**/*_test.js --exit",
"test": "run-s clean build copy_test_fixtures run_mocha",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"test:circleci": "yarn test:coverage",
@@ -54,35 +53,34 @@
"@0xproject/assert": "^0.2.14",
"@0xproject/json-schemas": "^0.8.3",
"@0xproject/types": "^0.8.2",
"@0xproject/typescript-typings": "^1.0.2",
"@0xproject/utils": "^1.0.2",
"lodash": "^4.17.4",
"query-string": "^5.0.1",
"sinon": "^4.0.0",
"websocket": "^1.0.25"
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"isomorphic-fetch": "2.2.1",
"lodash": "4.17.10",
"query-string": "4.3.4",
"websocket": "1.0.25"
},
"devDependencies": {
"@0xproject/monorepo-scripts": "^1.0.3",
"@0xproject/tslint-config": "^1.0.3",
"@types/fetch-mock": "^5.12.2",
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/tslint-config": "^0.4.21",
"@types/fetch-mock": "5.12.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/query-string": "^5.0.1",
"@types/sinon": "^2.2.2",
"@types/websocket": "^0.0.39",
"async-child-process": "^1.1.1",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"fetch-mock": "^5.13.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
"tslint": "5.11.0",
"typedoc": "~0.8.0",
"@types/mocha": "2.2.48",
"@types/query-string": "5.1.0",
"@types/websocket": "0.0.34",
"async-child-process": "1.1.1",
"chai": "4.1.2",
"chai-as-promised": "7.1.1",
"copyfiles": "1.2.0",
"dirty-chai": "2.0.1",
"fetch-mock": "5.13.1",
"make-promises-safe": "1.1.0",
"mocha": "4.1.0",
"npm-run-all": "4.1.2",
"nyc": "11.6.0",
"shx": "0.2.2",
"tslint": "5.8.0",
"typedoc": "0.8.0",
"typescript": "2.7.1"
},
"publishConfig": {

View File

@@ -1,7 +1,7 @@
import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types';
import { fetchAsync } from '@0xproject/utils';
import 'isomorphic-fetch';
import * as _ from 'lodash';
import * as queryString from 'query-string';
@@ -38,7 +38,7 @@ const OPTS_TO_QUERY_FIELD_MAP = {
* that implement the standard relayer API v0
*/
export class HttpClient implements Client {
private readonly _apiEndpointUrl: string;
private _apiEndpointUrl: string;
/**
* Format parameters to be appended to http requests into query string form
*/
@@ -48,7 +48,7 @@ export class HttpClient implements Client {
return '';
}
// format params into a form the api expects
const formattedParams = _.mapKeys(params, (_value: any, key: string) => {
const formattedParams = _.mapKeys(params, (value: any, key: string) => {
return _.get(OPTS_TO_QUERY_FIELD_MAP, key, key);
});
// stringify the formatted object
@@ -167,7 +167,7 @@ export class HttpClient implements Client {
const headers = new Headers({
'content-type': 'application/json',
});
const response = await fetchAsync(url, {
const response = await fetch(url, {
method: requestType,
body: JSON.stringify(payload),
headers,

View File

@@ -1,5 +1,5 @@
export { HttpClient } from './http_client';
export { orderbookChannelFactory } from './orderbook_channel_factory';
export { WebSocketOrderbookChannel } from './ws_orderbook_channel';
export {
Client,
FeesRequest,
@@ -14,6 +14,7 @@ export {
TokenPairsItem,
TokenPairsRequestOpts,
TokenTradeInfo,
WebSocketOrderbookChannelConfig,
} from './types';
export { Order, SignedOrder } from '@0xproject/types';
export { ECSignature, Order, SignedOrder } from '@0xproject/types';

View File

@@ -1,32 +0,0 @@
import * as WebSocket from 'websocket';
import { OrderbookChannel, OrderbookChannelHandler } from './types';
import { assert } from './utils/assert';
import { WebSocketOrderbookChannel } from './ws_orderbook_channel';
export const orderbookChannelFactory = {
/**
* Instantiates a new WebSocketOrderbookChannel instance
* @param url The relayer API base WS url you would like to interact with
* @param handler An OrderbookChannelHandler instance that responds to various
* channel updates
* @return An OrderbookChannel Promise
*/
async createWebSocketOrderbookChannelAsync(
url: string,
handler: OrderbookChannelHandler,
): Promise<OrderbookChannel> {
assert.isUri('url', url);
assert.isOrderbookChannelHandler('handler', handler);
return new Promise<OrderbookChannel>((resolve, reject) => {
const client = new WebSocket.w3cwebsocket(url);
client.onopen = () => {
const orderbookChannel = new WebSocketOrderbookChannel(client, handler);
resolve(orderbookChannel);
};
client.onerror = err => {
reject(err);
};
});
},
};

View File

@@ -3,6 +3,7 @@ import { orderBookRequestSchema } from './orderbook_request_schema';
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
import { tokenPairsRequestOptsSchema } from './token_pairs_request_opts_schema';
import { webSocketOrderbookChannelConfigSchema } from './websocket_orderbook_channel_config_schema';
export const schemas = {
feesRequestSchema,
@@ -10,4 +11,5 @@ export const schemas = {
ordersRequestOptsSchema,
pagedRequestOptsSchema,
tokenPairsRequestOptsSchema,
webSocketOrderbookChannelConfigSchema,
};

View File

@@ -0,0 +1,10 @@
export const webSocketOrderbookChannelConfigSchema = {
id: '/WebSocketOrderbookChannelConfig',
type: 'object',
properties: {
heartbeatIntervalMs: {
type: 'number',
minimum: 10,
},
},
};

View File

@@ -1,4 +1,4 @@
import { SignedOrder } from '@0xproject/types';
import { ECSignature, Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
export interface Client {
@@ -11,10 +11,17 @@ export interface Client {
}
export interface OrderbookChannel {
subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler) => void;
close: () => void;
}
/**
* heartbeatIntervalMs: Interval in milliseconds that the orderbook channel should ping the underlying websocket. Default: 15000
*/
export interface WebSocketOrderbookChannelConfig {
heartbeatIntervalMs?: number;
}
/**
* baseTokenAddress: The address of token designated as the baseToken in the currency pair calculation of price
* quoteTokenAddress: The address of token designated as the quoteToken in the currency pair calculation of price
@@ -39,8 +46,8 @@ export interface OrderbookChannelHandler {
subscriptionOpts: OrderbookChannelSubscriptionOpts,
order: SignedOrder,
) => void;
onError: (channel: OrderbookChannel, err: Error, subscriptionOpts?: OrderbookChannelSubscriptionOpts) => void;
onClose: (channel: OrderbookChannel) => void;
onError: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts, err: Error) => void;
onClose: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
}
export type OrderbookChannelMessage =

View File

@@ -1,26 +0,0 @@
import { assert as sharedAssert } from '@0xproject/assert';
// HACK: 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, schemas } from '@0xproject/json-schemas';
// tslint:disable-next-line:no-unused-variable
import { ECSignature } from '@0xproject/types';
// tslint:disable-next-line:no-unused-variable
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
export const assert = {
...sharedAssert,
isOrderbookChannelSubscriptionOpts(variableName: string, subscriptionOpts: any): void {
sharedAssert.doesConformToSchema(
variableName,
subscriptionOpts,
schemas.relayerApiOrderbookChannelSubscribePayload,
);
},
isOrderbookChannelHandler(variableName: string, handler: any): void {
sharedAssert.isFunction(`${variableName}.onSnapshot`, _.get(handler, 'onSnapshot'));
sharedAssert.isFunction(`${variableName}.onUpdate`, _.get(handler, 'onUpdate'));
sharedAssert.isFunction(`${variableName}.onError`, _.get(handler, 'onError'));
sharedAssert.isFunction(`${variableName}.onClose`, _.get(handler, 'onClose'));
},
};

View File

@@ -8,16 +8,10 @@ import { relayerResponseJsonParsers } from './relayer_response_json_parsers';
export const orderbookChannelMessageParser = {
parse(utf8Data: string): OrderbookChannelMessage {
// parse the message
const messageObj = JSON.parse(utf8Data);
// ensure we have a type parameter to switch on
const type: string = _.get(messageObj, 'type');
assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`);
assert.isString('type', type);
// ensure we have a request id for the resulting message
const requestId: number = _.get(messageObj, 'requestId');
assert.assert(!_.isUndefined(requestId), `Message is missing a requestId parameter: ${utf8Data}`);
assert.isNumber('requestId', requestId);
switch (type) {
case OrderbookChannelMessageTypes.Snapshot: {
assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelSnapshotSchema);
@@ -34,7 +28,7 @@ export const orderbookChannelMessageParser = {
default: {
return {
type: OrderbookChannelMessageTypes.Unknown,
requestId,
requestId: 0,
payload: undefined,
};
}

View File

@@ -1,6 +1,7 @@
import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types';
import * as _ from 'lodash';
import { FeesResponse, OrderbookResponse, TokenPairsItem } from '../types';

View File

@@ -6,12 +6,12 @@ export const typeConverters = {
const bids = _.get(orderbook, 'bids', []);
const asks = _.get(orderbook, 'asks', []);
return {
bids: bids.map((order: any) => typeConverters.convertOrderStringFieldsToBigNumber(order)),
asks: asks.map((order: any) => typeConverters.convertOrderStringFieldsToBigNumber(order)),
bids: bids.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)),
asks: asks.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)),
};
},
convertOrderStringFieldsToBigNumber(order: any): any {
return typeConverters.convertStringsFieldsToBigNumbers(order, [
return this.convertStringsFieldsToBigNumbers(order, [
'makerTokenAmount',
'takerTokenAmount',
'makerFee',

View File

@@ -1,105 +1,166 @@
import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import * as _ from 'lodash';
import * as WebSocket from 'websocket';
import { schemas as clientSchemas } from './schemas/schemas';
import {
OrderbookChannel,
OrderbookChannelHandler,
OrderbookChannelMessageTypes,
OrderbookChannelSubscriptionOpts,
WebsocketClientEventType,
WebsocketConnectionEventType,
WebSocketOrderbookChannelConfig,
} from './types';
import { assert } from './utils/assert';
import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser';
const DEFAULT_HEARTBEAT_INTERVAL_MS = 15000;
const MINIMUM_HEARTBEAT_INTERVAL_MS = 10;
/**
* This class includes all the functionality related to interacting with a websocket endpoint
* that implements the standard relayer API v0
*/
export class WebSocketOrderbookChannel implements OrderbookChannel {
private readonly _client: WebSocket.w3cwebsocket;
private readonly _handler: OrderbookChannelHandler;
private readonly _subscriptionOptsList: OrderbookChannelSubscriptionOpts[] = [];
private _apiEndpointUrl: string;
private _client: WebSocket.client;
private _connectionIfExists?: WebSocket.connection;
private _heartbeatTimerIfExists?: NodeJS.Timer;
private _subscriptionCounter = 0;
private _heartbeatIntervalMs: number;
/**
* Instantiates a new WebSocketOrderbookChannel instance
* @param client A WebSocket client
* @param handler An OrderbookChannelHandler instance that responds to various
* channel updates
* @param url The relayer API base WS url you would like to interact with
* @param config The configuration object. Look up the type for the description.
* @return An instance of WebSocketOrderbookChannel
*/
constructor(client: WebSocket.w3cwebsocket, handler: OrderbookChannelHandler) {
assert.isOrderbookChannelHandler('handler', handler);
// set private members
this._client = client;
this._handler = handler;
// attach client callbacks
this._client.onerror = err => {
this._handler.onError(this, err);
};
this._client.onclose = () => {
this._handler.onClose(this);
};
this._client.onmessage = message => {
this._handleWebSocketMessage(message);
};
constructor(url: string, config?: WebSocketOrderbookChannelConfig) {
assert.isUri('url', url);
if (!_.isUndefined(config)) {
assert.doesConformToSchema('config', config, clientSchemas.webSocketOrderbookChannelConfigSchema);
}
this._apiEndpointUrl = url;
this._heartbeatIntervalMs =
_.isUndefined(config) || _.isUndefined(config.heartbeatIntervalMs)
? DEFAULT_HEARTBEAT_INTERVAL_MS
: config.heartbeatIntervalMs;
this._client = new WebSocket.client();
}
/**
* Subscribe to orderbook snapshots and updates from the websocket
* @param subscriptionOpts An OrderbookChannelSubscriptionOpts instance describing which
* token pair to subscribe to
* @param handler An OrderbookChannelHandler instance that responds to various
* channel updates
*/
public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts): void {
assert.isOrderbookChannelSubscriptionOpts('subscriptionOpts', subscriptionOpts);
assert.assert(this._client.readyState === WebSocket.w3cwebsocket.OPEN, 'WebSocket connection is closed');
this._subscriptionOptsList.push(subscriptionOpts);
// TODO: update requestId management to use UUIDs for v2
public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler): void {
assert.doesConformToSchema(
'subscriptionOpts',
subscriptionOpts,
schemas.relayerApiOrderbookChannelSubscribePayload,
);
assert.isFunction('handler.onSnapshot', _.get(handler, 'onSnapshot'));
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._subscriptionOptsList.length - 1,
requestId: this._subscriptionCounter,
payload: subscriptionOpts,
};
this._client.send(JSON.stringify(subscribeMessage));
this._getConnection((error, connection) => {
if (!_.isUndefined(error)) {
handler.onError(this, subscriptionOpts, error);
} else if (!_.isUndefined(connection) && connection.connected) {
connection.on(WebsocketConnectionEventType.Error, wsError => {
handler.onError(this, subscriptionOpts, wsError);
});
connection.on(WebsocketConnectionEventType.Close, (code: number, desc: string) => {
handler.onClose(this, subscriptionOpts);
});
connection.on(WebsocketConnectionEventType.Message, message => {
this._handleWebSocketMessage(subscribeMessage.requestId, subscriptionOpts, message, handler);
});
connection.sendUTF(JSON.stringify(subscribeMessage));
}
});
}
/**
* Close the websocket and stop receiving updates
*/
public close(): void {
this._client.close();
}
private _handleWebSocketMessage(message: any): void {
if (_.isUndefined(message.data)) {
this._handler.onError(this, new Error(`Message does not contain data. Url: ${this._client.url}`));
return;
if (!_.isUndefined(this._connectionIfExists)) {
this._connectionIfExists.close();
}
try {
const data = message.data;
const parserResult = orderbookChannelMessageParser.parse(data);
const subscriptionOpts = this._subscriptionOptsList[parserResult.requestId];
if (_.isUndefined(subscriptionOpts)) {
this._handler.onError(
this,
new Error(`Message has unknown requestId. Url: ${this._client.url} Message: ${data}`),
);
return;
}
switch (parserResult.type) {
case OrderbookChannelMessageTypes.Snapshot: {
this._handler.onSnapshot(this, subscriptionOpts, parserResult.payload);
break;
}
case OrderbookChannelMessageTypes.Update: {
this._handler.onUpdate(this, subscriptionOpts, parserResult.payload);
break;
}
default: {
this._handler.onError(
this,
new Error(`Message has unknown type parameter. Url: ${this._client.url} Message: ${data}`),
subscriptionOpts,
if (!_.isUndefined(this._heartbeatTimerIfExists)) {
clearInterval(this._heartbeatTimerIfExists);
}
}
private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void): void {
if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) {
callback(undefined, this._connectionIfExists);
} else {
this._client.on(WebsocketClientEventType.Connect, connection => {
this._connectionIfExists = connection;
if (this._heartbeatIntervalMs >= MINIMUM_HEARTBEAT_INTERVAL_MS) {
this._heartbeatTimerIfExists = setInterval(() => {
connection.ping('');
}, this._heartbeatIntervalMs);
} else {
callback(
new Error(
`Heartbeat interval is ${
this._heartbeatIntervalMs
}ms which is less than the required minimum of ${MINIMUM_HEARTBEAT_INTERVAL_MS}ms`,
),
undefined,
);
}
callback(undefined, this._connectionIfExists);
});
this._client.on(WebsocketClientEventType.ConnectFailed, error => {
callback(error, undefined);
});
this._client.connect(this._apiEndpointUrl);
}
}
private _handleWebSocketMessage(
requestId: number,
subscriptionOpts: OrderbookChannelSubscriptionOpts,
message: WebSocket.IMessage,
handler: OrderbookChannelHandler,
): void {
if (!_.isUndefined(message.utf8Data)) {
try {
const utf8Data = message.utf8Data;
const parserResult = orderbookChannelMessageParser.parse(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, subscriptionOpts, error);
}
} catch (error) {
this._handler.onError(this, error);
} else {
handler.onError(this, subscriptionOpts, new Error(`Message does not contain utf8Data`));
}
}
}

View File

@@ -3,6 +3,7 @@ import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
import * as dirtyChai from 'dirty-chai';
import * as fetchMock from 'fetch-mock';
import 'make-promises-safe';
import 'mocha';
import { HttpClient } from '../src/index';

View File

@@ -1,45 +0,0 @@
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import * as _ from 'lodash';
import 'mocha';
import { orderbookChannelFactory } from '../src/orderbook_channel_factory';
chai.config.includeStack = true;
chai.use(dirtyChai);
const expect = chai.expect;
const emptyOrderbookChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => {
_.noop();
},
onError: () => {
_.noop();
},
onClose: () => {
_.noop();
},
};
describe('orderbookChannelFactory', () => {
const websocketUrl = 'ws://localhost:8080';
describe('#createWebSocketOrderbookChannelAsync', () => {
it('throws when input is not a url', () => {
const badUrlInput = 54;
expect(
orderbookChannelFactory.createWebSocketOrderbookChannelAsync(
badUrlInput as any,
emptyOrderbookChannelHandler,
),
).to.be.rejected();
});
it('throws when handler has the incorrect members', () => {
const badHandlerInput = {};
expect(
orderbookChannelFactory.createWebSocketOrderbookChannelAsync(websocketUrl, badHandlerInput as any),
).to.be.rejected();
});
});
});

View File

@@ -1,5 +1,6 @@
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import 'make-promises-safe';
import 'mocha';
import { orderbookChannelMessageParser } from '../src/utils/orderbook_channel_message_parser';

View File

@@ -1,59 +1,62 @@
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import * as _ from 'lodash';
import 'make-promises-safe';
import 'mocha';
import * as Sinon from 'sinon';
import * as WebSocket from 'websocket';
import { WebSocketOrderbookChannel } from '../src/ws_orderbook_channel';
chai.config.includeStack = true;
chai.use(dirtyChai);
const expect = chai.expect;
const emptyOrderbookChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => {
_.noop();
},
onError: () => {
_.noop();
},
onClose: () => {
_.noop();
},
};
describe('WebSocketOrderbookChannel', () => {
const websocketUrl = 'ws://localhost:8080';
const openClient = new WebSocket.w3cwebsocket(websocketUrl);
Sinon.stub(openClient, 'readyState').get(() => WebSocket.w3cwebsocket.OPEN);
Sinon.stub(openClient, 'send').callsFake(_.noop.bind(_));
const openOrderbookChannel = new WebSocketOrderbookChannel(openClient, emptyOrderbookChannelHandler);
const orderbookChannel = new WebSocketOrderbookChannel(websocketUrl);
const subscriptionOpts = {
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
snapshot: true,
limit: 100,
};
const emptyOrderbookChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => {
_.noop();
},
onError: () => {
_.noop();
},
onClose: () => {
_.noop();
},
};
describe('#subscribe', () => {
it('throws when subscriptionOpts does not conform to schema', () => {
const badSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, {});
const badSubscribeCall = orderbookChannel.subscribe.bind(
orderbookChannel,
{},
emptyOrderbookChannelHandler,
);
expect(badSubscribeCall).throws(
'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseTokenAddress", instance requires property "quoteTokenAddress"',
);
});
it('does not throw when inputs are of correct types', () => {
const goodSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, subscriptionOpts);
expect(goodSubscribeCall).to.not.throw();
it('throws when handler has the incorrect members', () => {
const badSubscribeCall = orderbookChannel.subscribe.bind(orderbookChannel, subscriptionOpts, {});
expect(badSubscribeCall).throws(
'Expected handler.onSnapshot to be of type function, encountered: undefined',
);
});
it('throws when client is closed', () => {
const closedClient = new WebSocket.w3cwebsocket(websocketUrl);
Sinon.stub(closedClient, 'readyState').get(() => WebSocket.w3cwebsocket.CLOSED);
const closedOrderbookChannel = new WebSocketOrderbookChannel(closedClient, emptyOrderbookChannelHandler);
const badSubscribeCall = closedOrderbookChannel.subscribe.bind(closedOrderbookChannel, subscriptionOpts);
expect(badSubscribeCall).throws('WebSocket connection is closed');
it('does not throw when inputs are of correct types', () => {
const goodSubscribeCall = orderbookChannel.subscribe.bind(
orderbookChannel,
subscriptionOpts,
emptyOrderbookChannelHandler,
);
expect(goodSubscribeCall).to.not.throw();
});
});
});

View File

@@ -1,45 +1,4 @@
[
{
"version": "1.0.1-rc.2",
"changes": [
{
"note": "Fixed bug caused by importing non-existent dep"
}
],
"timestamp": 1532614997
},
{
"version": "1.0.1-rc.1",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1532605697
},
{
"timestamp": 1532357734,
"version": "1.0.0",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1532043000,
"version": "1.0.0-rc.1",
"changes": [
{
"note": "Update blockstream to v5.0 and propogate up caught errors to active subscriptions",
"pr": 815
},
{
"note": "Update to v2 of 0x rpotocol",
"pr": 822
}
]
},
{
"timestamp": 1531919263,
"version": "0.1.1",
@@ -49,6 +8,16 @@
}
]
},
{
"version": "0.1.0",
"changes": [
{
"note":
"Update Blockstream dep. to V5.0 and no longer force unsubscribe on blockstream error (which are not recoverable)"
}
],
"timestamp": 1531149657
},
{
"timestamp": 1529397769,
"version": "0.0.5",
@@ -63,7 +32,16 @@
"version": "0.0.4",
"changes": [
{
"note": "Expose 'abi' ContractAbi property on all contract wrappers"
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527616612,
"version": "0.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},

View File

@@ -1,38 +1,29 @@
<!--
changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly.
This file is auto-generated using the monorepo-scripts package. Don't edit directly.
Edit the package's CHANGELOG.json file only.
-->
CHANGELOG
## v1.0.1-rc.2 - _July 26, 2018_
* Fixed bug caused by importing non-existent dep
## v1.0.1-rc.1 - _July 26, 2018_
* Dependencies updated
## v1.0.0 - _July 23, 2018_
* Dependencies updated
## v1.0.0-rc.1 - _July 20, 2018_
* Update blockstream to v5.0 and propogate up caught errors to active subscriptions (#815)
* Update to v2 of 0x rpotocol (#822)
## v0.1.1 - _July 18, 2018_
* Dependencies updated
## v0.1.0 - _July 9, 2018_
* Update Blockstream dep. to V5.0 and no longer force unsubscribe on blockstream error (which are not recoverable)
## v0.0.5 - _June 19, 2018_
* Dependencies updated
## v0.0.4 - _May 29, 2018_
* Expose 'abi' ContractAbi property on all contract wrappers
* Dependencies updated
## v0.0.3 - _May 29, 2018_
* Dependencies updated
## v0.0.2 - _May 22, 2018_

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/contract-wrappers",
"version": "1.0.1-rc.1",
"version": "0.1.1",
"description": "Smart TS wrappers for 0x smart contracts",
"keywords": [
"0xproject",
@@ -11,26 +11,23 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"pre_build": "run-s update_artifacts_v2_beta update_artifacts_v2 generate_contract_wrappers copy_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers",
"lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*",
"watch": "tsc -w",
"prebuild": "run-s clean generate_contract_wrappers",
"generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
"lint": "tslint --project .",
"test:circleci": "run-s test:coverage",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test": "run-s clean build run_mocha",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"update_artifacts_v2_beta": "for i in ${npm_package_config_contracts_v2_beta}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-beta-testnet/$i.json src/artifacts; done;",
"update_artifacts_v2": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json src/artifacts; done;",
"copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts",
"clean": "shx rm -rf _bundles lib test_temp scripts test/artifacts src/contract_wrappers/generated src/artifacts",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/1.0.0/$i.json test/artifacts; done;",
"clean": "shx rm -rf _bundles lib test_temp scripts test/artifacts src/contract_wrappers/generated",
"build": "tsc && yarn update_artifacts && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"config": {
"contracts_v2_beta": "Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken",
"contracts_v2": "DummyERC20Token DummyERC721Token"
"compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry",
"contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels"
},
"repository": {
"type": "git",
@@ -41,53 +38,53 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@0xproject/abi-gen": "^1.0.2",
"@0xproject/dev-utils": "^1.0.2",
"@0xproject/migrations": "^1.0.2",
"@0xproject/monorepo-scripts": "^1.0.3",
"@0xproject/sol-compiler": "^1.0.2",
"@0xproject/subproviders": "^1.0.2",
"@0xproject/tslint-config": "^1.0.3",
"@0xproject/abi-gen": "^0.3.4",
"@0xproject/dev-utils": "^0.4.6",
"@0xproject/migrations": "^0.0.10",
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/subproviders": "^0.10.6",
"@0xproject/tslint-config": "^0.4.21",
"@types/lodash": "4.14.104",
"@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-bignumber": "^2.0.1",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"opn-cli": "^3.1.0",
"shx": "^0.2.2",
"sinon": "^4.0.0",
"source-map-support": "^0.5.0",
"tslint": "5.11.0",
"@types/mocha": "2.2.48",
"@types/node": "9.6.0",
"@types/sinon": "2.3.7",
"@types/uuid": "3.4.3",
"awesome-typescript-loader": "3.5.0",
"chai": "4.1.2",
"chai-as-promised": "7.1.1",
"chai-bignumber": "2.0.1",
"copyfiles": "1.2.0",
"dirty-chai": "2.0.1",
"make-promises-safe": "1.1.0",
"mocha": "4.1.0",
"npm-run-all": "4.1.2",
"nyc": "11.6.0",
"opn-cli": "3.1.0",
"prettier": "1.12.1",
"shx": "0.2.2",
"sinon": "4.4.9",
"source-map-support": "0.5.4",
"tslint": "5.8.0",
"typescript": "2.7.1",
"web3-provider-engine": "14.0.6"
"web3-provider-engine": "13.8.0"
},
"dependencies": {
"@0xproject/assert": "^1.0.2",
"@0xproject/base-contract": "^1.0.2",
"@0xproject/fill-scenarios": "^1.0.1-rc.1",
"@0xproject/json-schemas": "^1.0.1-rc.1",
"@0xproject/order-utils": "^1.0.1-rc.1",
"@0xproject/types": "^1.0.1-rc.1",
"@0xproject/typescript-typings": "^1.0.2",
"@0xproject/utils": "^1.0.2",
"@0xproject/web3-wrapper": "^1.1.0",
"ethereum-types": "^1.0.2",
"@0xproject/assert": "^0.2.14",
"@0xproject/base-contract": "^0.3.6",
"@0xproject/fill-scenarios": "^0.0.6",
"@0xproject/json-schemas": "^0.8.3",
"@0xproject/order-utils": "^0.0.9",
"@0xproject/sol-compiler": "^0.5.4",
"@0xproject/types": "^0.8.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"@0xproject/web3-wrapper": "^0.7.3",
"ethereumjs-blockstream": "5.0.0",
"ethereumjs-util": "^5.1.1",
"ethereumjs-util": "5.1.5",
"ethers": "3.0.22",
"js-sha3": "^0.7.0",
"lodash": "^4.17.4",
"uuid": "^3.1.0"
"js-sha3": "0.7.0",
"lodash": "4.17.10",
"uuid": "3.2.1"
},
"publishConfig": {
"access": "public"

View File

@@ -1,11 +0,0 @@
import { BigNumber } from '@0xproject/utils';
export abstract class AbstractBalanceAndProxyAllowanceLazyStore {
public abstract async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>;
public abstract async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>;
public abstract setBalance(tokenAddress: string, userAddress: string, balance: BigNumber): void;
public abstract deleteBalance(tokenAddress: string, userAddress: string): void;
public abstract setProxyAllowance(tokenAddress: string, userAddress: string, proxyAllowance: BigNumber): void;
public abstract deleteProxyAllowance(tokenAddress: string, userAddress: string): void;
public abstract deleteAll(): void;
}

View File

@@ -1,23 +1,18 @@
import { ContractArtifact } from '@0xproject/sol-compiler';
import * as DummyERC20Token from './artifacts/DummyERC20Token.json';
import * as DummyERC721Token from './artifacts/DummyERC721Token.json';
import * as ERC20Proxy from './artifacts/ERC20Proxy.json';
import * as ERC20Token from './artifacts/ERC20Token.json';
import * as ERC721Proxy from './artifacts/ERC721Proxy.json';
import * as ERC721Token from './artifacts/ERC721Token.json';
import * as Exchange from './artifacts/Exchange.json';
import * as EtherToken from './artifacts/WETH9.json';
import * as ZRXToken from './artifacts/ZRXToken.json';
import { Artifact } from '@0xproject/types';
import * as DummyToken from './compact_artifacts/DummyToken.json';
import * as EtherToken from './compact_artifacts/EtherToken.json';
import * as Exchange from './compact_artifacts/Exchange.json';
import * as Token from './compact_artifacts/Token.json';
import * as TokenRegistry from './compact_artifacts/TokenRegistry.json';
import * as TokenTransferProxy from './compact_artifacts/TokenTransferProxy.json';
import * as ZRX from './compact_artifacts/ZRX.json';
export const artifacts = {
ZRXToken: (ZRXToken as any) as ContractArtifact,
DummyERC20Token: (DummyERC20Token as any) as ContractArtifact,
DummyERC721Token: (DummyERC721Token as any) as ContractArtifact,
ERC20Token: (ERC20Token as any) as ContractArtifact,
ERC721Token: (ERC721Token as any) as ContractArtifact,
Exchange: (Exchange as any) as ContractArtifact,
EtherToken: (EtherToken as any) as ContractArtifact,
ERC20Proxy: (ERC20Proxy as any) as ContractArtifact,
ERC721Proxy: (ERC721Proxy as any) as ContractArtifact,
ZRX: (ZRX as any) as Artifact,
DummyToken: (DummyToken as any) as Artifact,
Token: (Token as any) as Artifact,
Exchange: (Exchange as any) as Artifact,
EtherToken: (EtherToken as any) as Artifact,
TokenRegistry: (TokenRegistry as any) as Artifact,
TokenTransferProxy: (TokenTransferProxy as any) as Artifact,
};

View File

@@ -0,0 +1,22 @@
{
"contract_name": "DummyToken",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "_target",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "setBalance",
"outputs": [],
"payable": false,
"type": "function"
}
]
}

View File

@@ -0,0 +1,287 @@
{
"contract_name": "EtherToken",
"abi": [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "amount",
"type": "uint256"
}
],
"name": "withdraw",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "deposit",
"outputs": [],
"payable": true,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"payable": true,
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_spender",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Deposit",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Withdrawal",
"type": "event"
}
],
"networks": {
"1": {
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
},
"3": {
"address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
},
"4": {
"address": "0xc778417e063141139fce010982780140aa0cd5ab"
},
"42": {
"address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
},
"50": {
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
}
}
}

View File

@@ -0,0 +1,610 @@
{
"contract_name": "Exchange",
"abi": [
{
"constant": true,
"inputs": [
{
"name": "numerator",
"type": "uint256"
},
{
"name": "denominator",
"type": "uint256"
},
{
"name": "target",
"type": "uint256"
}
],
"name": "isRoundingError",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "bytes32"
}
],
"name": "filled",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "bytes32"
}
],
"name": "cancelled",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "fillOrdersUpTo",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "cancelTakerTokenAmount",
"type": "uint256"
}
],
"name": "cancelOrder",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "ZRX_TOKEN_CONTRACT",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmounts",
"type": "uint256[]"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "batchFillOrKillOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "fillOrKillOrder",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "orderHash",
"type": "bytes32"
}
],
"name": "getUnavailableTakerTokenAmount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "signer",
"type": "address"
},
{
"name": "hash",
"type": "bytes32"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "isValidSignature",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "numerator",
"type": "uint256"
},
{
"name": "denominator",
"type": "uint256"
},
{
"name": "target",
"type": "uint256"
}
],
"name": "getPartialAmount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "TOKEN_TRANSFER_PROXY_CONTRACT",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmounts",
"type": "uint256[]"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "batchFillOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "cancelTakerTokenAmounts",
"type": "uint256[]"
}
],
"name": "batchCancelOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "fillOrder",
"outputs": [
{
"name": "filledTakerTokenAmount",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
}
],
"name": "getOrderHash",
"outputs": [
{
"name": "",
"type": "bytes32"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "EXTERNAL_QUERY_GAS_LIMIT",
"outputs": [
{
"name": "",
"type": "uint16"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "VERSION",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"inputs": [
{
"name": "_zrxToken",
"type": "address"
},
{
"name": "_tokenTransferProxy",
"type": "address"
}
],
"payable": false,
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "maker",
"type": "address"
},
{
"indexed": false,
"name": "taker",
"type": "address"
},
{
"indexed": true,
"name": "feeRecipient",
"type": "address"
},
{
"indexed": false,
"name": "makerToken",
"type": "address"
},
{
"indexed": false,
"name": "takerToken",
"type": "address"
},
{
"indexed": false,
"name": "filledMakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "filledTakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "paidMakerFee",
"type": "uint256"
},
{
"indexed": false,
"name": "paidTakerFee",
"type": "uint256"
},
{
"indexed": true,
"name": "tokens",
"type": "bytes32"
},
{
"indexed": false,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogFill",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "maker",
"type": "address"
},
{
"indexed": true,
"name": "feeRecipient",
"type": "address"
},
{
"indexed": false,
"name": "makerToken",
"type": "address"
},
{
"indexed": false,
"name": "takerToken",
"type": "address"
},
{
"indexed": false,
"name": "cancelledMakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "cancelledTakerTokenAmount",
"type": "uint256"
},
{
"indexed": true,
"name": "tokens",
"type": "bytes32"
},
{
"indexed": false,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogCancel",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "errorId",
"type": "uint8"
},
{
"indexed": true,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogError",
"type": "event"
}
],
"networks": {
"1": {
"address": "0x12459c951127e0c374ff9105dda097662a027093"
},
"3": {
"address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac"
},
"4": {
"address": "0x1d16ef40fac01cec8adac2ac49427b9384192c05"
},
"42": {
"address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
},
"50": {
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
}
}
}

View File

@@ -0,0 +1,172 @@
{
"contract_name": "Token",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "supply",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "success",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "remaining",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_spender",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
}
]
}

View File

@@ -0,0 +1,547 @@
{
"contract_name": "TokenRegistry",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_index",
"type": "uint256"
}
],
"name": "removeToken",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_name",
"type": "string"
}
],
"name": "getTokenAddressByName",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_symbol",
"type": "string"
}
],
"name": "getTokenAddressBySymbol",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_swarmHash",
"type": "bytes"
}
],
"name": "setTokenSwarmHash",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_token",
"type": "address"
}
],
"name": "getTokenMetaData",
"outputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "uint8"
},
{
"name": "",
"type": "bytes"
},
{
"name": "",
"type": "bytes"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_name",
"type": "string"
},
{
"name": "_symbol",
"type": "string"
},
{
"name": "_decimals",
"type": "uint8"
},
{
"name": "_ipfsHash",
"type": "bytes"
},
{
"name": "_swarmHash",
"type": "bytes"
}
],
"name": "addToken",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_name",
"type": "string"
}
],
"name": "setTokenName",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "tokens",
"outputs": [
{
"name": "token",
"type": "address"
},
{
"name": "name",
"type": "string"
},
{
"name": "symbol",
"type": "string"
},
{
"name": "decimals",
"type": "uint8"
},
{
"name": "ipfsHash",
"type": "bytes"
},
{
"name": "swarmHash",
"type": "bytes"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "tokenAddresses",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_name",
"type": "string"
}
],
"name": "getTokenByName",
"outputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "uint8"
},
{
"name": "",
"type": "bytes"
},
{
"name": "",
"type": "bytes"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getTokenAddresses",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_ipfsHash",
"type": "bytes"
}
],
"name": "setTokenIpfsHash",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_symbol",
"type": "string"
}
],
"name": "getTokenBySymbol",
"outputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "string"
},
{
"name": "",
"type": "uint8"
},
{
"name": "",
"type": "bytes"
},
{
"name": "",
"type": "bytes"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_token",
"type": "address"
},
{
"name": "_symbol",
"type": "string"
}
],
"name": "setTokenSymbol",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "name",
"type": "string"
},
{
"indexed": false,
"name": "symbol",
"type": "string"
},
{
"indexed": false,
"name": "decimals",
"type": "uint8"
},
{
"indexed": false,
"name": "ipfsHash",
"type": "bytes"
},
{
"indexed": false,
"name": "swarmHash",
"type": "bytes"
}
],
"name": "LogAddToken",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "name",
"type": "string"
},
{
"indexed": false,
"name": "symbol",
"type": "string"
},
{
"indexed": false,
"name": "decimals",
"type": "uint8"
},
{
"indexed": false,
"name": "ipfsHash",
"type": "bytes"
},
{
"indexed": false,
"name": "swarmHash",
"type": "bytes"
}
],
"name": "LogRemoveToken",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "oldName",
"type": "string"
},
{
"indexed": false,
"name": "newName",
"type": "string"
}
],
"name": "LogTokenNameChange",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "oldSymbol",
"type": "string"
},
{
"indexed": false,
"name": "newSymbol",
"type": "string"
}
],
"name": "LogTokenSymbolChange",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "oldIpfsHash",
"type": "bytes"
},
{
"indexed": false,
"name": "newIpfsHash",
"type": "bytes"
}
],
"name": "LogTokenIpfsHashChange",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "token",
"type": "address"
},
{
"indexed": false,
"name": "oldSwarmHash",
"type": "bytes"
},
{
"indexed": false,
"name": "newSwarmHash",
"type": "bytes"
}
],
"name": "LogTokenSwarmHashChange",
"type": "event"
}
],
"networks": {
"1": {
"address": "0x926a74c5c36adf004c87399e65f75628b0f98d2c"
},
"3": {
"address": "0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed"
},
"4": {
"address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
},
"42": {
"address": "0xf18e504561f4347bea557f3d4558f559dddbae7f"
},
"50": {
"address": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082"
}
}
}

View File

@@ -0,0 +1,187 @@
{
"contract_name": "TokenTransferProxy",
"abi": [
{
"constant": false,
"inputs": [
{
"name": "token",
"type": "address"
},
{
"name": "from",
"type": "address"
},
{
"name": "to",
"type": "address"
},
{
"name": "value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
}
],
"name": "addAuthorizedAddress",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "authorities",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
}
],
"name": "removeAuthorizedAddress",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "authorized",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getAuthorizedAddresses",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "target",
"type": "address"
},
{
"indexed": true,
"name": "caller",
"type": "address"
}
],
"name": "LogAuthorizedAddressAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "target",
"type": "address"
},
{
"indexed": true,
"name": "caller",
"type": "address"
}
],
"name": "LogAuthorizedAddressRemoved",
"type": "event"
}
],
"networks": {
"1": {
"address": "0x8da0d80f5007ef1e431dd2127178d224e32c2ef4"
},
"3": {
"address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6"
},
"4": {
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
},
"42": {
"address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4"
},
"50": {
"address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48"
}
}
}

View File

@@ -0,0 +1,20 @@
{
"contract_name": "ZRX",
"networks": {
"1": {
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
},
"3": {
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
},
"4": {
"address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8"
},
"42": {
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
},
"50": {
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
}
}
}

View File

@@ -1,16 +1,13 @@
import { Provider } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
import { constants } from './utils/constants';
import { artifacts } from './artifacts';
import { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
import { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
import { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
import { TokenRegistryWrapper } from './contract_wrappers/token_registry_wrapper';
import { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper';
import { TokenWrapper } from './contract_wrappers/token_wrapper';
import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema';
import { contractWrappersPrivateNetworkConfigSchema } from './schemas/contract_wrappers_private_network_config_schema';
import { contractWrappersPublicNetworkConfigSchema } from './schemas/contract_wrappers_public_network_config_schema';
@@ -25,28 +22,24 @@ export class ContractWrappers {
*/
public exchange: ExchangeWrapper;
/**
* An instance of the ERC20TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
* An instance of the TokenRegistryWrapper class containing methods for interacting with the 0x
* TokenRegistry smart contract.
*/
public erc20Token: ERC20TokenWrapper;
public tokenRegistry: TokenRegistryWrapper;
/**
* An instance of the ERC721TokenWrapper class containing methods for interacting with any ERC721 token smart contract.
* An instance of the TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
*/
public erc721Token: ERC721TokenWrapper;
public token: TokenWrapper;
/**
* An instance of the EtherTokenWrapper class containing methods for interacting with the
* wrapped ETH ERC20 token smart contract.
*/
public etherToken: EtherTokenWrapper;
/**
* An instance of the ERC20ProxyWrapper class containing methods for interacting with the
* erc20Proxy smart contract.
* An instance of the TokenTransferProxyWrapper class containing methods for interacting with the
* tokenTransferProxy smart contract.
*/
public erc20Proxy: ERC20ProxyWrapper;
/**
* An instance of the ERC721ProxyWrapper class containing methods for interacting with the
* erc721Proxy smart contract.
*/
public erc721Proxy: ERC721ProxyWrapper;
public proxy: TokenTransferProxyWrapper;
private _web3Wrapper: Web3Wrapper;
/**
* Instantiates a new ContractWrappers instance.
@@ -62,7 +55,7 @@ export class ContractWrappers {
contractWrappersPublicNetworkConfigSchema,
]);
const artifactJSONs = _.values(artifacts);
const abiArrays = _.map(artifactJSONs, artifact => artifact.compilerOutput.abi);
const abiArrays = _.map(artifactJSONs, artifact => artifact.abi);
const txDefaults = {
gasPrice: config.gasPrice,
};
@@ -70,40 +63,25 @@ export class ContractWrappers {
_.forEach(abiArrays, abi => {
this._web3Wrapper.abiDecoder.addABI(abi);
});
const blockPollingIntervalMs = _.isUndefined(config.blockPollingIntervalMs)
? constants.DEFAULT_BLOCK_POLLING_INTERVAL
: config.blockPollingIntervalMs;
this.erc20Proxy = new ERC20ProxyWrapper(this._web3Wrapper, config.networkId, config.erc20ProxyContractAddress);
this.erc721Proxy = new ERC721ProxyWrapper(
this.proxy = new TokenTransferProxyWrapper(
this._web3Wrapper,
config.networkId,
config.erc721ProxyContractAddress,
);
this.erc20Token = new ERC20TokenWrapper(
this._web3Wrapper,
config.networkId,
this.erc20Proxy,
blockPollingIntervalMs,
);
this.erc721Token = new ERC721TokenWrapper(
this._web3Wrapper,
config.networkId,
this.erc721Proxy,
blockPollingIntervalMs,
);
this.etherToken = new EtherTokenWrapper(
this._web3Wrapper,
config.networkId,
this.erc20Token,
blockPollingIntervalMs,
config.tokenTransferProxyContractAddress,
);
this.token = new TokenWrapper(this._web3Wrapper, config.networkId, this.proxy);
this.exchange = new ExchangeWrapper(
this._web3Wrapper,
config.networkId,
this.token,
config.exchangeContractAddress,
config.zrxContractAddress,
blockPollingIntervalMs,
);
this.tokenRegistry = new TokenRegistryWrapper(
this._web3Wrapper,
config.networkId,
config.tokenRegistryContractAddress,
);
this.etherToken = new EtherTokenWrapper(this._web3Wrapper, config.networkId, this.token);
}
/**
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
@@ -115,10 +93,12 @@ export class ContractWrappers {
this._web3Wrapper.setProvider(provider);
(this.exchange as any)._invalidateContractInstances();
(this.exchange as any)._setNetworkId(networkId);
(this.erc20Token as any)._invalidateContractInstances();
(this.erc20Token as any)._setNetworkId(networkId);
(this.erc20Proxy as any)._invalidateContractInstance();
(this.erc20Proxy as any)._setNetworkId(networkId);
(this.tokenRegistry as any)._invalidateContractInstance();
(this.tokenRegistry as any)._setNetworkId(networkId);
(this.token as any)._invalidateContractInstances();
(this.token as any)._setNetworkId(networkId);
(this.proxy as any)._invalidateContractInstance();
(this.proxy as any)._setNetworkId(networkId);
(this.etherToken as any)._invalidateContractInstance();
(this.etherToken as any)._setNetworkId(networkId);
}

View File

@@ -1,7 +1,14 @@
import { ContractArtifact } from '@0xproject/sol-compiler';
import { AbiDecoder, intervalUtils, logUtils } from '@0xproject/utils';
import {
Artifact,
BlockParamLiteral,
ContractAbi,
FilterObject,
LogEntry,
LogWithDecodedArgs,
RawLog,
} from '@0xproject/types';
import { intervalUtils, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from 'ethereum-types';
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
import * as _ from 'lodash';
@@ -12,6 +19,7 @@ import {
ContractWrappersError,
EventCallback,
IndexedFilterValues,
InternalContractWrappersError,
} from '../types';
import { constants } from '../utils/constants';
import { filterUtils } from '../utils/filter_utils';
@@ -21,19 +29,16 @@ const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {
} = {
ZRX: ContractWrappersError.ZRXContractDoesNotExist,
EtherToken: ContractWrappersError.EtherTokenContractDoesNotExist,
ERC20Token: ContractWrappersError.ERC20TokenContractDoesNotExist,
ERC20Proxy: ContractWrappersError.ERC20ProxyContractDoesNotExist,
ERC721Token: ContractWrappersError.ERC721TokenContractDoesNotExist,
ERC721Proxy: ContractWrappersError.ERC721ProxyContractDoesNotExist,
Token: ContractWrappersError.TokenContractDoesNotExist,
TokenRegistry: ContractWrappersError.TokenRegistryContractDoesNotExist,
TokenTransferProxy: ContractWrappersError.TokenTransferProxyContractDoesNotExist,
Exchange: ContractWrappersError.ExchangeContractDoesNotExist,
};
export abstract class ContractWrapper {
public abstract abi: ContractAbi;
export class ContractWrapper {
protected _web3Wrapper: Web3Wrapper;
protected _networkId: number;
private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined;
private _blockPollingIntervalMs: number;
private _blockAndLogStreamerIfExists?: BlockAndLogStreamer<Block, Log> | undefined;
private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer;
private _filters: { [filterToken: string]: FilterObject };
private _filterCallbacks: {
@@ -41,19 +46,16 @@ export abstract class ContractWrapper {
};
private _onLogAddedSubscriptionToken: string | undefined;
private _onLogRemovedSubscriptionToken: string | undefined;
private static _onBlockAndLogStreamerError(isVerbose: boolean, err: Error): void {
// Since Blockstream errors are all recoverable, we simply log them if the verbose
// config is passed in.
private static _onBlockstreamError(isVerbose: boolean, err: Error): void {
// Noop on blockstream errors since they are automatically
// recovered from and don't cause Blockstream to exit.
if (isVerbose) {
logUtils.warn(err);
logUtils.warn(err.message);
}
}
constructor(web3Wrapper: Web3Wrapper, networkId: number, blockPollingIntervalMs?: number) {
constructor(web3Wrapper: Web3Wrapper, networkId: number) {
this._web3Wrapper = web3Wrapper;
this._networkId = networkId;
this._blockPollingIntervalMs = _.isUndefined(blockPollingIntervalMs)
? constants.DEFAULT_BLOCK_POLLING_INTERVAL
: blockPollingIntervalMs;
this._filters = {};
this._filterCallbacks = {};
this._blockAndLogStreamerIfExists = undefined;
@@ -112,12 +114,14 @@ export abstract class ContractWrapper {
protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
log: LogEntry,
): LogWithDecodedArgs<ArgsType> | RawLog {
const abiDecoder = new AbiDecoder([this.abi]);
const logWithDecodedArgs = abiDecoder.tryToDecodeLogOrNoop(log);
if (_.isUndefined(this._web3Wrapper.abiDecoder)) {
throw new Error(InternalContractWrappersError.NoAbiDecoder);
}
const logWithDecodedArgs = this._web3Wrapper.abiDecoder.tryToDecodeLogOrNoop(log);
return logWithDecodedArgs;
}
protected async _getContractAbiAndAddressFromArtifactsAsync(
artifact: ContractArtifact,
artifact: Artifact,
addressIfExists?: string,
): Promise<[ContractAbi, string]> {
let contractAddress: string;
@@ -131,12 +135,12 @@ export abstract class ContractWrapper {
}
const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(contractAddress);
if (!doesContractExist) {
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contractName]);
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
}
const abiAndAddress: [ContractAbi, string] = [artifact.compilerOutput.abi, contractAddress];
const abiAndAddress: [ContractAbi, string] = [artifact.abi, contractAddress];
return abiAndAddress;
}
protected _getContractAddress(artifact: ContractArtifact, addressIfExists?: string): string {
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
if (_.isUndefined(addressIfExists)) {
const contractAddress = artifact.networks[this._networkId].address;
if (_.isUndefined(contractAddress)) {
@@ -166,14 +170,14 @@ export abstract class ContractWrapper {
this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose),
ContractWrapper._onBlockstreamError.bind(this, isVerbose),
);
const catchAllLogFilter = {};
this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval(
this._reconcileBlockAsync.bind(this),
this._blockPollingIntervalMs,
ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose),
constants.DEFAULT_BLOCK_POLLING_INTERVAL,
ContractWrapper._onBlockstreamError.bind(this, isVerbose),
);
let isRemoved = false;
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
@@ -184,11 +188,6 @@ export abstract class ContractWrapper {
this._onLogStateChanged.bind(this, isRemoved),
);
}
// HACK: This should be a package-scoped method (which doesn't exist in TS)
// We don't want this method available in the public interface for all classes
// who inherit from ContractWrapper, and it is only used by the internal implementation
// of those higher classes.
// tslint:disable-next-line:no-unused-variable
private _setNetworkId(networkId: number): void {
this._networkId = networkId;
}

View File

@@ -1,85 +0,0 @@
import { AssetProxyId } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { assert } from '../utils/assert';
import { ContractWrapper } from './contract_wrapper';
import { ERC20ProxyContract } from './generated/erc20_proxy';
/**
* This class includes the functionality related to interacting with the ERC20Proxy contract.
*/
export class ERC20ProxyWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.ERC20Proxy.compilerOutput.abi;
private _erc20ProxyContractIfExists?: ERC20ProxyContract;
private _contractAddressIfExists?: string;
constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
super(web3Wrapper, networkId);
this._contractAddressIfExists = contractAddressIfExists;
}
/**
* Get the 4 bytes ID of this asset proxy
* @return Proxy id
*/
public async getProxyIdAsync(): Promise<AssetProxyId> {
const ERC20ProxyContractInstance = await this._getERC20ProxyContractAsync();
const proxyId = (await ERC20ProxyContractInstance.getProxyId.callAsync()) as AssetProxyId;
return proxyId;
}
/**
* Check if the Exchange contract address is authorized by the ERC20Proxy contract.
* @param exchangeContractAddress The hex encoded address of the Exchange contract to call.
* @return Whether the exchangeContractAddress is authorized.
*/
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
const ERC20ProxyContractInstance = await this._getERC20ProxyContractAsync();
const isAuthorized = await ERC20ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress);
return isAuthorized;
}
/**
* Get the list of all Exchange contract addresses authorized by the ERC20Proxy contract.
* @return The list of authorized addresses.
*/
public async getAuthorizedAddressesAsync(): Promise<string[]> {
const ERC20ProxyContractInstance = await this._getERC20ProxyContractAsync();
const authorizedAddresses = await ERC20ProxyContractInstance.getAuthorizedAddresses.callAsync();
return authorizedAddresses;
}
/**
* Retrieves the Ethereum address of the ERC20Proxy contract deployed on the network
* that the user-passed web3 provider is connected to.
* @returns The Ethereum address of the ERC20Proxy contract being used.
*/
public getContractAddress(): string {
const contractAddress = this._getContractAddress(artifacts.ERC20Proxy, this._contractAddressIfExists);
return contractAddress;
}
// HACK: We don't want this method to be visible to the other units within that package but not to the end user.
// TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused.
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstance(): void {
delete this._erc20ProxyContractIfExists;
}
private async _getERC20ProxyContractAsync(): Promise<ERC20ProxyContract> {
if (!_.isUndefined(this._erc20ProxyContractIfExists)) {
return this._erc20ProxyContractIfExists;
}
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
artifacts.ERC20Proxy,
this._contractAddressIfExists,
);
const contractInstance = new ERC20ProxyContract(
abi,
address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._erc20ProxyContractIfExists = contractInstance;
return this._erc20ProxyContractIfExists;
}
}

View File

@@ -1,85 +0,0 @@
import { AssetProxyId } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { assert } from '../utils/assert';
import { ContractWrapper } from './contract_wrapper';
import { ERC721ProxyContract } from './generated/erc721_proxy';
/**
* This class includes the functionality related to interacting with the ERC721Proxy contract.
*/
export class ERC721ProxyWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.ERC20Proxy.compilerOutput.abi;
private _erc721ProxyContractIfExists?: ERC721ProxyContract;
private _contractAddressIfExists?: string;
constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
super(web3Wrapper, networkId);
this._contractAddressIfExists = contractAddressIfExists;
}
/**
* Get the 4 bytes ID of this asset proxy
* @return Proxy id
*/
public async getProxyIdAsync(): Promise<AssetProxyId> {
const ERC721ProxyContractInstance = await this._getERC721ProxyContractAsync();
const proxyId = (await ERC721ProxyContractInstance.getProxyId.callAsync()) as AssetProxyId;
return proxyId;
}
/**
* Check if the Exchange contract address is authorized by the ERC721Proxy contract.
* @param exchangeContractAddress The hex encoded address of the Exchange contract to call.
* @return Whether the exchangeContractAddress is authorized.
*/
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
const ERC721ProxyContractInstance = await this._getERC721ProxyContractAsync();
const isAuthorized = await ERC721ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress);
return isAuthorized;
}
/**
* Get the list of all Exchange contract addresses authorized by the ERC721Proxy contract.
* @return The list of authorized addresses.
*/
public async getAuthorizedAddressesAsync(): Promise<string[]> {
const ERC721ProxyContractInstance = await this._getERC721ProxyContractAsync();
const authorizedAddresses = await ERC721ProxyContractInstance.getAuthorizedAddresses.callAsync();
return authorizedAddresses;
}
/**
* Retrieves the Ethereum address of the ERC721Proxy contract deployed on the network
* that the user-passed web3 provider is connected to.
* @returns The Ethereum address of the ERC721Proxy contract being used.
*/
public getContractAddress(): string {
const contractAddress = this._getContractAddress(artifacts.ERC721Proxy, this._contractAddressIfExists);
return contractAddress;
}
// HACK: We don't want this method to be visible to the other units within that package but not to the end user.
// TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused.
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstance(): void {
delete this._erc721ProxyContractIfExists;
}
private async _getERC721ProxyContractAsync(): Promise<ERC721ProxyContract> {
if (!_.isUndefined(this._erc721ProxyContractIfExists)) {
return this._erc721ProxyContractIfExists;
}
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
artifacts.ERC721Proxy,
this._contractAddressIfExists,
);
const contractInstance = new ERC721ProxyContract(
abi,
address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._erc721ProxyContractIfExists = contractInstance;
return this._erc721ProxyContractIfExists;
}
}

View File

@@ -1,472 +0,0 @@
import { schemas } from '@0xproject/json-schemas';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { methodOptsSchema } from '../schemas/method_opts_schema';
import { txOptsSchema } from '../schemas/tx_opts_schema';
import {
BlockRange,
ContractWrappersError,
EventCallback,
IndexedFilterValues,
MethodOpts,
TransactionOpts,
} from '../types';
import { assert } from '../utils/assert';
import { constants } from '../utils/constants';
import { ContractWrapper } from './contract_wrapper';
import { ERC721ProxyWrapper } from './erc721_proxy_wrapper';
import { ERC721TokenContract, ERC721TokenEventArgs, ERC721TokenEvents } from './generated/erc721_token';
const removeUndefinedProperties = _.pickBy;
/**
* This class includes all the functionality related to interacting with ERC721 token contracts.
* All ERC721 method calls are supported, along with some convenience methods for getting/setting allowances
* to the 0x ERC721 Proxy smart contract.
*/
export class ERC721TokenWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.ERC721Token.compilerOutput.abi;
private _tokenContractsByAddress: { [address: string]: ERC721TokenContract };
private _erc721ProxyWrapper: ERC721ProxyWrapper;
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
erc721ProxyWrapper: ERC721ProxyWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
this._tokenContractsByAddress = {};
this._erc721ProxyWrapper = erc721ProxyWrapper;
}
/**
* Count all NFTs assigned to an owner
* NFTs assigned to the zero address are considered invalid, and this function throws for queries about the zero address.
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param ownerAddress The hex encoded user Ethereum address whose balance you would like to check.
* @param methodOpts Optional arguments this method accepts.
* @return The number of NFTs owned by `ownerAddress`, possibly zero
*/
public async getTokenCountAsync(
tokenAddress: string,
ownerAddress: string,
methodOpts: MethodOpts = {},
): Promise<BigNumber> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const txData = {};
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, methodOpts.defaultBlock);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
balance = new BigNumber(balance);
return balance;
}
/**
* Find the owner of an NFT
* NFTs assigned to zero address are considered invalid, and queries about them do throw.
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param tokenId The identifier for an NFT
* @param methodOpts Optional arguments this method accepts.
* @return The address of the owner of the NFT
*/
public async getOwnerOfAsync(
tokenAddress: string,
tokenId: BigNumber,
methodOpts: MethodOpts = {},
): Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isBigNumber('tokenId', tokenId);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const txData = {};
try {
const tokenOwner = await tokenContract.ownerOf.callAsync(tokenId, txData, methodOpts.defaultBlock);
return tokenOwner;
} catch (err) {
throw new Error(ContractWrappersError.ERC721OwnerNotFound);
}
}
/**
* Query if an address is an authorized operator for all NFT's of `ownerAddress`
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param ownerAddress The hex encoded user Ethereum address of the token owner.
* @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to check if approved.
* @param methodOpts Optional arguments this method accepts.
* @return True if `operatorAddress` is an approved operator for `ownerAddress`, false otherwise
*/
public async isApprovedForAllAsync(
tokenAddress: string,
ownerAddress: string,
operatorAddress: string,
methodOpts: MethodOpts = {},
): Promise<boolean> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('operatorAddress', operatorAddress);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const normalizedOperatorAddress = operatorAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const txData = {};
const isApprovedForAll = await tokenContract.isApprovedForAll.callAsync(
normalizedOwnerAddress,
normalizedOperatorAddress,
txData,
methodOpts.defaultBlock,
);
return isApprovedForAll;
}
/**
* Query if 0x proxy is an authorized operator for all NFT's of `ownerAddress`
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param ownerAddress The hex encoded user Ethereum address of the token owner.
* @param methodOpts Optional arguments this method accepts.
* @return True if `operatorAddress` is an approved operator for `ownerAddress`, false otherwise
*/
public async isProxyApprovedForAllAsync(
tokenAddress: string,
ownerAddress: string,
methodOpts: MethodOpts = {},
): Promise<boolean> {
const proxyAddress = this._erc721ProxyWrapper.getContractAddress();
const isProxyApprovedForAll = await this.isApprovedForAllAsync(
tokenAddress,
ownerAddress,
proxyAddress,
methodOpts,
);
return isProxyApprovedForAll;
}
/**
* Get the approved address for a single NFT. Returns undefined if no approval was set
* Throws if `_tokenId` is not a valid NFT
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param tokenId The identifier for an NFT
* @param methodOpts Optional arguments this method accepts.
* @return The approved address for this NFT, or the undefined if there is none
*/
public async getApprovedIfExistsAsync(
tokenAddress: string,
tokenId: BigNumber,
methodOpts: MethodOpts = {},
): Promise<string | undefined> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isBigNumber('tokenId', tokenId);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const txData = {};
const approvedAddress = await tokenContract.getApproved.callAsync(tokenId, txData, methodOpts.defaultBlock);
if (approvedAddress === constants.NULL_ADDRESS) {
return undefined;
}
return approvedAddress;
}
/**
* Checks if 0x proxy is approved for a single NFT
* Throws if `_tokenId` is not a valid NFT
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param tokenId The identifier for an NFT
* @param methodOpts Optional arguments this method accepts.
* @return True if 0x proxy is approved
*/
public async isProxyApprovedAsync(
tokenAddress: string,
tokenId: BigNumber,
methodOpts: MethodOpts = {},
): Promise<boolean> {
const proxyAddress = this._erc721ProxyWrapper.getContractAddress();
const approvedAddress = await this.getApprovedIfExistsAsync(tokenAddress, tokenId, methodOpts);
const isProxyApproved = approvedAddress === proxyAddress;
return isProxyApproved;
}
/**
* Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets.
* Throws if `_tokenId` is not a valid NFT
* Emits the ApprovalForAll event.
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param ownerAddress The hex encoded user Ethereum address of the token owner.
* @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to set approval for.
* @param isApproved The boolean variable to set the approval to.
* @param txOpts Transaction parameters.
* @return Transaction hash.
*/
public async setApprovalForAllAsync(
tokenAddress: string,
ownerAddress: string,
operatorAddress: string,
isApproved: boolean,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
assert.isETHAddressHex('operatorAddress', operatorAddress);
assert.isBoolean('isApproved', isApproved);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const normalizedOperatorAddress = operatorAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const txHash = await tokenContract.setApprovalForAll.sendTransactionAsync(
normalizedOperatorAddress,
isApproved,
removeUndefinedProperties({
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
from: normalizedOwnerAddress,
}),
);
return txHash;
}
/**
* Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets.
* Throws if `_tokenId` is not a valid NFT
* Emits the ApprovalForAll event.
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param ownerAddress The hex encoded user Ethereum address of the token owner.
* @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to set approval for.
* @param isApproved The boolean variable to set the approval to.
* @param txOpts Transaction parameters.
* @return Transaction hash.
*/
public async setProxyApprovalForAllAsync(
tokenAddress: string,
ownerAddress: string,
isApproved: boolean,
txOpts: TransactionOpts = {},
): Promise<string> {
const proxyAddress = this._erc721ProxyWrapper.getContractAddress();
const txHash = await this.setApprovalForAllAsync(tokenAddress, ownerAddress, proxyAddress, isApproved, txOpts);
return txHash;
}
/**
* Set or reaffirm the approved address for an NFT
* The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner,
* or an authorized operator of the current owner.
* Throws if `_tokenId` is not a valid NFT
* Emits the Approval event.
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param approvedAddress The hex encoded user Ethereum address you'd like to set approval for.
* @param tokenId The identifier for an NFT
* @param txOpts Transaction parameters.
* @return Transaction hash.
*/
public async setApprovalAsync(
tokenAddress: string,
approvedAddress: string,
tokenId: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('approvedAddress', approvedAddress);
assert.isBigNumber('tokenId', tokenId);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedApprovedAddress = approvedAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const tokenOwnerAddress = await tokenContract.ownerOf.callAsync(tokenId);
await assert.isSenderAddressAsync('tokenOwnerAddress', tokenOwnerAddress, this._web3Wrapper);
const txHash = await tokenContract.approve.sendTransactionAsync(
normalizedApprovedAddress,
tokenId,
removeUndefinedProperties({
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
from: tokenOwnerAddress,
}),
);
return txHash;
}
/**
* Set or reaffirm 0x proxy as an approved address for an NFT
* Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner.
* Throws if `_tokenId` is not a valid NFT
* Emits the Approval event.
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param tokenId The identifier for an NFT
* @param txOpts Transaction parameters.
* @return Transaction hash.
*/
public async setProxyApprovalAsync(
tokenAddress: string,
tokenId: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
const proxyAddress = this._erc721ProxyWrapper.getContractAddress();
const txHash = await this.setApprovalAsync(tokenAddress, proxyAddress, tokenId, txOpts);
return txHash;
}
/**
* Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets.
* Throws if `_tokenId` is not a valid NFT
* Emits the ApprovalForAll event.
* @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed.
* @param receiverAddress The hex encoded Ethereum address of the user to send the NFT to.
* @param senderAddress The hex encoded Ethereum address of the user to send the NFT to.
* @param tokenId The identifier for an NFT
* @param txOpts Transaction parameters.
* @return Transaction hash.
*/
public async transferFromAsync(
tokenAddress: string,
receiverAddress: string,
senderAddress: string,
tokenId: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('receiverAddress', receiverAddress);
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedReceiverAddress = receiverAddress.toLowerCase();
const normalizedSenderAddress = senderAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const ownerAddress = await this.getOwnerOfAsync(tokenAddress, tokenId);
if (normalizedSenderAddress !== ownerAddress) {
const isApprovedForAll = await this.isApprovedForAllAsync(
normalizedTokenAddress,
ownerAddress,
normalizedSenderAddress,
);
if (!isApprovedForAll) {
const approvedAddress = await this.getApprovedIfExistsAsync(normalizedTokenAddress, tokenId);
if (approvedAddress !== normalizedSenderAddress) {
throw new Error(ContractWrappersError.ERC721NoApproval);
}
}
}
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
ownerAddress,
normalizedReceiverAddress,
tokenId,
removeUndefinedProperties({
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
from: normalizedSenderAddress,
}),
);
return txHash;
}
/**
* Subscribe to an event type emitted by the Token contract.
* @param tokenAddress The hex encoded address where the ERC721 token is deployed.
* @param eventName The 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 `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC721TokenEventArgs>(
tokenAddress: string,
eventName: ERC721TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const subscriptionToken = this._subscribe<ArgsType>(
normalizedTokenAddress,
eventName,
indexFilterValues,
artifacts.ERC721Token.compilerOutput.abi,
callback,
isVerbose,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
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 emitted the logs.
* @param eventName The 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 `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends ERC721TokenEventArgs>(
tokenAddress: string,
eventName: ERC721TokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const logs = await this._getLogsAsync<ArgsType>(
normalizedTokenAddress,
eventName,
blockRange,
indexFilterValues,
artifacts.ERC721Token.compilerOutput.abi,
);
return logs;
}
// HACK: We don't want this method to be visible to the other units within that package but not to the end user.
// TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused.
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstances(): void {
this.unsubscribeAll();
this._tokenContractsByAddress = {};
}
private async _getTokenContractAsync(tokenAddress: string): Promise<ERC721TokenContract> {
const normalizedTokenAddress = tokenAddress.toLowerCase();
let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress];
if (!_.isUndefined(tokenContract)) {
return tokenContract;
}
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
artifacts.ERC721Token,
normalizedTokenAddress,
);
const contractInstance = new ERC721TokenContract(
abi,
address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
tokenContract = contractInstance;
this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract;
return tokenContract;
}
}

View File

@@ -1,7 +1,7 @@
import { schemas } from '@0xproject/json-schemas';
import { BigNumber } from '@0xproject/utils';
import { LogWithDecodedArgs } from '@0xproject/types';
import { AbiDecoder, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
@@ -9,29 +9,21 @@ import { BlockRange, ContractWrappersError, EventCallback, IndexedFilterValues,
import { assert } from '../utils/assert';
import { ContractWrapper } from './contract_wrapper';
import { ERC20TokenWrapper } from './erc20_token_wrapper';
import { WETH9Contract, WETH9EventArgs, WETH9Events } from './generated/weth9';
const removeUndefinedProperties = _.pickBy;
import { EtherTokenContract, EtherTokenContractEventArgs, EtherTokenEvents } from './generated/ether_token';
import { TokenWrapper } from './token_wrapper';
/**
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
*/
export class EtherTokenWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.EtherToken.compilerOutput.abi;
private _etherTokenContractsByAddress: {
[address: string]: WETH9Contract;
[address: string]: EtherTokenContract;
} = {};
private _erc20TokenWrapper: ERC20TokenWrapper;
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
erc20TokenWrapper: ERC20TokenWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
this._erc20TokenWrapper = erc20TokenWrapper;
private _tokenWrapper: TokenWrapper;
constructor(web3Wrapper: Web3Wrapper, networkId: number, tokenWrapper: TokenWrapper) {
super(web3Wrapper, networkId);
this._tokenWrapper = tokenWrapper;
}
/**
* Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens
@@ -59,14 +51,12 @@ export class EtherTokenWrapper extends ContractWrapper {
assert.assert(ethBalanceInWei.gte(amountInWei), ContractWrappersError.InsufficientEthBalanceForDeposit);
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
const txHash = await wethContract.deposit.sendTransactionAsync(
removeUndefinedProperties({
from: normalizedDepositorAddress,
value: amountInWei,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
);
const txHash = await wethContract.deposit.sendTransactionAsync({
from: normalizedDepositorAddress,
value: amountInWei,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
});
return txHash;
}
/**
@@ -90,7 +80,7 @@ export class EtherTokenWrapper extends ContractWrapper {
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
const normalizedWithdrawerAddress = withdrawer.toLowerCase();
const WETHBalanceInBaseUnits = await this._erc20TokenWrapper.getBalanceAsync(
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(
normalizedEtherTokenAddress,
normalizedWithdrawerAddress,
);
@@ -100,14 +90,11 @@ export class EtherTokenWrapper extends ContractWrapper {
);
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
const txHash = await wethContract.withdraw.sendTransactionAsync(
amountInWei,
removeUndefinedProperties({
from: normalizedWithdrawerAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
);
const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
from: normalizedWithdrawerAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
});
return txHash;
}
/**
@@ -119,15 +106,15 @@ export class EtherTokenWrapper extends ContractWrapper {
* the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends WETH9EventArgs>(
public async getLogsAsync<ArgsType extends EtherTokenContractEventArgs>(
etherTokenAddress: string,
eventName: WETH9Events,
eventName: EtherTokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._getLogsAsync<ArgsType>(
@@ -135,7 +122,7 @@ export class EtherTokenWrapper extends ContractWrapper {
eventName,
blockRange,
indexFilterValues,
artifacts.EtherToken.compilerOutput.abi,
artifacts.EtherToken.abi,
);
return logs;
}
@@ -149,23 +136,23 @@ export class EtherTokenWrapper extends ContractWrapper {
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends WETH9EventArgs>(
public subscribe<ArgsType extends EtherTokenContractEventArgs>(
etherTokenAddress: string,
eventName: WETH9Events,
eventName: EtherTokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscribe<ArgsType>(
normalizedEtherTokenAddress,
eventName,
indexFilterValues,
artifacts.EtherToken.compilerOutput.abi,
artifacts.EtherToken.abi,
callback,
isVerbose,
);
@@ -176,7 +163,6 @@ export class EtherTokenWrapper extends ContractWrapper {
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken);
}
/**
@@ -198,12 +184,11 @@ export class EtherTokenWrapper extends ContractWrapper {
: networkSpecificArtifact.address;
return contractAddressIfExists;
}
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstance(): void {
this.unsubscribeAll();
this._etherTokenContractsByAddress = {};
}
private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<WETH9Contract> {
private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<EtherTokenContract> {
let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress];
if (!_.isUndefined(etherTokenContract)) {
return etherTokenContract;
@@ -212,7 +197,7 @@ export class EtherTokenWrapper extends ContractWrapper {
artifacts.EtherToken,
etherTokenAddress,
);
const contractInstance = new WETH9Contract(
const contractInstance = new EtherTokenContract(
abi,
address,
this._web3Wrapper.getProvider(),

View File

@@ -0,0 +1,131 @@
import { Token } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { TokenMetadata } from '../types';
import { assert } from '../utils/assert';
import { constants } from '../utils/constants';
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.
*/
export class TokenRegistryWrapper extends ContractWrapper {
private _tokenRegistryContractIfExists?: TokenRegistryContract;
private _contractAddressIfExists?: string;
private static _createTokenFromMetadata(metadata: TokenMetadata): Token | undefined {
if (metadata[0] === constants.NULL_ADDRESS) {
return undefined;
}
const token = {
address: metadata[0],
name: metadata[1],
symbol: metadata[2],
decimals: metadata[3],
};
return token;
}
constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
super(web3Wrapper, networkId);
this._contractAddressIfExists = contractAddressIfExists;
}
/**
* Retrieves all the tokens currently listed in the Token Registry smart contract
* @return An array of objects that conform to the Token interface.
*/
public async getTokensAsync(): Promise<Token[]> {
const addresses = await this.getTokenAddressesAsync();
const tokenPromises: Array<Promise<Token | undefined>> = _.map(addresses, async (address: string) =>
this.getTokenIfExistsAsync(address),
);
const tokens = await Promise.all(tokenPromises);
return tokens as Token[];
}
/**
* Retrieves all the addresses of the tokens currently listed in the Token Registry smart contract
* @return An array of token addresses.
*/
public async getTokenAddressesAsync(): Promise<string[]> {
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const addresses = await tokenRegistryContract.getTokenAddresses.callAsync();
const lowerCaseAddresses = _.map(addresses, address => address.toLowerCase());
return lowerCaseAddresses;
}
/**
* Retrieves a token by address currently listed in the Token Registry smart contract
* @return An object that conforms to the Token interface or undefined if token not found.
*/
public async getTokenIfExistsAsync(address: string): Promise<Token | undefined> {
assert.isETHAddressHex('address', address);
const normalizedAddress = address.toLowerCase();
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(normalizedAddress);
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
return token;
}
public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string | undefined> {
assert.isString('symbol', symbol);
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const addressIfExists = await tokenRegistryContract.getTokenAddressBySymbol.callAsync(symbol);
if (addressIfExists === constants.NULL_ADDRESS) {
return undefined;
}
return addressIfExists;
}
public async getTokenAddressByNameIfExistsAsync(name: string): Promise<string | undefined> {
assert.isString('name', name);
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const addressIfExists = await tokenRegistryContract.getTokenAddressByName.callAsync(name);
if (addressIfExists === constants.NULL_ADDRESS) {
return undefined;
}
return addressIfExists;
}
public async getTokenBySymbolIfExistsAsync(symbol: string): Promise<Token | undefined> {
assert.isString('symbol', symbol);
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const metadata = await tokenRegistryContract.getTokenBySymbol.callAsync(symbol);
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
return token;
}
public async getTokenByNameIfExistsAsync(name: string): Promise<Token | undefined> {
assert.isString('name', name);
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const metadata = await tokenRegistryContract.getTokenByName.callAsync(name);
const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
return token;
}
/**
* Retrieves the Ethereum address of the TokenRegistry contract deployed on the network
* that the user-passed web3 provider is connected to.
* @returns The Ethereum address of the TokenRegistry contract being used.
*/
public getContractAddress(): string {
const contractAddress = this._getContractAddress(artifacts.TokenRegistry, this._contractAddressIfExists);
return contractAddress;
}
private _invalidateContractInstance(): void {
delete this._tokenRegistryContractIfExists;
}
private async _getTokenRegistryContractAsync(): Promise<TokenRegistryContract> {
if (!_.isUndefined(this._tokenRegistryContractIfExists)) {
return this._tokenRegistryContractIfExists;
}
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
artifacts.TokenRegistry,
this._contractAddressIfExists,
);
const contractInstance = new TokenRegistryContract(
abi,
address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._tokenRegistryContractIfExists = contractInstance;
return this._tokenRegistryContractIfExists;
}
}

View File

@@ -0,0 +1,72 @@
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { assert } from '../utils/assert';
import { ContractWrapper } from './contract_wrapper';
import { TokenTransferProxyContract } from './generated/token_transfer_proxy';
/**
* This class includes the functionality related to interacting with the TokenTransferProxy contract.
*/
export class TokenTransferProxyWrapper extends ContractWrapper {
private _tokenTransferProxyContractIfExists?: TokenTransferProxyContract;
private _contractAddressIfExists?: string;
constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
super(web3Wrapper, networkId);
this._contractAddressIfExists = contractAddressIfExists;
}
/**
* Check if the Exchange contract address is authorized by the TokenTransferProxy contract.
* @param exchangeContractAddress The hex encoded address of the Exchange contract to call.
* @return Whether the exchangeContractAddress is authorized.
*/
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
const isAuthorized = await tokenTransferProxyContractInstance.authorized.callAsync(
normalizedExchangeContractAddress,
);
return isAuthorized;
}
/**
* Get the list of all Exchange contract addresses authorized by the TokenTransferProxy contract.
* @return The list of authorized addresses.
*/
public async getAuthorizedAddressesAsync(): Promise<string[]> {
const tokenTransferProxyContractInstance = await this._getTokenTransferProxyContractAsync();
const authorizedAddresses = await tokenTransferProxyContractInstance.getAuthorizedAddresses.callAsync();
return authorizedAddresses;
}
/**
* Retrieves the Ethereum address of the TokenTransferProxy contract deployed on the network
* that the user-passed web3 provider is connected to.
* @returns The Ethereum address of the TokenTransferProxy contract being used.
*/
public getContractAddress(): string {
const contractAddress = this._getContractAddress(artifacts.TokenTransferProxy, this._contractAddressIfExists);
return contractAddress;
}
private _invalidateContractInstance(): void {
delete this._tokenTransferProxyContractIfExists;
}
private async _getTokenTransferProxyContractAsync(): Promise<TokenTransferProxyContract> {
if (!_.isUndefined(this._tokenTransferProxyContractIfExists)) {
return this._tokenTransferProxyContractIfExists;
}
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
artifacts.TokenTransferProxy,
this._contractAddressIfExists,
);
const contractInstance = new TokenTransferProxyContract(
abi,
address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._tokenTransferProxyContractIfExists = contractInstance;
return this._tokenTransferProxyContractIfExists;
}
}

View File

@@ -1,12 +1,10 @@
import { schemas } from '@0xproject/json-schemas';
import { BigNumber } from '@0xproject/utils';
import { LogWithDecodedArgs } from '@0xproject/types';
import { AbiDecoder, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { methodOptsSchema } from '../schemas/method_opts_schema';
import { txOptsSchema } from '../schemas/tx_opts_schema';
import {
BlockRange,
ContractWrappersError,
@@ -19,30 +17,22 @@ import { assert } from '../utils/assert';
import { constants } from '../utils/constants';
import { ContractWrapper } from './contract_wrapper';
import { ERC20ProxyWrapper } from './erc20_proxy_wrapper';
import { ERC20TokenContract, ERC20TokenEventArgs, ERC20TokenEvents } from './generated/erc20_token';
const removeUndefinedProperties = _.pickBy;
import { TokenContract, TokenContractEventArgs, TokenEvents } from './generated/token';
import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper';
/**
* 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
* to the 0x ERC20 Proxy smart contract.
* to the 0x Proxy smart contract.
*/
export class ERC20TokenWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.ERC20Token.compilerOutput.abi;
export class TokenWrapper extends ContractWrapper {
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
private _tokenContractsByAddress: { [address: string]: ERC20TokenContract };
private _erc20ProxyWrapper: ERC20ProxyWrapper;
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
erc20ProxyWrapper: ERC20ProxyWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
private _tokenContractsByAddress: { [address: string]: TokenContract };
private _tokenTransferProxyWrapper: TokenTransferProxyWrapper;
constructor(web3Wrapper: Web3Wrapper, networkId: number, tokenTransferProxyWrapper: TokenTransferProxyWrapper) {
super(web3Wrapper, networkId);
this._tokenContractsByAddress = {};
this._erc20ProxyWrapper = erc20ProxyWrapper;
this._tokenTransferProxyWrapper = tokenTransferProxyWrapper;
}
/**
* Retrieves an owner's ERC20 token balance.
@@ -54,18 +44,17 @@ export class ERC20TokenWrapper extends ContractWrapper {
public async getBalanceAsync(
tokenAddress: string,
ownerAddress: string,
methodOpts: MethodOpts = {},
methodOpts?: MethodOpts,
): Promise<BigNumber> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
const txData = {};
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, methodOpts.defaultBlock);
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, defaultBlock);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
balance = new BigNumber(balance);
return balance;
@@ -88,25 +77,20 @@ export class ERC20TokenWrapper extends ContractWrapper {
amountInBaseUnits: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('spenderAddress', spenderAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
assert.isETHAddressHex('spenderAddress', spenderAddress);
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const normalizedSpenderAddress = spenderAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const txHash = await tokenContract.approve.sendTransactionAsync(
normalizedSpenderAddress,
amountInBaseUnits,
removeUndefinedProperties({
from: normalizedOwnerAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
);
const txHash = await tokenContract.approve.sendTransactionAsync(normalizedSpenderAddress, amountInBaseUnits, {
from: normalizedOwnerAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
});
return txHash;
}
/**
@@ -127,10 +111,16 @@ export class ERC20TokenWrapper extends ContractWrapper {
spenderAddress: string,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('spenderAddress', spenderAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const normalizedSpenderAddress = spenderAddress.toLowerCase();
const txHash = await this.setAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
normalizedTokenAddress,
normalizedOwnerAddress,
normalizedSpenderAddress,
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
txOpts,
);
@@ -148,24 +138,23 @@ export class ERC20TokenWrapper extends ContractWrapper {
tokenAddress: string,
ownerAddress: string,
spenderAddress: string,
methodOpts: MethodOpts = {},
methodOpts?: MethodOpts,
): Promise<BigNumber> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('spenderAddress', spenderAddress);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const normalizedSpenderAddress = spenderAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
const txData = {};
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
normalizedOwnerAddress,
normalizedSpenderAddress,
txData,
methodOpts.defaultBlock,
defaultBlock,
);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
@@ -180,10 +169,20 @@ export class ERC20TokenWrapper extends ContractWrapper {
public async getProxyAllowanceAsync(
tokenAddress: string,
ownerAddress: string,
methodOpts: MethodOpts = {},
methodOpts?: MethodOpts,
): Promise<BigNumber> {
const proxyAddress = this._erc20ProxyWrapper.getContractAddress();
const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts);
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
const allowanceInBaseUnits = await this.getAllowanceAsync(
normalizedTokenAddress,
normalizedOwnerAddress,
proxyAddress,
methodOpts,
);
return allowanceInBaseUnits;
}
/**
@@ -202,10 +201,16 @@ export class ERC20TokenWrapper extends ContractWrapper {
amountInBaseUnits: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
const proxyAddress = this._erc20ProxyWrapper.getContractAddress();
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
const txHash = await this.setAllowanceAsync(
tokenAddress,
ownerAddress,
normalizedTokenAddress,
normalizedOwnerAddress,
proxyAddress,
amountInBaseUnits,
txOpts,
@@ -228,9 +233,13 @@ export class ERC20TokenWrapper extends ContractWrapper {
ownerAddress: string,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const txHash = await this.setProxyAllowanceAsync(
tokenAddress,
ownerAddress,
normalizedTokenAddress,
normalizedOwnerAddress,
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
txOpts,
);
@@ -253,13 +262,12 @@ export class ERC20TokenWrapper extends ContractWrapper {
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
assert.isETHAddressHex('toAddress', toAddress);
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedFromAddress = fromAddress.toLowerCase();
const normalizedToAddress = toAddress.toLowerCase();
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
@@ -268,15 +276,11 @@ export class ERC20TokenWrapper extends ContractWrapper {
throw new Error(ContractWrappersError.InsufficientBalanceForTransfer);
}
const txHash = await tokenContract.transfer.sendTransactionAsync(
normalizedToAddress,
amountInBaseUnits,
removeUndefinedProperties({
from: normalizedFromAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
);
const txHash = await tokenContract.transfer.sendTransactionAsync(normalizedToAddress, amountInBaseUnits, {
from: normalizedFromAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
});
return txHash;
}
/**
@@ -301,16 +305,15 @@ export class ERC20TokenWrapper extends ContractWrapper {
amountInBaseUnits: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('fromAddress', fromAddress);
assert.isETHAddressHex('toAddress', toAddress);
assert.isETHAddressHex('fromAddress', fromAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
const normalizedToAddress = toAddress.toLowerCase();
const normalizedFromAddress = fromAddress.toLowerCase();
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedSenderAddress = senderAddress.toLowerCase();
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
@@ -332,11 +335,11 @@ export class ERC20TokenWrapper extends ContractWrapper {
normalizedFromAddress,
normalizedToAddress,
amountInBaseUnits,
removeUndefinedProperties({
{
from: normalizedSenderAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
},
);
return txHash;
}
@@ -350,23 +353,23 @@ export class ERC20TokenWrapper extends ContractWrapper {
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC20TokenEventArgs>(
public subscribe<ArgsType extends TokenContractEventArgs>(
tokenAddress: string,
eventName: ERC20TokenEvents,
eventName: TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
const normalizedTokenAddress = tokenAddress.toLowerCase();
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const subscriptionToken = this._subscribe<ArgsType>(
normalizedTokenAddress,
eventName,
indexFilterValues,
artifacts.ERC20Token.compilerOutput.abi,
artifacts.Token.abi,
callback,
isVerbose,
);
@@ -377,7 +380,6 @@ export class ERC20TokenWrapper extends ContractWrapper {
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken);
}
/**
@@ -395,44 +397,41 @@ export class ERC20TokenWrapper extends ContractWrapper {
* 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 ERC20TokenEventArgs>(
public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
tokenAddress: string,
eventName: ERC20TokenEvents,
eventName: TokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
const normalizedTokenAddress = tokenAddress.toLowerCase();
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const logs = await this._getLogsAsync<ArgsType>(
normalizedTokenAddress,
eventName,
blockRange,
indexFilterValues,
artifacts.ERC20Token.compilerOutput.abi,
artifacts.Token.abi,
);
return logs;
}
// HACK: We don't want this method to be visible to the other units within that package but not to the end user.
// TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused.
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstances(): void {
this.unsubscribeAll();
this._tokenContractsByAddress = {};
}
private async _getTokenContractAsync(tokenAddress: string): Promise<ERC20TokenContract> {
private async _getTokenContractAsync(tokenAddress: string): Promise<TokenContract> {
const normalizedTokenAddress = tokenAddress.toLowerCase();
let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress];
if (!_.isUndefined(tokenContract)) {
return tokenContract;
}
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
artifacts.ERC20Token,
artifacts.Token,
normalizedTokenAddress,
);
const contractInstance = new ERC20TokenContract(
const contractInstance = new TokenContract(
abi,
address,
this._web3Wrapper.getProvider(),

View File

@@ -0,0 +1,28 @@
import { AbstractBalanceAndProxyAllowanceFetcher } from '@0xproject/order-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
export class SimpleBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher {
private _tokenWrapper: TokenWrapper;
private _defaultBlock: BlockParamLiteral;
constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
this._tokenWrapper = token;
this._defaultBlock = defaultBlock;
}
public async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const balance = this._tokenWrapper.getBalanceAsync(tokenAddress, userAddress, methodOpts);
return balance;
}
public async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const proxyAllowance = this._tokenWrapper.getProxyAllowanceAsync(tokenAddress, userAddress, methodOpts);
return proxyAllowance;
}
}

View File

@@ -0,0 +1,36 @@
import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
export class SimpleOrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher {
private _exchangeWrapper: ExchangeWrapper;
private _defaultBlock: BlockParamLiteral;
constructor(exchange: ExchangeWrapper, defaultBlock: BlockParamLiteral) {
this._exchangeWrapper = exchange;
this._defaultBlock = defaultBlock;
}
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const filledTakerAmount = this._exchangeWrapper.getFilledTakerAmountAsync(orderHash, methodOpts);
return filledTakerAmount;
}
public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const cancelledTakerAmount = this._exchangeWrapper.getCancelledTakerAmountAsync(orderHash, methodOpts);
return cancelledTakerAmount;
}
public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber> {
const unavailableTakerAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
return unavailableTakerAmount;
}
public getZRXTokenAddress(): string {
const zrxToken = this._exchangeWrapper.getZRXTokenAddress();
return zrxToken;
}
}

View File

@@ -1,10 +1,9 @@
export { ContractWrappers } from './contract_wrappers';
export { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
export { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
export { TokenWrapper } from './contract_wrappers/token_wrapper';
export { TokenRegistryWrapper } from './contract_wrappers/token_registry_wrapper';
export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
export { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper';
export {
ContractWrappersError,
@@ -13,6 +12,7 @@ export {
Token,
IndexedFilterValues,
BlockRange,
OrderCancellationRequest,
OrderFillRequest,
ContractEventArgs,
ContractWrappersConfig,
@@ -22,60 +22,47 @@ export {
LogEvent,
DecodedLogEvent,
OnOrderStateChangeCallback,
OrderStatus,
OrderInfo,
} from './types';
export {
Order,
SignedOrder,
ECSignature,
OrderStateValid,
OrderStateInvalid,
OrderState,
AssetProxyId,
} from '@0xproject/types';
export {
BlockParamLiteral,
FilterObject,
BlockParam,
ContractEventArg,
ExchangeContractErrs,
LogWithDecodedArgs,
Order,
Provider,
SignedOrder,
ECSignature,
OrderStateValid,
OrderStateInvalid,
OrderState,
TransactionReceipt,
TransactionReceiptWithDecodedLogs,
} from 'ethereum-types';
} from '@0xproject/types';
export {
WETH9Events,
WETH9WithdrawalEventArgs,
WETH9ApprovalEventArgs,
WETH9EventArgs,
WETH9DepositEventArgs,
WETH9TransferEventArgs,
} from './contract_wrappers/generated/weth9';
EtherTokenContractEventArgs,
WithdrawalContractEventArgs,
DepositContractEventArgs,
EtherTokenEvents,
} from './contract_wrappers/generated/ether_token';
export {
ERC20TokenTransferEventArgs,
ERC20TokenApprovalEventArgs,
ERC20TokenEvents,
ERC20TokenEventArgs,
} from './contract_wrappers/generated/erc20_token';
TransferContractEventArgs,
ApprovalContractEventArgs,
TokenContractEventArgs,
TokenEvents,
} from './contract_wrappers/generated/token';
export {
ERC721TokenApprovalEventArgs,
ERC721TokenApprovalForAllEventArgs,
ERC721TokenTransferEventArgs,
ERC721TokenEvents,
ERC721TokenEventArgs,
} from './contract_wrappers/generated/erc721_token';
export {
ExchangeCancelUpToEventArgs,
ExchangeAssetProxyRegisteredEventArgs,
ExchangeFillEventArgs,
ExchangeCancelEventArgs,
ExchangeEventArgs,
LogErrorContractEventArgs,
LogCancelContractEventArgs,
LogFillContractEventArgs,
ExchangeContractEventArgs,
ExchangeEvents,
} from './contract_wrappers/generated/exchange';
export { BalanceAndProxyAllowanceLazyStore } from './stores/balance_proxy_allowance_lazy_store';
export { OrderFilledCancelledLazyStore } from './stores/order_filled_cancelled_lazy_store';

View File

@@ -8,9 +8,8 @@ export const contractWrappersPrivateNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
blockPollingIntervalMs: { type: 'number' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {
@@ -30,7 +29,7 @@ export const contractWrappersPrivateNetworkConfigSchema = {
'networkId',
'zrxContractAddress',
'exchangeContractAddress',
'erc20ProxyContractAddress',
'erc721ProxyContractAddress',
'tokenRegistryContractAddress',
'tokenTransferProxyContractAddress',
],
};

View File

@@ -22,9 +22,8 @@ export const contractWrappersPublicNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
blockPollingIntervalMs: { type: 'number' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {

View File

@@ -1,7 +0,0 @@
export const methodOptsSchema = {
id: '/MethodOpts',
properties: {
defaultBlock: { $ref: '/BlockParam' },
},
type: 'object',
};

View File

@@ -1,8 +0,0 @@
export const orderTxOptsSchema = {
id: '/OrderTxOpts',
allOf: [{ $ref: '/TxOpts' }],
properties: {
shouldValidate: { type: 'boolean' },
},
type: 'object',
};

View File

@@ -1,8 +0,0 @@
export const txOptsSchema = {
id: '/TxOpts',
properties: {
gasPrice: { $ref: '/Number' },
gasLimit: { type: 'number' },
},
type: 'object',
};

Some files were not shown because too many files have changed in this diff Show More