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
971 changed files with 21155 additions and 58563 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,41 +95,19 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0xproject/0x.js
- 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
- 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:
@@ -108,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
@@ -148,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
@@ -159,19 +156,13 @@ jobs:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-0xjs-{{ .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 }}
@@ -180,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

11
.gitignore vendored
View File

@@ -83,19 +83,18 @@ packages/order-watcher/test/artifacts/
packages/contract-wrappers/test/artifacts/
# generated contract wrappers
packages/0x.js/src/generated_contract_wrappers/
packages/contracts/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,22 +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/test/artifacts
/packages/contracts/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,10 +1,24 @@
<!--- 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

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

@@ -2,7 +2,7 @@
"private": true,
"name": "0x-monorepo",
"engines": {
"node": ">=6.12"
"node" : ">=6.12"
},
"workspaces": [
"packages/*"
@@ -21,33 +21,26 @@
"install:all": "yarn install",
"wsrun": "wsrun",
"lerna:run": "lerna run",
"watch": "wsrun watch_without_deps $PKG --fast-exit -r --stages --done-criteria='complete|successfully'",
"watch": "wsrun watch $PKG --fast-exit -r --stages --done-criteria='complete|successfully'",
"build": "wsrun build $PKG --fast-exit -r --stages",
"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",
"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.",
"postinstall": "rm -rf `pwd`/packages/order-utils/node_modules/@0xproject; mkdir `pwd`/packages/order-utils/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-utils/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/assert `pwd`/packages/order-utils/node_modules/@0xproject/assert; ln -s `pwd`/packages/types `pwd`/packages/order-utils/node_modules/@0xproject/types; rm -f `pwd`/packages/contracts/node_modules/@0xproject/types; ln -s `pwd`/packages/types `pwd`/packages/contracts/node_modules/@0xproject/types; rm -rf `pwd`/packages/fill-scenarios/node_modules/@0xproject; mkdir -p `pwd`/packages/fill-scenarios/node_modules/@0xproject; ln -s `pwd`/packages/types `pwd`/packages/fill-scenarios/node_modules/@0xproject/types; ln -s `pwd`/packages/json-schemas `pwd`/packages/fill-scenarios/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/fill-scenarios/node_modules/@0xproject/order-utils; rm -rf `pwd`/packages/contract-wrappers/node_modules/@0xproject; mkdir -p `pwd`/packages/contract-wrappers/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contract-wrappers/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/assert `pwd`/packages/contract-wrappers/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/contract-wrappers/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/types `pwd`/packages/contract-wrappers/node_modules/@0xproject/types; ln -s `pwd`/packages/fill-scenarios `pwd`/packages/contract-wrappers/node_modules/@0xproject/fill-scenarios; rm -rf `pwd`/packages/assert/node_modules/@0xproject; mkdir -p `pwd`/packages/assert/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/assert/node_modules/@0xproject/json-schemas"
"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",
"lerna": "^2.5.1",
"npm-run-all": "^4.1.2",
"prettier": "^1.11.1",
"wsrun": "^2.2.0",
"source-map-support": "^0.5.6"
},
"resolutions": {
"ethers": "0xproject/ethers.js#eip-838-reasons"
"npm-run-all": "4.1.2",
"prettier": "1.12.1",
"wsrun": "^2.2.0"
}
}

View File

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

View File

@@ -1,4 +1,22 @@
[
{
"timestamp": 1531919263,
"version": "0.38.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.38.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1529397769,
"version": "0.38.4",

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.38.6 - _July 18, 2018_
* Dependencies updated
## v0.38.5 - _July 9, 2018_
* Dependencies updated
## v0.38.4 - _June 19, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "0x.js",
"version": "0.38.4",
"version": "0.38.6",
"engines": {
"node": ">=6.12"
},
@@ -15,22 +15,20 @@
"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 generate_contract_wrappers copy_artifacts",
"copy_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts",
"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/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 && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_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",
"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",
@@ -46,7 +44,6 @@
"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",
@@ -54,9 +51,9 @@
"../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/generated_contract_wrappers/ether_token.ts",
"./src/generated_contract_wrappers/token.ts",
"./src/generated_contract_wrappers/exchange.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/"
@@ -69,50 +66,49 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@0xproject/abi-gen": "^0.3.2",
"@0xproject/dev-utils": "^0.4.4",
"@0xproject/migrations": "^0.0.8",
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/sol-compiler": "^0.5.2",
"@0xproject/tslint-config": "^0.4.20",
"@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",
"@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": "^0.2.12",
"@0xproject/base-contract": "^0.3.4",
"@0xproject/contract-wrappers": "^0.0.5",
"@0xproject/order-utils": "^0.0.7",
"@0xproject/order-watcher": "^0.0.6",
"@0xproject/sol-compiler": "^0.5.2",
"@0xproject/types": "^0.8.1",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"@0xproject/web3-wrapper": "^0.7.1",
"ethereum-types": "^0.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

@@ -19,6 +19,7 @@ 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 * as _ from 'lodash';
import { constants } from './utils/constants';

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,11 +1,14 @@
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 { ApprovalContractEventArgs, LogWithDecodedArgs, TokenEvents, ZeroEx } from '../src';
import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
@@ -134,7 +137,6 @@ describe('ZeroEx library', () => {
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<ApprovalContractEventArgs>;
expect(log.event).to.be.equal(TokenEvents.Approval);
expect(log.args._owner).to.be.equal(coinbase);

View File

@@ -1,4 +1,6 @@
import { web3Factory } from '@0xproject/dev-utils';
import * as fs from 'fs';
import 'make-promises-safe';
import { ZeroEx } from '../src';
@@ -13,7 +15,7 @@ const TIMEOUT = 10000;
describe('Artifacts', () => {
describe('contracts are deployed on kovan', () => {
const kovanRpcUrl = constants.KOVAN_RPC_URL;
const provider = web3Factory.getRpcProvider({ rpcUrl: kovanRpcUrl });
const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider;
const config = {
networkId: constants.KOVAN_NETWORK_ID,
};
@@ -30,7 +32,7 @@ describe('Artifacts', () => {
});
describe('contracts are deployed on ropsten', () => {
const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
const provider = web3Factory.getRpcProvider({ rpcUrl: ropstenRpcUrl });
const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider;
const config = {
networkId: constants.ROPSTEN_NETWORK_ID,
};

View File

@@ -1,6 +1,8 @@
import { devConstants } from '@0xproject/dev-utils';
import { runV1MigrationsAsync } 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> {
@@ -9,9 +11,9 @@ before('migrate contracts', async function(): Promise<void> {
const mochaTestTimeoutMs = 20000;
this.timeout(mochaTestTimeoutMs);
const txDefaults = {
gas: devConstants.GAS_LIMIT,
gas: devConstants.GAS_ESTIMATE,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const artifactsDir = `../migrations/artifacts/1.0.0`;
await runV1MigrationsAsync(provider, artifactsDir, txDefaults);
await runMigrationsAsync(provider, artifactsDir, txDefaults);
});

View File

@@ -1,8 +1,9 @@
import { web3Factory } from '@0xproject/dev-utils';
import { devConstants, web3Factory } from '@0xproject/dev-utils';
import { Provider } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
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 };

View File

@@ -1,14 +1,19 @@
[
{
"version": "0.4.0",
"timestamp": 1531919263,
"version": "0.3.4",
"changes": [
{
"note": "Convert e_r_c to erc in generated file names",
"pr": 822
},
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.3.3",
"changes": [
{
"note": "Remove the output directory before writing to it",
"pr": 822
"note": "Dependencies updated"
}
]
},

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.3.4 - _July 18, 2018_
* Dependencies updated
## v0.3.3 - _July 9, 2018_
* Dependencies updated
## v0.3.2 - _June 19, 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,6 +1,6 @@
{
"name": "@0xproject/abi-gen",
"version": "0.3.2",
"version": "0.3.4",
"engines": {
"node": ">=6.12"
},
@@ -8,7 +8,7 @@
"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",
@@ -27,31 +27,29 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
"dependencies": {
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"ethereum-types": "^0.0.2",
"chalk": "^2.3.0",
"glob": "^7.1.2",
"handlebars": "^4.0.11",
"lodash": "^4.17.4",
"rimraf": "^2.6.2",
"mkdirp": "^0.5.1",
"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": "^0.2.1",
"@0xproject/tslint-config": "^0.4.20",
"@types/glob": "^5.0.33",
"@types/rimraf": "^2.0.2",
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",
"@types/node": "^8.0.53",
"@types/yargs": "^10.0.0",
"copyfiles": "^1.2.0",
"make-promises-safe": "^1.1.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"@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.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"
},

View File

@@ -1,19 +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 rimraf from 'rimraf';
import * as yargs from 'yargs';
import toSnakeCase = require('to-snake-case');
import { ContextData, ContractsBackend, ParamKind } from './types';
import { ContextData, ContractsBackend, Method, ParamKind } from './types';
import { utils } from './utils';
const ABI_TYPE_CONSTRUCTOR = 'constructor';
@@ -73,9 +72,9 @@ function registerPartials(partialsGlob: string): void {
function writeOutputFile(name: string, renderedTsCode: string): void {
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');
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)}`);
@@ -97,7 +96,6 @@ if (_.isEmpty(abiFileNames)) {
process.exit(1);
} else {
logUtils.log(`Found ${chalk.green(`${abiFileNames.length}`)} ${chalk.bold('ABI')} files`);
rimraf.sync(args.output);
mkdirp.sync(args.output);
}
for (const abiFileName of abiFileNames) {

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,4 +1,4 @@
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';
@@ -56,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}`);

View File

@@ -1,11 +1,19 @@
[
{
"timestamp": 1531919263,
"version": "0.2.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.2.13",
"changes": [
{
"note":
"Fix bug in string enum assertion. We erroneously were checking against the enum keys, not values",
"pr": 821
"note": "Dependencies updated"
}
]
},

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.2.14 - _July 18, 2018_
* Dependencies updated
## v0.2.13 - _July 9, 2018_
* Dependencies updated
## v0.2.12 - _June 19, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/assert",
"version": "0.3.0",
"version": "0.2.14",
"engines": {
"node": ">=6.12"
},
@@ -8,14 +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",
"run_mocha": "mocha lib/test/**/*_test.js --exit",
"prepublishOnly": "run-p build",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean 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",
"test:circleci": "yarn test:coverage",
@@ -31,28 +30,28 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
"devDependencies": {
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/tslint-config": "^0.4.20",
"@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",
"@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.0",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"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

@@ -41,8 +41,8 @@ export const assert = {
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(
@@ -64,9 +64,6 @@ export const assert = {
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));

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';

View File

@@ -1,4 +1,22 @@
[
{
"timestamp": 1531919263,
"version": "0.3.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.3.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.3.4",
"changes": [

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.3.6 - _July 18, 2018_
* Dependencies updated
## v0.3.5 - _July 9, 2018_
* Dependencies updated
## v0.3.4 - _June 19, 2018_
* Update EthersJs to fix the `value.toLowerCase()` is not a function bug caused by `ethers.js` breaking patch version https://github.com/ethers-io/ethers.js/issues/201

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/base-contract",
"version": "0.3.4",
"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",
"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": "^0.2.1",
"@0xproject/tslint-config": "^0.4.20",
"@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",
"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": {
"ethereum-types": "^0.0.2",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"@0xproject/web3-wrapper": "^0.7.1",
"@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>>(
@@ -80,7 +79,8 @@ export class BaseContract {
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
} as any;
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults as any);
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,4 +1,22 @@
[
{
"timestamp": 1531919263,
"version": "0.6.17",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.6.16",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1529397769,
"version": "0.6.15",

View File

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.6.17 - _July 18, 2018_
* Dependencies updated
## v0.6.16 - _July 9, 2018_
* Dependencies updated
## v0.6.15 - _June 19, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/connect",
"version": "0.6.15",
"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",
@@ -51,37 +50,37 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
"dependencies": {
"@0xproject/assert": "^0.2.12",
"@0xproject/json-schemas": "0.8.1",
"@0xproject/types": "^0.8.1",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.4",
"query-string": "^5.0.1",
"websocket": "^1.0.25"
"@0xproject/assert": "^0.2.14",
"@0xproject/json-schemas": "^0.8.3",
"@0xproject/types": "^0.8.2",
"@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": "^0.2.1",
"@0xproject/tslint-config": "^0.4.20",
"@types/fetch-mock": "^5.12.1",
"@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/websocket": "^0.0.34",
"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",
"@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",
"typedoc": "0.8.0",
"typescript": "2.7.1"
},
"publishConfig": {

View File

@@ -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

View File

@@ -17,4 +17,4 @@ export {
WebSocketOrderbookChannelConfig,
} from './types';
export { Order, SignedOrder } from '@0xproject/types';
export { ECSignature, Order, SignedOrder } from '@0xproject/types';

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 {
@@ -16,7 +16,7 @@ export interface OrderbookChannel {
}
/**
* heartbeatInterval: Interval in milliseconds that the orderbook channel should ping the underlying websocket. Default: 15000
* heartbeatIntervalMs: Interval in milliseconds that the orderbook channel should ping the underlying websocket. Default: 15000
*/
export interface WebSocketOrderbookChannelConfig {
heartbeatIntervalMs?: number;

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

@@ -78,7 +78,7 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
connection.on(WebsocketConnectionEventType.Error, wsError => {
handler.onError(this, subscriptionOpts, wsError);
});
connection.on(WebsocketConnectionEventType.Close, (_code: number, _desc: string) => {
connection.on(WebsocketConnectionEventType.Close, (code: number, desc: string) => {
handler.onClose(this, subscriptionOpts);
});
connection.on(WebsocketConnectionEventType.Message, message => {

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,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,6 +1,7 @@
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import * as _ from 'lodash';
import 'make-promises-safe';
import 'mocha';
import { WebSocketOrderbookChannel } from '../src/ws_orderbook_channel';

View File

@@ -1,16 +1,23 @@
[
{
"version": "1.0.0",
"timestamp": 1531919263,
"version": "0.1.1",
"changes": [
{
"note": "Update blockstream to v5.0 and propogate up caught errors to active subscriptions"
},
{
"note": "Update to v2 of 0x rpotocol",
"pr": 822
"note": "Dependencies updated"
}
]
},
{
"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",
@@ -25,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

@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## 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

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/contract-wrappers",
"version": "0.0.6",
"version": "0.1.1",
"description": "Smart TS wrappers for 0x smart contracts",
"keywords": [
"0xproject",
@@ -11,28 +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 generate_contract_wrappers update_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": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts",
"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",
"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": "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": {
"postpublish": {
"assets": [
"packages/contract-wrappers/_bundles/index.js",
"packages/contract-wrappers/_bundles/index.min.js"
]
}
"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",
@@ -43,53 +38,53 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@0xproject/abi-gen": "^0.3.2",
"@0xproject/dev-utils": "^0.4.4",
"@0xproject/migrations": "^0.0.8",
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/sol-compiler": "^0.5.2",
"@0xproject/subproviders": "^0.10.4",
"@0xproject/tslint-config": "^0.4.20",
"@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",
"@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": "^0.3.0",
"@0xproject/base-contract": "^0.3.4",
"@0xproject/order-utils": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"@0xproject/web3-wrapper": "^0.7.1",
"@0xproject/fill-scenarios": "^1.0.0",
"@0xproject/json-schemas": "^1.0.0",
"@0xproject/types": "^1.0.0",
"ethereum-types": "^0.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

@@ -1,306 +0,0 @@
{
"schemaVersion": "2.0.0",
"contractName": "DummyERC20Token",
"compilerOutput": {
"abi": [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_value",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_target",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "setBalance",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"name": "_name",
"type": "string"
},
{
"name": "_symbol",
"type": "string"
},
{
"name": "_decimals",
"type": "uint8"
},
{
"name": "_totalSupply",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"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

@@ -1,368 +0,0 @@
{
"schemaVersion": "2.0.0",
"contractName": "DummyERC721Token",
"compilerOutput": {
"abi": [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "to",
"type": "address"
},
{
"name": "tokenId",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "exists",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_tokenId",
"type": "uint256"
},
{
"name": "_data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"name": "name",
"type": "string"
},
{
"name": "symbol",
"type": "string"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_approved",
"type": "address"
},
{
"indexed": false,
"name": "_tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_operator",
"type": "address"
},
{
"indexed": false,
"name": "_approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
}
]
}
}

View File

@@ -1,210 +0,0 @@
{
"contractName": "ERC20Proxy",
"compilerOutput": {
"abi": [
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
}
],
"name": "addAuthorizedAddress",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "authorities",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
}
],
"name": "removeAuthorizedAddress",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
},
{
"name": "index",
"type": "uint256"
}
],
"name": "removeAuthorizedAddressAtIndex",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "assetData",
"type": "bytes"
},
{
"name": "from",
"type": "address"
},
{
"name": "to",
"type": "address"
},
{
"name": "amount",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getProxyId",
"outputs": [
{
"name": "",
"type": "bytes4"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "authorized",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getAuthorizedAddresses",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "target",
"type": "address"
},
{
"indexed": true,
"name": "caller",
"type": "address"
}
],
"name": "AuthorizedAddressAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "target",
"type": "address"
},
{
"indexed": true,
"name": "caller",
"type": "address"
}
],
"name": "AuthorizedAddressRemoved",
"type": "event"
}
]
},
"networks": {
"50": { "address": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48" }
}
}

View File

@@ -1,174 +0,0 @@
{
"contractName": "ERC20Token",
"compilerOutput": {
"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

@@ -1,210 +0,0 @@
{
"contractName": "ERC20Proxy",
"compilerOutput": {
"abi": [
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
}
],
"name": "addAuthorizedAddress",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "authorities",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
}
],
"name": "removeAuthorizedAddress",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "target",
"type": "address"
},
{
"name": "index",
"type": "uint256"
}
],
"name": "removeAuthorizedAddressAtIndex",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "assetData",
"type": "bytes"
},
{
"name": "from",
"type": "address"
},
{
"name": "to",
"type": "address"
},
{
"name": "amount",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getProxyId",
"outputs": [
{
"name": "",
"type": "bytes4"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "authorized",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getAuthorizedAddresses",
"outputs": [
{
"name": "",
"type": "address[]"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "target",
"type": "address"
},
{
"indexed": true,
"name": "caller",
"type": "address"
}
],
"name": "AuthorizedAddressAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "target",
"type": "address"
},
{
"indexed": true,
"name": "caller",
"type": "address"
}
],
"name": "AuthorizedAddressRemoved",
"type": "event"
}
]
},
"networks": {
"50": { "address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401" }
}
}

View File

@@ -1,322 +0,0 @@
{
"schemaVersion": "2.0.0",
"contractName": "ERC721Token",
"compilerOutput": {
"abi": [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "exists",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_approved",
"type": "bool"
}
],
"name": "setApprovalForAll",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_tokenId",
"type": "uint256"
},
{
"name": "_data",
"type": "bytes"
}
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_operator",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"name": "_name",
"type": "string"
},
{
"name": "_symbol",
"type": "string"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_approved",
"type": "address"
},
{
"indexed": false,
"name": "_tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_operator",
"type": "address"
},
{
"indexed": false,
"name": "_approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,301 +0,0 @@
{
"contractName": "WETH9",
"compilerOutput": {
"abi": [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "guy",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "src",
"type": "address"
},
{
"name": "dst",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "wad",
"type": "uint256"
}
],
"name": "withdraw",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "dst",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "deposit",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"payable": true,
"stateMutability": "payable",
"type": "fallback"
},
{
"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": "_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": 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": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082"
}
}
}

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

@@ -1,8 +1,5 @@
{
"contractName": "ZRXToken",
"compilerOutput": {
"abi": []
},
"contract_name": "ZRX",
"networks": {
"1": {
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
@@ -17,7 +14,7 @@
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
},
"50": {
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
"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 } 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,12 +46,16 @@ export abstract class ContractWrapper {
};
private _onLogAddedSubscriptionToken: string | undefined;
private _onLogRemovedSubscriptionToken: string | undefined;
constructor(web3Wrapper: Web3Wrapper, networkId: number, blockPollingIntervalMs?: number) {
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.message);
}
}
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;
@@ -79,10 +88,11 @@ export abstract class ContractWrapper {
indexFilterValues: IndexedFilterValues,
abi: ContractAbi,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi);
if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
this._startBlockAndLogStream();
this._startBlockAndLogStream(isVerbose);
}
const filterToken = filterUtils.generateUUID();
this._filters[filterToken] = filter;
@@ -104,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;
@@ -123,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)) {
@@ -151,21 +163,21 @@ export abstract class ContractWrapper {
}
});
}
private _startBlockAndLogStream(): void {
private _startBlockAndLogStream(isVerbose: boolean): void {
if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
throw new Error(ContractWrappersError.SubscriptionAlreadyPresent);
}
this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
this._onBlockAndLogStreamerError.bind(this),
ContractWrapper._onBlockstreamError.bind(this, isVerbose),
);
const catchAllLogFilter = {};
this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval(
this._reconcileBlockAsync.bind(this),
this._blockPollingIntervalMs,
this._onReconcileBlockError.bind(this),
constants.DEFAULT_BLOCK_POLLING_INTERVAL,
ContractWrapper._onBlockstreamError.bind(this, isVerbose),
);
let isRemoved = false;
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
@@ -176,21 +188,6 @@ export abstract class ContractWrapper {
this._onLogStateChanged.bind(this, isRemoved),
);
}
private _onBlockAndLogStreamerError(err: Error): void {
// Propogate all Blockstream subscriber errors to all
// top-level subscriptions
const filterCallbacks = _.values(this._filterCallbacks);
_.each(filterCallbacks, filterCallback => {
filterCallback(err);
});
}
private _onReconcileBlockError(err: Error): void {
const filterTokens = _.keys(this._filterCallbacks);
_.each(filterTokens, filterToken => {
this._unsubscribe(filterToken, err);
});
}
// 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,467 +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 { constants } from '../../test/utils/constants';
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 { 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);
const isApprovedForAll = await this.isApprovedForAllAsync(
normalizedTokenAddress,
ownerAddress,
normalizedSenderAddress,
);
if (!isApprovedForAll) {
const approvedAddress = await this.getApprovedIfExistsAsync(normalizedTokenAddress, tokenId);
if (approvedAddress !== senderAddress) {
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
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC721TokenEventArgs>(
tokenAddress: string,
eventName: ERC721TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
): 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,
);
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;
}
@@ -146,25 +133,28 @@ export class EtherTokenWrapper extends ContractWrapper {
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @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,
);
return subscriptionToken;
}
@@ -173,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);
}
/**
@@ -195,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;
@@ -209,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;
}
@@ -347,25 +350,28 @@ export class ERC20TokenWrapper extends ContractWrapper {
* @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 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,
);
return subscriptionToken;
}
@@ -374,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);
}
/**
@@ -392,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,7 +1,9 @@
export { ContractWrappers } from './contract_wrappers';
export { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
export { ExchangeWrapper } from './contract_wrappers/exchange_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 { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
export { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper';
export {
ContractWrappersError,
@@ -10,6 +12,7 @@ export {
Token,
IndexedFilterValues,
BlockRange,
OrderCancellationRequest,
OrderFillRequest,
ContractEventArgs,
ContractWrappersConfig,
@@ -19,51 +22,47 @@ export {
LogEvent,
DecodedLogEvent,
OnOrderStateChangeCallback,
OrderStatus,
OrderInfo,
} from './types';
export { Order, SignedOrder, ECSignature, OrderStateValid, OrderStateInvalid, OrderState } 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,
} 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

@@ -10,7 +10,6 @@ export const contractWrappersPrivateNetworkConfigSchema = {
exchangeContractAddress: { $ref: '/Address' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
blockPollingIntervalMs: { type: 'number' },
orderWatcherConfig: {
type: 'object',
properties: {

View File

@@ -24,7 +24,6 @@ export const contractWrappersPublicNetworkConfigSchema = {
exchangeContractAddress: { $ref: '/Address' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
blockPollingIntervalMs: { type: 'number' },
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',
};

View File

@@ -0,0 +1,91 @@
import { AbstractBalanceAndProxyAllowanceFetcher } from '@0xproject/order-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
/**
* Copy on read store for balances/proxyAllowances of tokens/accounts
*/
export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProxyAllowanceFetcher {
private _tokenWrapper: TokenWrapper;
private _defaultBlock: BlockParamLiteral;
private _balance: {
[tokenAddress: string]: {
[userAddress: string]: BigNumber;
};
};
private _proxyAllowance: {
[tokenAddress: string]: {
[userAddress: string]: BigNumber;
};
};
constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
this._tokenWrapper = token;
this._defaultBlock = defaultBlock;
this._balance = {};
this._proxyAllowance = {};
}
public async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
if (_.isUndefined(this._balance[tokenAddress]) || _.isUndefined(this._balance[tokenAddress][userAddress])) {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const balance = await this._tokenWrapper.getBalanceAsync(tokenAddress, userAddress, methodOpts);
this.setBalance(tokenAddress, userAddress, balance);
}
const cachedBalance = this._balance[tokenAddress][userAddress];
return cachedBalance;
}
public setBalance(tokenAddress: string, userAddress: string, balance: BigNumber): void {
if (_.isUndefined(this._balance[tokenAddress])) {
this._balance[tokenAddress] = {};
}
this._balance[tokenAddress][userAddress] = balance;
}
public deleteBalance(tokenAddress: string, userAddress: string): void {
if (!_.isUndefined(this._balance[tokenAddress])) {
delete this._balance[tokenAddress][userAddress];
if (_.isEmpty(this._balance[tokenAddress])) {
delete this._balance[tokenAddress];
}
}
}
public async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber> {
if (
_.isUndefined(this._proxyAllowance[tokenAddress]) ||
_.isUndefined(this._proxyAllowance[tokenAddress][userAddress])
) {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const proxyAllowance = await this._tokenWrapper.getProxyAllowanceAsync(
tokenAddress,
userAddress,
methodOpts,
);
this.setProxyAllowance(tokenAddress, userAddress, proxyAllowance);
}
const cachedProxyAllowance = this._proxyAllowance[tokenAddress][userAddress];
return cachedProxyAllowance;
}
public setProxyAllowance(tokenAddress: string, userAddress: string, proxyAllowance: BigNumber): void {
if (_.isUndefined(this._proxyAllowance[tokenAddress])) {
this._proxyAllowance[tokenAddress] = {};
}
this._proxyAllowance[tokenAddress][userAddress] = proxyAllowance;
}
public deleteProxyAllowance(tokenAddress: string, userAddress: string): void {
if (!_.isUndefined(this._proxyAllowance[tokenAddress])) {
delete this._proxyAllowance[tokenAddress][userAddress];
if (_.isEmpty(this._proxyAllowance[tokenAddress])) {
delete this._proxyAllowance[tokenAddress];
}
}
}
public deleteAll(): void {
this._balance = {};
this._proxyAllowance = {};
}
}

View File

@@ -0,0 +1,75 @@
import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
/**
* Copy on read store for filled/cancelled taker amounts
*/
export class OrderFilledCancelledLazyStore implements AbstractOrderFilledCancelledFetcher {
private _exchangeWrapper: ExchangeWrapper;
private _defaultBlock: BlockParamLiteral;
private _filledTakerAmount: {
[orderHash: string]: BigNumber;
};
private _cancelledTakerAmount: {
[orderHash: string]: BigNumber;
};
constructor(exchange: ExchangeWrapper, defaultBlock: BlockParamLiteral) {
this._exchangeWrapper = exchange;
this._defaultBlock = defaultBlock;
this._filledTakerAmount = {};
this._cancelledTakerAmount = {};
}
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
if (_.isUndefined(this._filledTakerAmount[orderHash])) {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const filledTakerAmount = await this._exchangeWrapper.getFilledTakerAmountAsync(orderHash, methodOpts);
this.setFilledTakerAmount(orderHash, filledTakerAmount);
}
const cachedFilled = this._filledTakerAmount[orderHash];
return cachedFilled;
}
public setFilledTakerAmount(orderHash: string, filledTakerAmount: BigNumber): void {
this._filledTakerAmount[orderHash] = filledTakerAmount;
}
public deleteFilledTakerAmount(orderHash: string): void {
delete this._filledTakerAmount[orderHash];
}
public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
if (_.isUndefined(this._cancelledTakerAmount[orderHash])) {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const cancelledTakerAmount = await this._exchangeWrapper.getCancelledTakerAmountAsync(
orderHash,
methodOpts,
);
this.setCancelledTakerAmount(orderHash, cancelledTakerAmount);
}
const cachedCancelled = this._cancelledTakerAmount[orderHash];
return cachedCancelled;
}
public setCancelledTakerAmount(orderHash: string, cancelledTakerAmount: BigNumber): void {
this._cancelledTakerAmount[orderHash] = cancelledTakerAmount;
}
public deleteCancelledTakerAmount(orderHash: string): void {
delete this._cancelledTakerAmount[orderHash];
}
public deleteAll(): void {
this._filledTakerAmount = {};
this._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,25 +1,30 @@
import { BigNumber } from '@0xproject/utils';
import { OrderState, SignedOrder } from '@0xproject/types';
import { BlockParam, ContractEventArg, DecodedLogArgs, LogEntryEvent, LogWithDecodedArgs } from 'ethereum-types';
import {
BlockParam,
BlockParamLiteral,
ContractAbi,
ContractEventArg,
ExchangeContractErrs,
FilterObject,
LogEntryEvent,
LogWithDecodedArgs,
Order,
OrderState,
SignedOrder,
} from '@0xproject/types';
import { ERC20TokenEventArgs, ERC20TokenEvents } from './contract_wrappers/generated/erc20_token';
import { ERC721TokenEventArgs, ERC721TokenEvents } from './contract_wrappers/generated/erc721_token';
import { ExchangeEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange';
import { WETH9EventArgs, WETH9Events } from './contract_wrappers/generated/weth9';
export enum ExchangeWrapperError {
AssetDataMismatch = 'ASSET_DATA_MISMATCH',
}
import { EtherTokenContractEventArgs, EtherTokenEvents } from './contract_wrappers/generated/ether_token';
import { ExchangeContractEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange';
import { TokenContractEventArgs, TokenEvents } from './contract_wrappers/generated/token';
export enum ContractWrappersError {
ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
EtherTokenContractDoesNotExist = 'ETHER_TOKEN_CONTRACT_DOES_NOT_EXIST',
ERC20ProxyContractDoesNotExist = 'ERC20_PROXY_CONTRACT_DOES_NOT_EXIST',
ERC721ProxyContractDoesNotExist = 'ERC721_PROXY_CONTRACT_DOES_NOT_EXIST',
ERC20TokenContractDoesNotExist = 'ERC20_TOKEN_CONTRACT_DOES_NOT_EXIST',
ERC721TokenContractDoesNotExist = 'ERC721_TOKEN_CONTRACT_DOES_NOT_EXIST',
TokenTransferProxyContractDoesNotExist = 'TOKEN_TRANSFER_PROXY_CONTRACT_DOES_NOT_EXIST',
TokenRegistryContractDoesNotExist = 'TOKEN_REGISTRY_CONTRACT_DOES_NOT_EXIST',
TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST',
ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
@@ -29,24 +34,30 @@ export enum ContractWrappersError {
OutOfGas = 'OUT_OF_GAS',
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
ERC721OwnerNotFound = 'ERC_721_OWNER_NOT_FOUND',
ERC721NoApproval = 'ERC_721_NO_APPROVAL',
}
export enum InternalContractWrappersError {
NoAbiDecoder = 'NO_ABI_DECODER',
ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY',
WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY',
}
export type LogEvent = LogEntryEvent;
export interface DecodedLogEvent<ArgsType extends DecodedLogArgs> {
export interface DecodedLogEvent<ArgsType> {
isRemoved: boolean;
log: LogWithDecodedArgs<ArgsType>;
}
export type EventCallback<ArgsType extends DecodedLogArgs> = (
err: null | Error,
log?: DecodedLogEvent<ArgsType>,
) => void;
export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void;
export enum ExchangeContractErrCodes {
ERROR_FILL_EXPIRED, // Order has already expired
ERROR_FILL_NO_VALUE, // Order has already been fully filled or cancelled
ERROR_FILL_TRUNCATION, // Rounding error too large
ERROR_FILL_BALANCE_ALLOWANCE, // Insufficient balance or allowance for token transfer
ERROR_CANCEL_EXPIRED, // Order has already expired
ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled
}
export interface ContractEvent {
logIndex: number;
@@ -60,7 +71,7 @@ export interface ContractEvent {
args: ContractEventArgs;
}
export type ContractEventArgs = ExchangeEventArgs | ERC20TokenEventArgs | ERC721TokenEventArgs | WETH9EventArgs;
export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs;
// [address, name, symbol, decimals, ipfsHash, swarmHash]
export type TokenMetadata = [string, string, string, number, string, string];
@@ -83,7 +94,7 @@ export interface TokenAddressBySymbol {
[symbol: string]: string;
}
export type ContractEvents = ERC20TokenEvents | ERC721TokenEvents | ExchangeEvents | WETH9Events;
export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents;
export interface IndexedFilterValues {
[index: string]: ContractEventArg;
@@ -94,9 +105,14 @@ export interface BlockRange {
toBlock: BlockParam;
}
export interface OrderCancellationRequest {
order: Order | SignedOrder;
takerTokenCancelAmount: BigNumber;
}
export interface OrderFillRequest {
signedOrder: SignedOrder;
takerAssetFillAmount: BigNumber;
takerTokenFillAmount: BigNumber;
}
export type AsyncMethod = (...args: any[]) => Promise<any>;
@@ -107,19 +123,17 @@ export type SyncMethod = (...args: any[]) => any;
* gasPrice: Gas price to use with every transaction
* exchangeContractAddress: The address of an exchange contract to use
* zrxContractAddress: The address of the ZRX contract to use
* erc20ProxyContractAddress: The address of the erc20 token transfer proxy contract to use
* erc721ProxyContractAddress: The address of the erc721 token transfer proxy contract to use
* tokenRegistryContractAddress: The address of a token registry contract to use
* tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use
* orderWatcherConfig: All the configs related to the orderWatcher
* blockPollingIntervalMs: The interval to use for block polling in event watching methods (defaults to 1000)
*/
export interface ContractWrappersConfig {
networkId: number;
gasPrice?: BigNumber;
exchangeContractAddress?: string;
zrxContractAddress?: string;
erc20ProxyContractAddress?: string;
erc721ProxyContractAddress?: string;
blockPollingIntervalMs?: number;
tokenRegistryContractAddress?: string;
tokenTransferProxyContractAddress?: string;
}
/**
@@ -144,7 +158,7 @@ export interface MethodOpts {
/**
* gasPrice: Gas price in Wei to use for a transaction
* gasLimit: The amount of gas to send with a transaction (in Gwei)
* gasLimit: The amount of gas to send with a transaction
*/
export interface TransactionOpts {
gasPrice?: BigNumber;
@@ -170,19 +184,3 @@ export enum TransferType {
}
export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void;
export interface OrderInfo {
orderStatus: number;
orderHash: string;
orderTakerAssetFilledAmount: BigNumber;
}
export enum OrderStatus {
INVALID,
INVALID_MAKER_ASSET_AMOUNT,
INVALID_TAKER_ASSET_AMOUNT,
FILLABLE,
EXPIRED,
FULLY_FILLED,
CANCELLED,
}

View File

@@ -1,28 +1,21 @@
import { assert as sharedAssert } from '@0xproject/assert';
// We need those two unused imports because they're actually used by sharedAssert which gets injected here
import { Schema } from '@0xproject/json-schemas'; // tslint:disable-line:no-unused-variable
import { isValidSignatureAsync } from '@0xproject/order-utils';
import { ECSignature } from '@0xproject/types'; // tslint:disable-line:no-unused-variable
import { BigNumber } from '@0xproject/utils'; // tslint:disable-line:no-unused-variable
// tslint:disable-next-line:no-unused-variable
import { Schema } from '@0xproject/json-schemas';
// tslint:disable-next-line:no-unused-variable
import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
import { isValidSignature } from '@0xproject/order-utils';
export const assert = {
...sharedAssert,
async isValidSignatureAsync(
provider: Provider,
orderHash: string,
signature: string,
signerAddress: string,
): Promise<void> {
const isValid = await isValidSignatureAsync(provider, orderHash, signature, signerAddress);
isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string): void {
const isValid = isValidSignature(orderHash, ecSignature, signerAddress);
this.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
},
isValidSubscriptionToken(variableName: string, subscriptionToken: string): void {
const uuidRegex = new RegExp('^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$');
const isValid = uuidRegex.test(subscriptionToken);
this.assert(isValid, `Expected ${variableName} to be a valid subscription token`);
},
async isSenderAddressAsync(
variableName: string,
senderAddressHex: string,

View File

@@ -4,7 +4,6 @@ export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
TESTRPC_NETWORK_ID: 50,
INVALID_JUMP_PATTERN: 'invalid JUMP at',
REVERT: 'revert',
OUT_OF_GAS_PATTERN: 'out of gas',
INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string',
// tslint:disable-next-line:custom-no-magic-numbers

View File

@@ -1,4 +1,3 @@
import { RevertReason } from '@0xproject/types';
import * as _ from 'lodash';
import { AsyncMethod, ContractWrappersError, SyncMethod } from '../types';
@@ -14,10 +13,6 @@ const contractCallErrorTransformer = (error: Error) => {
if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) {
return new Error(ContractWrappersError.OutOfGas);
}
if (_.includes(error.message, constants.REVERT)) {
const revertReason = error.message.split(constants.REVERT)[1].trim();
return new Error(revertReason);
}
return error;
};
@@ -35,8 +30,8 @@ const schemaErrorTransformer = (error: Error) => {
*/
const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
const asyncErrorHandlingDecorator = (
_target: object,
_key: string | symbol,
target: object,
key: string | symbol,
descriptor: TypedPropertyDescriptor<AsyncMethod>,
) => {
const originalMethod = descriptor.value as AsyncMethod;
@@ -62,8 +57,8 @@ const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
const syncErrorHandlingDecorator = (
_target: object,
_key: string | symbol,
target: object,
key: string | symbol,
descriptor: TypedPropertyDescriptor<SyncMethod>,
) => {
const originalMethod = descriptor.value as SyncMethod;

View File

@@ -1,7 +1,9 @@
import { ExchangeContractErrs } from '@0xproject/types';
import { BlockParamLiteral, ExchangeContractErrs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store';
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';
import { TradeSide, TransferType } from '../types';
import { constants } from '../utils/constants';
@@ -34,7 +36,8 @@ const ERR_MSG_MAPPING = {
};
export class ExchangeTransferSimulator {
private _store: AbstractBalanceAndProxyAllowanceLazyStore;
private _store: BalanceAndProxyAllowanceLazyStore;
private _UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
private static _throwValidationError(
failureReason: FailureReason,
tradeSide: TradeSide,
@@ -43,8 +46,9 @@ export class ExchangeTransferSimulator {
const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType];
throw new Error(errMsg);
}
constructor(store: AbstractBalanceAndProxyAllowanceLazyStore) {
this._store = store;
constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) {
this._store = new BalanceAndProxyAllowanceLazyStore(token, defaultBlock);
this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS = token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
}
/**
* Simulates transferFrom call performed by a proxy
@@ -88,7 +92,7 @@ export class ExchangeTransferSimulator {
amountInBaseUnits: BigNumber,
): Promise<void> {
const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress);
if (!proxyAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits));
}
}

View File

@@ -1,4 +1,12 @@
import { ConstructorAbi, ContractAbi, EventAbi, FallbackAbi, FilterObject, LogEntry, MethodAbi } from 'ethereum-types';
import {
ConstructorAbi,
ContractAbi,
EventAbi,
FallbackAbi,
FilterObject,
LogEntry,
MethodAbi,
} from '@0xproject/types';
import * as ethUtil from 'ethereumjs-util';
import * as jsSHA3 from 'js-sha3';
import * as _ from 'lodash';
@@ -20,7 +28,7 @@ export const filterUtils = {
blockRange?: BlockRange,
): FilterObject {
const eventAbi = _.find(abi, { name: eventName }) as EventAbi;
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi);
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi, eventName);
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
const topics = [topicForEventSignature, ...topicsForIndexedArgs];
@@ -36,7 +44,7 @@ export const filterUtils = {
}
return filter;
},
getEventSignatureFromAbiByName(eventAbi: EventAbi): string {
getEventSignatureFromAbiByName(eventAbi: EventAbi, eventName: ContractEvents): string {
const types = _.map(eventAbi.inputs, 'type');
const signature = `${eventAbi.name}(${types.join(',')})`;
return signature;

View File

@@ -0,0 +1,198 @@
import { getOrderHashHex, isValidSignature, OrderError } from '@0xproject/order-utils';
import { ExchangeContractErrs, Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
import { ContractWrappersError, TradeSide, TransferType } from '../types';
import { constants } from '../utils/constants';
import { utils } from '../utils/utils';
import { ExchangeTransferSimulator } from './exchange_transfer_simulator';
export class OrderValidationUtils {
private _exchangeWrapper: ExchangeWrapper;
public static validateCancelOrderThrowIfInvalid(
order: Order,
cancelTakerTokenAmount: BigNumber,
unavailableTakerTokenAmount: BigNumber,
): void {
if (cancelTakerTokenAmount.eq(0)) {
throw new Error(ExchangeContractErrs.OrderCancelAmountZero);
}
if (order.takerTokenAmount.eq(unavailableTakerTokenAmount)) {
throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
}
const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
if (order.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
throw new Error(ExchangeContractErrs.OrderCancelExpired);
}
}
public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTradeEmulator: ExchangeTransferSimulator,
signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber,
senderAddress: string,
zrxTokenAddress: string,
): Promise<void> {
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerTokenAmount,
);
await exchangeTradeEmulator.transferFromAsync(
signedOrder.makerTokenAddress,
signedOrder.maker,
senderAddress,
fillMakerTokenAmount,
TradeSide.Maker,
TransferType.Trade,
);
await exchangeTradeEmulator.transferFromAsync(
signedOrder.takerTokenAddress,
senderAddress,
signedOrder.maker,
fillTakerTokenAmount,
TradeSide.Taker,
TransferType.Trade,
);
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerFee,
);
await exchangeTradeEmulator.transferFromAsync(
zrxTokenAddress,
signedOrder.maker,
signedOrder.feeRecipient,
makerFeeAmount,
TradeSide.Maker,
TransferType.Fee,
);
const takerFeeAmount = OrderValidationUtils._getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.takerFee,
);
await exchangeTradeEmulator.transferFromAsync(
zrxTokenAddress,
senderAddress,
signedOrder.feeRecipient,
takerFeeAmount,
TradeSide.Taker,
TransferType.Fee,
);
}
private static _validateRemainingFillAmountNotZeroOrThrow(
takerTokenAmount: BigNumber,
unavailableTakerTokenAmount: BigNumber,
): void {
if (takerTokenAmount.eq(unavailableTakerTokenAmount)) {
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
}
}
private static _validateOrderNotExpiredOrThrow(expirationUnixTimestampSec: BigNumber): void {
const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
if (expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
throw new Error(ExchangeContractErrs.OrderFillExpired);
}
}
private static _getPartialAmount(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
const fillMakerTokenAmount = numerator
.mul(target)
.div(denominator)
.round(0);
return fillMakerTokenAmount;
}
constructor(exchangeWrapper: ExchangeWrapper) {
this._exchangeWrapper = exchangeWrapper;
}
public async validateOrderFillableOrThrowAsync(
exchangeTradeEmulator: ExchangeTransferSimulator,
signedOrder: SignedOrder,
zrxTokenAddress: string,
expectedFillTakerTokenAmount?: BigNumber,
): Promise<void> {
const orderHash = getOrderHashHex(signedOrder);
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
signedOrder.takerTokenAmount,
unavailableTakerTokenAmount,
);
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
let fillTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
if (!_.isUndefined(expectedFillTakerTokenAmount)) {
fillTakerTokenAmount = expectedFillTakerTokenAmount;
}
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTradeEmulator,
signedOrder,
fillTakerTokenAmount,
signedOrder.taker,
zrxTokenAddress,
);
}
public async validateFillOrderThrowIfInvalidAsync(
exchangeTradeEmulator: ExchangeTransferSimulator,
signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber,
takerAddress: string,
zrxTokenAddress: string,
): Promise<BigNumber> {
if (fillTakerTokenAmount.eq(0)) {
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
}
const orderHash = getOrderHashHex(signedOrder);
if (!isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) {
throw new Error(OrderError.InvalidSignature);
}
const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
signedOrder.takerTokenAmount,
unavailableTakerTokenAmount,
);
if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== takerAddress) {
throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
}
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
const remainingTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount)
? remainingTakerTokenAmount
: fillTakerTokenAmount;
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTradeEmulator,
signedOrder,
filledTakerTokenAmount,
takerAddress,
zrxTokenAddress,
);
const wouldRoundingErrorOccur = await this._exchangeWrapper.isRoundingErrorAsync(
filledTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerTokenAmount,
);
if (wouldRoundingErrorOccur) {
throw new Error(ExchangeContractErrs.OrderFillRoundingError);
}
return filledTakerTokenAmount;
}
public async validateFillOrKillOrderThrowIfInvalidAsync(
exchangeTradeEmulator: ExchangeTransferSimulator,
signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber,
takerAddress: string,
zrxTokenAddress: string,
): Promise<void> {
const filledTakerTokenAmount = await this.validateFillOrderThrowIfInvalidAsync(
exchangeTradeEmulator,
signedOrder,
fillTakerTokenAmount,
takerAddress,
zrxTokenAddress,
);
if (filledTakerTokenAmount !== fillTakerTokenAmount) {
throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount);
}
}
}

View File

@@ -1,6 +1,9 @@
import { BigNumber } from '@0xproject/utils';
export const utils = {
spawnSwitchErr(name: string, value: any): Error {
return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
},
getCurrentUnixTimestampSec(): BigNumber {
const milisecondsInSecond = 1000;
return new BigNumber(Date.now() / milisecondsInSecond).round();

View File

@@ -1,4 +1,6 @@
import { web3Factory } from '@0xproject/dev-utils';
import * as fs from 'fs';
import 'make-promises-safe';
import { ContractWrappers } from '../src';
@@ -10,34 +12,39 @@ chaiSetup.configure();
// Those tests are slower cause they're talking to a remote node
const TIMEOUT = 10000;
// TODO: Re-enable those tests after final kovan and ropsten deployments are done.
describe.skip('Artifacts', () => {
describe('Artifacts', () => {
describe('contracts are deployed on kovan', () => {
const kovanRpcUrl = constants.KOVAN_RPC_URL;
const provider = web3Factory.getRpcProvider({ rpcUrl: kovanRpcUrl });
const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider;
const config = {
networkId: constants.KOVAN_NETWORK_ID,
};
const contractWrappers = new ContractWrappers(provider, config);
it('erc20 proxy contract is deployed', async () => {
await (contractWrappers.erc20Proxy as any)._getTokenTransferProxyContractAsync();
it('token registry contract is deployed', async () => {
await (contractWrappers.tokenRegistry as any)._getTokenRegistryContractAsync();
}).timeout(TIMEOUT);
it('erc721 proxy contract is deployed', async () => {
await (contractWrappers.erc721Proxy as any)._getTokenTransferProxyContractAsync();
it('proxy contract is deployed', async () => {
await (contractWrappers.proxy as any)._getTokenTransferProxyContractAsync();
}).timeout(TIMEOUT);
it('exchange contract is deployed', async () => {
await (contractWrappers.exchange as any)._getExchangeContractAsync();
}).timeout(TIMEOUT);
});
describe('contracts are deployed on ropsten', () => {
const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
const provider = web3Factory.getRpcProvider({ rpcUrl: ropstenRpcUrl });
const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider;
const config = {
networkId: constants.ROPSTEN_NETWORK_ID,
};
const contractWrappers = new ContractWrappers(provider, config);
it('erc20 proxy contract is deployed', async () => {
await (contractWrappers.erc20Proxy as any)._getTokenTransferProxyContractAsync();
it('token registry contract is deployed', async () => {
await (contractWrappers.tokenRegistry as any)._getTokenRegistryContractAsync();
}).timeout(TIMEOUT);
it('erc721 proxy contract is deployed', async () => {
await (contractWrappers.erc721Proxy as any)._getTokenTransferProxyContractAsync();
it('proxy contract is deployed', async () => {
await (contractWrappers.proxy as any)._getTokenTransferProxyContractAsync();
}).timeout(TIMEOUT);
it('exchange contract is deployed', async () => {
await (contractWrappers.exchange as any)._getExchangeContractAsync();
}).timeout(TIMEOUT);
});
});

View File

@@ -1,35 +0,0 @@
import * as chai from 'chai';
import { ContractWrappers } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { provider } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
describe('ERC721ProxyWrapper', () => {
let contractWrappers: ContractWrappers;
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
};
before(async () => {
contractWrappers = new ContractWrappers(provider, config);
});
describe('#isAuthorizedAsync', () => {
it('should return false if the address is not authorized', async () => {
const isAuthorized = await contractWrappers.erc721Proxy.isAuthorizedAsync(constants.NULL_ADDRESS);
expect(isAuthorized).to.be.false();
});
});
describe('#getAuthorizedAddressesAsync', () => {
it('should return the list of authorized addresses', async () => {
const authorizedAddresses = await contractWrappers.erc721Proxy.getAuthorizedAddressesAsync();
for (const authorizedAddress of authorizedAddresses) {
const isAuthorized = await contractWrappers.erc721Proxy.isAuthorizedAsync(authorizedAddress);
expect(isAuthorized).to.be.true();
}
});
});
});

View File

@@ -1,472 +0,0 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { EmptyWalletSubprovider } from '@0xproject/subproviders';
import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { Provider } from 'ethereum-types';
import 'mocha';
import Web3ProviderEngine = require('web3-provider-engine');
import {
BlockParamLiteral,
BlockRange,
ContractWrappers,
ContractWrappersError,
DecodedLogEvent,
ERC721TokenApprovalEventArgs,
ERC721TokenApprovalForAllEventArgs,
ERC721TokenEvents,
ERC721TokenTransferEventArgs,
} from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('ERC721Wrapper', () => {
let contractWrappers: ContractWrappers;
let userAddresses: string[];
let tokens: string[];
let ownerAddress: string;
let tokenAddress: string;
let anotherOwnerAddress: string;
let operatorAddress: string;
let approvedAddress: string;
let receiverAddress: string;
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
};
before(async () => {
contractWrappers = new ContractWrappers(provider, config);
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
tokens = tokenUtils.getDummyERC721TokenAddresses();
tokenAddress = tokens[0];
[ownerAddress, operatorAddress, anotherOwnerAddress, approvedAddress, receiverAddress] = userAddresses;
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('#transferFromAsync', () => {
it('should fail to transfer NFT if fromAddress has no approvals set', async () => {
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
return expect(
contractWrappers.erc721Token.transferFromAsync(tokenAddress, receiverAddress, approvedAddress, tokenId),
).to.be.rejectedWith(ContractWrappersError.ERC721NoApproval);
});
it('should successfully transfer tokens when sender is an approved address', async () => {
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
let txHash = await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const owner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
expect(owner).to.be.equal(ownerAddress);
txHash = await contractWrappers.erc721Token.transferFromAsync(
tokenAddress,
receiverAddress,
approvedAddress,
tokenId,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const newOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
expect(newOwner).to.be.equal(receiverAddress);
});
it('should successfully transfer tokens when sender is an approved operator', async () => {
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const isApprovedForAll = true;
let txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
isApprovedForAll,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const owner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
expect(owner).to.be.equal(ownerAddress);
txHash = await contractWrappers.erc721Token.transferFromAsync(
tokenAddress,
receiverAddress,
operatorAddress,
tokenId,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const newOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
expect(newOwner).to.be.equal(receiverAddress);
});
});
describe('#getTokenCountAsync', () => {
describe('With provider with accounts', () => {
it('should return the count for an existing ERC721 token', async () => {
let tokenCount = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, ownerAddress);
expect(tokenCount).to.be.bignumber.equal(0);
await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
tokenCount = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, ownerAddress);
expect(tokenCount).to.be.bignumber.equal(1);
});
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
return expect(
contractWrappers.erc721Token.getTokenCountAsync(nonExistentTokenAddress, ownerAddress),
).to.be.rejectedWith(ContractWrappersError.ERC721TokenContractDoesNotExist);
});
it('should return a balance of 0 for a non-existent owner address', async () => {
const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593';
const balance = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, nonExistentOwner);
const expectedBalance = new BigNumber(0);
return expect(balance).to.be.bignumber.equal(expectedBalance);
});
});
describe('With provider without accounts', () => {
let zeroExContractWithoutAccounts: ContractWrappers;
before(async () => {
const emptyWalletProvider = addEmptyWalletSubprovider(provider);
zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config);
});
it('should return balance even when called with provider instance without addresses', async () => {
const balance = await zeroExContractWithoutAccounts.erc721Token.getTokenCountAsync(
tokenAddress,
ownerAddress,
);
return expect(balance).to.be.bignumber.equal(0);
});
});
});
describe('#getOwnerOfAsync', () => {
it('should return the owner for an existing ERC721 token', async () => {
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const tokenOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId);
expect(tokenOwner).to.be.bignumber.equal(ownerAddress);
});
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
const fakeTokenId = new BigNumber(42);
return expect(
contractWrappers.erc721Token.getOwnerOfAsync(nonExistentTokenAddress, fakeTokenId),
).to.be.rejectedWith(ContractWrappersError.ERC721TokenContractDoesNotExist);
});
it('should return undefined not 0 for a non-existent ERC721', async () => {
const fakeTokenId = new BigNumber(42);
return expect(contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, fakeTokenId)).to.be.rejectedWith(
ContractWrappersError.ERC721OwnerNotFound,
);
});
});
describe('#setApprovalForAllAsync/isApprovedForAllAsync', () => {
it('should check if operator address is approved', async () => {
let isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
);
expect(isApprovedForAll).to.be.false();
// set
isApprovedForAll = true;
let txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
isApprovedForAll,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
);
expect(isApprovedForAll).to.be.true();
// unset
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
false,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
);
expect(isApprovedForAll).to.be.false();
});
});
describe('#setProxyApprovalForAllAsync/isProxyApprovedForAllAsync', () => {
it('should check if proxy address is approved', async () => {
let isApprovedForAll = true;
const txHash = await contractWrappers.erc721Token.setProxyApprovalForAllAsync(
tokenAddress,
ownerAddress,
isApprovedForAll,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
isApprovedForAll = await contractWrappers.erc721Token.isProxyApprovedForAllAsync(
tokenAddress,
ownerAddress,
);
expect(isApprovedForAll).to.be.true();
});
});
describe('#setApprovalAsync/getApprovedIfExistsAsync', () => {
it("should set the spender's approval", async () => {
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const approvalBeforeSet = await contractWrappers.erc721Token.getApprovedIfExistsAsync(
tokenAddress,
tokenId,
);
expect(approvalBeforeSet).to.be.undefined();
await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId);
const approvalAfterSet = await contractWrappers.erc721Token.getApprovedIfExistsAsync(tokenAddress, tokenId);
expect(approvalAfterSet).to.be.equal(approvedAddress);
});
});
describe('#setProxyApprovalAsync/isProxyApprovedAsync', () => {
it('should set the proxy approval', async () => {
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const approvalBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync(tokenAddress, tokenId);
expect(approvalBeforeSet).to.be.false();
await contractWrappers.erc721Token.setProxyApprovalAsync(tokenAddress, tokenId);
const approvalAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync(tokenAddress, tokenId);
expect(approvalAfterSet).to.be.true();
});
});
describe('#subscribe', () => {
const indexFilterValues = {};
afterEach(() => {
contractWrappers.erc721Token.unsubscribeAll();
});
// Hack: Mocha does not allow a test to be both async and have a `done` callback
// Since we need to await the receipt of the event in the `subscribe` callback,
// we do need both. A hack is to make the top-level a sync fn w/ a done callback and then
// wrap the rest of the test in an async block
// Source: https://github.com/mochajs/mocha/issues/2407
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
(async () => {
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<ERC721TokenTransferEventArgs>) => {
expect(logEvent.isRemoved).to.be.false();
expect(logEvent.log.logIndex).to.be.equal(0);
expect(logEvent.log.transactionIndex).to.be.equal(0);
expect(logEvent.log.blockNumber).to.be.a('number');
const args = logEvent.log.args;
expect(args._from).to.be.equal(ownerAddress);
expect(args._to).to.be.equal(receiverAddress);
expect(args._tokenId).to.be.bignumber.equal(tokenId);
},
);
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const isApprovedForAll = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
isApprovedForAll,
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
contractWrappers.erc721Token.subscribe(
tokenAddress,
ERC721TokenEvents.Transfer,
indexFilterValues,
callback,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await contractWrappers.erc721Token.transferFromAsync(
tokenAddress,
receiverAddress,
operatorAddress,
tokenId,
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
})().catch(done);
});
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
(async () => {
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<ERC721TokenApprovalEventArgs>) => {
expect(logEvent).to.not.be.undefined();
expect(logEvent.isRemoved).to.be.false();
const args = logEvent.log.args;
expect(args._owner).to.be.equal(ownerAddress);
expect(args._approved).to.be.equal(approvedAddress);
expect(args._tokenId).to.be.bignumber.equal(tokenId);
},
);
contractWrappers.erc721Token.subscribe(
tokenAddress,
ERC721TokenEvents.Approval,
indexFilterValues,
callback,
);
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
await web3Wrapper.awaitTransactionSuccessAsync(
await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId),
constants.AWAIT_TRANSACTION_MINED_MS,
);
})().catch(done);
});
it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => {
(async () => {
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<ERC721TokenApprovalEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
},
);
contractWrappers.erc721Token.subscribe(
tokenAddress,
ERC721TokenEvents.Transfer,
indexFilterValues,
callbackNeverToBeCalled,
);
const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)();
contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID);
contractWrappers.erc721Token.subscribe(
tokenAddress,
ERC721TokenEvents.Approval,
indexFilterValues,
callbackToBeCalled,
);
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
await web3Wrapper.awaitTransactionSuccessAsync(
await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId),
constants.AWAIT_TRANSACTION_MINED_MS,
);
done();
})().catch(done);
});
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
(async () => {
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<ERC721TokenApprovalForAllEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
},
);
const subscriptionToken = contractWrappers.erc721Token.subscribe(
tokenAddress,
ERC721TokenEvents.ApprovalForAll,
indexFilterValues,
callbackNeverToBeCalled,
);
contractWrappers.erc721Token.unsubscribe(subscriptionToken);
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
isApproved,
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
done();
})().catch(done);
});
});
describe('#getLogsAsync', () => {
let tokenTransferProxyAddress: string;
const blockRange: BlockRange = {
fromBlock: 0,
toBlock: BlockParamLiteral.Latest,
};
let txHash: string;
before(() => {
tokenTransferProxyAddress = contractWrappers.erc721Proxy.getContractAddress();
});
it('should get logs with decoded args emitted by ApprovalForAll', async () => {
const isApprovedForAll = true;
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
isApprovedForAll,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const eventName = ERC721TokenEvents.ApprovalForAll;
const indexFilterValues = {};
const logs = await contractWrappers.erc721Token.getLogsAsync<ERC721TokenApprovalForAllEventArgs>(
tokenAddress,
eventName,
blockRange,
indexFilterValues,
);
expect(logs).to.have.length(1);
const args = logs[0].args;
expect(logs[0].event).to.be.equal(eventName);
expect(args._owner).to.be.equal(ownerAddress);
expect(args._operator).to.be.equal(operatorAddress);
expect(args._approved).to.be.equal(isApprovedForAll);
});
it('should only get the logs with the correct event name', async () => {
const isApprovedForAll = true;
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
isApprovedForAll,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const differentEventName = ERC721TokenEvents.Transfer;
const indexFilterValues = {};
const logs = await contractWrappers.erc721Token.getLogsAsync(
tokenAddress,
differentEventName,
blockRange,
indexFilterValues,
);
expect(logs).to.have.length(0);
});
it('should only get the logs with the correct indexed fields', async () => {
const isApprovedForAll = true;
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
ownerAddress,
operatorAddress,
isApprovedForAll,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
tokenAddress,
anotherOwnerAddress,
operatorAddress,
isApprovedForAll,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const eventName = ERC721TokenEvents.ApprovalForAll;
const indexFilterValues = {
_owner: anotherOwnerAddress,
};
const logs = await contractWrappers.erc721Token.getLogsAsync<ERC721TokenApprovalForAllEventArgs>(
tokenAddress,
eventName,
blockRange,
indexFilterValues,
);
expect(logs).to.have.length(1);
const args = logs[0].args;
expect(args._owner).to.be.equal(anotherOwnerAddress);
});
});
});
// tslint:disable:max-file-line-count
function addEmptyWalletSubprovider(p: Provider): Provider {
const providerEngine = new Web3ProviderEngine();
providerEngine.addProvider(new EmptyWalletSubprovider());
const currentSubproviders = (p as any)._providers;
for (const subprovider of currentSubproviders) {
providerEngine.addProvider(subprovider);
}
providerEngine.start();
return providerEngine;
}

View File

@@ -1,26 +1,28 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { BlockchainLifecycle, callbackErrorReporter, devConstants, web3Factory } from '@0xproject/dev-utils';
import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import 'make-promises-safe';
import 'mocha';
import {
ApprovalContractEventArgs,
BlockParamLiteral,
BlockRange,
ContractWrappers,
ContractWrappersError,
DecodedLogEvent,
WETH9ApprovalEventArgs,
WETH9DepositEventArgs,
WETH9Events,
WETH9TransferEventArgs,
WETH9WithdrawalEventArgs,
DepositContractEventArgs,
EtherTokenEvents,
Token,
TransferContractEventArgs,
WithdrawalContractEventArgs,
} 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';
chaiSetup.configure();
@@ -35,6 +37,7 @@ const MAX_REASONABLE_GAS_COST_IN_WEI = 62517;
describe('EtherTokenWrapper', () => {
let contractWrappers: ContractWrappers;
let tokens: Token[];
let userAddresses: string[];
let addressWithETH: string;
let wethContractAddress: string;
@@ -52,6 +55,7 @@ describe('EtherTokenWrapper', () => {
const withdrawalAmount = new BigNumber(42);
before(async () => {
contractWrappers = new ContractWrappers(provider, zeroExConfig);
tokens = await contractWrappers.tokenRegistry.getTokensAsync();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
addressWithETH = userAddresses[0];
wethContractAddress = contractWrappers.etherToken.getContractAddressIfExists() as string;
@@ -82,10 +86,7 @@ describe('EtherTokenWrapper', () => {
describe('#depositAsync', () => {
it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => {
const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync(
wethContractAddress,
addressWithETH,
);
const preWETHBalance = await contractWrappers.token.getBalanceAsync(wethContractAddress, addressWithETH);
expect(preETHBalance).to.be.bignumber.gt(0);
expect(preWETHBalance).to.be.bignumber.equal(0);
@@ -94,10 +95,10 @@ describe('EtherTokenWrapper', () => {
depositWeiAmount,
addressWithETH,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
const postETHBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
const postWETHBalanceInBaseUnits = await contractWrappers.erc20Token.getBalanceAsync(
const postWETHBalanceInBaseUnits = await contractWrappers.token.getBalanceAsync(
wethContractAddress,
addressWithETH,
);
@@ -126,10 +127,7 @@ describe('EtherTokenWrapper', () => {
const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount);
const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync(
wethContractAddress,
addressWithETH,
);
const preWETHBalance = await contractWrappers.token.getBalanceAsync(wethContractAddress, addressWithETH);
let gasCost = expectedPreETHBalance.minus(preETHBalance);
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount);
@@ -139,10 +137,10 @@ describe('EtherTokenWrapper', () => {
depositWeiAmount,
addressWithETH,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
const postETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH);
const postWETHBalanceInBaseUnits = await contractWrappers.erc20Token.getBalanceAsync(
const postWETHBalanceInBaseUnits = await contractWrappers.token.getBalanceAsync(
wethContractAddress,
addressWithETH,
);
@@ -153,10 +151,7 @@ describe('EtherTokenWrapper', () => {
expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI);
});
it('should throw if user has insufficient WETH balance for withdrawal', async () => {
const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync(
wethContractAddress,
addressWithETH,
);
const preWETHBalance = await contractWrappers.token.getBalanceAsync(wethContractAddress, addressWithETH);
expect(preWETHBalance).to.be.bignumber.equal(0);
// tslint:disable-next-line:custom-no-magic-numbers
@@ -170,8 +165,10 @@ describe('EtherTokenWrapper', () => {
describe('#subscribe', () => {
const indexFilterValues = {};
let etherTokenAddress: string;
before(async () => {
etherTokenAddress = tokenUtils.getWethTokenAddress();
before(() => {
const tokenUtils = new TokenUtils(tokens);
const etherToken = tokenUtils.getWethTokenOrThrow();
etherTokenAddress = etherToken.address;
});
afterEach(() => {
contractWrappers.etherToken.unsubscribeAll();
@@ -184,7 +181,7 @@ describe('EtherTokenWrapper', () => {
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
(async () => {
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<WETH9TransferEventArgs>) => {
(logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
expect(logEvent).to.not.be.undefined();
expect(logEvent.isRemoved).to.be.false();
expect(logEvent.log.logIndex).to.be.equal(0);
@@ -199,11 +196,11 @@ describe('EtherTokenWrapper', () => {
await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
contractWrappers.etherToken.subscribe(
etherTokenAddress,
WETH9Events.Transfer,
EtherTokenEvents.Transfer,
indexFilterValues,
callback,
);
await contractWrappers.erc20Token.transferAsync(
await contractWrappers.token.transferAsync(
etherTokenAddress,
addressWithETH,
addressWithoutFunds,
@@ -214,7 +211,7 @@ describe('EtherTokenWrapper', () => {
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
(async () => {
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => {
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
expect(logEvent).to.not.be.undefined();
expect(logEvent.isRemoved).to.be.false();
const args = logEvent.log.args;
@@ -225,11 +222,11 @@ describe('EtherTokenWrapper', () => {
);
contractWrappers.etherToken.subscribe(
etherTokenAddress,
WETH9Events.Approval,
EtherTokenEvents.Approval,
indexFilterValues,
callback,
);
await contractWrappers.erc20Token.setAllowanceAsync(
await contractWrappers.token.setAllowanceAsync(
etherTokenAddress,
addressWithETH,
addressWithoutFunds,
@@ -240,7 +237,7 @@ describe('EtherTokenWrapper', () => {
it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => {
(async () => {
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<WETH9DepositEventArgs>) => {
(logEvent: DecodedLogEvent<DepositContractEventArgs>) => {
expect(logEvent).to.not.be.undefined();
expect(logEvent.isRemoved).to.be.false();
const args = logEvent.log.args;
@@ -250,7 +247,7 @@ describe('EtherTokenWrapper', () => {
);
contractWrappers.etherToken.subscribe(
etherTokenAddress,
WETH9Events.Deposit,
EtherTokenEvents.Deposit,
indexFilterValues,
callback,
);
@@ -260,7 +257,7 @@ describe('EtherTokenWrapper', () => {
it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => {
(async () => {
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<WETH9WithdrawalEventArgs>) => {
(logEvent: DecodedLogEvent<WithdrawalContractEventArgs>) => {
expect(logEvent).to.not.be.undefined();
expect(logEvent.isRemoved).to.be.false();
const args = logEvent.log.args;
@@ -271,7 +268,7 @@ describe('EtherTokenWrapper', () => {
await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
contractWrappers.etherToken.subscribe(
etherTokenAddress,
WETH9Events.Withdrawal,
EtherTokenEvents.Withdrawal,
indexFilterValues,
callback,
);
@@ -281,13 +278,13 @@ describe('EtherTokenWrapper', () => {
it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => {
(async () => {
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
(_logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => {
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
},
);
contractWrappers.etherToken.subscribe(
etherTokenAddress,
WETH9Events.Transfer,
EtherTokenEvents.Transfer,
indexFilterValues,
callbackNeverToBeCalled,
);
@@ -296,11 +293,11 @@ describe('EtherTokenWrapper', () => {
await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
contractWrappers.etherToken.subscribe(
etherTokenAddress,
WETH9Events.Transfer,
EtherTokenEvents.Transfer,
indexFilterValues,
callbackToBeCalled,
);
await contractWrappers.erc20Token.transferAsync(
await contractWrappers.token.transferAsync(
etherTokenAddress,
addressWithETH,
addressWithoutFunds,
@@ -311,19 +308,19 @@ describe('EtherTokenWrapper', () => {
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
(async () => {
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
(_logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => {
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
},
);
await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH);
const subscriptionToken = contractWrappers.etherToken.subscribe(
etherTokenAddress,
WETH9Events.Transfer,
EtherTokenEvents.Transfer,
indexFilterValues,
callbackNeverToBeCalled,
);
contractWrappers.etherToken.unsubscribe(subscriptionToken);
await contractWrappers.erc20Token.transferAsync(
await contractWrappers.token.transferAsync(
etherTokenAddress,
addressWithETH,
addressWithoutFunds,
@@ -335,7 +332,7 @@ describe('EtherTokenWrapper', () => {
});
describe('#getLogsAsync', () => {
let etherTokenAddress: string;
let erc20ProxyAddress: string;
let tokenTransferProxyAddress: string;
const blockRange: BlockRange = {
fromBlock: 0,
toBlock: BlockParamLiteral.Latest,
@@ -343,18 +340,17 @@ describe('EtherTokenWrapper', () => {
let txHash: string;
before(() => {
addressWithETH = userAddresses[0];
etherTokenAddress = tokenUtils.getWethTokenAddress();
erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
const tokenUtils = new TokenUtils(tokens);
const etherToken = tokenUtils.getWethTokenOrThrow();
etherTokenAddress = etherToken.address;
tokenTransferProxyAddress = contractWrappers.proxy.getContractAddress();
});
it('should get logs with decoded args emitted by Approval', async () => {
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
etherTokenAddress,
addressWithETH,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const eventName = WETH9Events.Approval;
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
const eventName = EtherTokenEvents.Approval;
const indexFilterValues = {};
const logs = await contractWrappers.etherToken.getLogsAsync<WETH9ApprovalEventArgs>(
const logs = await contractWrappers.etherToken.getLogsAsync<ApprovalContractEventArgs>(
etherTokenAddress,
eventName,
blockRange,
@@ -364,14 +360,14 @@ describe('EtherTokenWrapper', () => {
const args = logs[0].args;
expect(logs[0].event).to.be.equal(eventName);
expect(args._owner).to.be.equal(addressWithETH);
expect(args._spender).to.be.equal(erc20ProxyAddress);
expect(args._value).to.be.bignumber.equal(contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
expect(args._spender).to.be.equal(tokenTransferProxyAddress);
expect(args._value).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
});
it('should get logs with decoded args emitted by Deposit', async () => {
await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH);
const eventName = WETH9Events.Deposit;
const eventName = EtherTokenEvents.Deposit;
const indexFilterValues = {};
const logs = await contractWrappers.etherToken.getLogsAsync<WETH9DepositEventArgs>(
const logs = await contractWrappers.etherToken.getLogsAsync<DepositContractEventArgs>(
etherTokenAddress,
eventName,
blockRange,
@@ -384,12 +380,9 @@ describe('EtherTokenWrapper', () => {
expect(args._value).to.be.bignumber.equal(depositAmount);
});
it('should only get the logs with the correct event name', async () => {
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
etherTokenAddress,
addressWithETH,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const differentEventName = WETH9Events.Transfer;
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
const differentEventName = EtherTokenEvents.Transfer;
const indexFilterValues = {};
const logs = await contractWrappers.etherToken.getLogsAsync(
etherTokenAddress,
@@ -400,21 +393,18 @@ describe('EtherTokenWrapper', () => {
expect(logs).to.have.length(0);
});
it('should only get the logs with the correct indexed fields', async () => {
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
etherTokenAddress,
addressWithETH,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(
etherTokenAddress,
addressWithoutFunds,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const eventName = WETH9Events.Approval;
await web3Wrapper.awaitTransactionMinedAsync(txHash);
const eventName = EtherTokenEvents.Approval;
const indexFilterValues = {
_owner: addressWithETH,
};
const logs = await contractWrappers.etherToken.getLogsAsync<WETH9ApprovalEventArgs>(
const logs = await contractWrappers.etherToken.getLogsAsync<ApprovalContractEventArgs>(
etherTokenAddress,
eventName,
blockRange,

View File

@@ -0,0 +1,120 @@
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
import { BlockParamLiteral, Token } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import 'make-promises-safe';
import { ContractWrappers, ExchangeContractErrs } from '../src';
import { TradeSide, TransferType } from '../src/types';
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('ExchangeTransferSimulator', () => {
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
};
const contractWrappers = new ContractWrappers(provider, config);
const transferAmount = new BigNumber(5);
let userAddresses: string[];
let tokens: Token[];
let coinbase: string;
let sender: string;
let recipient: string;
let exampleTokenAddress: string;
let exchangeTransferSimulator: ExchangeTransferSimulator;
let txHash: string;
before(async () => {
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
[coinbase, sender, recipient] = userAddresses;
tokens = await contractWrappers.tokenRegistry.getTokensAsync();
exampleTokenAddress = tokens[0].address;
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('#transferFromAsync', () => {
beforeEach(() => {
exchangeTransferSimulator = new ExchangeTransferSimulator(contractWrappers.token, BlockParamLiteral.Latest);
});
it("throws if the user doesn't have enough allowance", async () => {
return expect(
exchangeTransferSimulator.transferFromAsync(
exampleTokenAddress,
sender,
recipient,
transferAmount,
TradeSide.Taker,
TransferType.Trade,
),
).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance);
});
it("throws if the user doesn't have enough balance", async () => {
txHash = await contractWrappers.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
return expect(
exchangeTransferSimulator.transferFromAsync(
exampleTokenAddress,
sender,
recipient,
transferAmount,
TradeSide.Maker,
TransferType.Trade,
),
).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance);
});
it('updates balances and proxyAllowance after transfer', async () => {
txHash = await contractWrappers.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
txHash = await contractWrappers.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
await exchangeTransferSimulator.transferFromAsync(
exampleTokenAddress,
sender,
recipient,
transferAmount,
TradeSide.Taker,
TransferType.Trade,
);
const store = (exchangeTransferSimulator as any)._store;
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
expect(senderBalance).to.be.bignumber.equal(0);
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
expect(senderProxyAllowance).to.be.bignumber.equal(0);
});
it("doesn't update proxyAllowance after transfer if unlimited", async () => {
txHash = await contractWrappers.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender);
await web3Wrapper.awaitTransactionMinedAsync(txHash);
await exchangeTransferSimulator.transferFromAsync(
exampleTokenAddress,
sender,
recipient,
transferAmount,
TradeSide.Taker,
TransferType.Trade,
);
const store = (exchangeTransferSimulator as any)._store;
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
expect(senderBalance).to.be.bignumber.equal(0);
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
expect(senderProxyAllowance).to.be.bignumber.equal(
contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
);
});
});
});

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