Compare commits

..

143 Commits

Author SHA1 Message Date
Francesco Agosti
f5c74d123a Merge pull request #644 from 0xProject/feature/website/refactor-token-state-fetching
Move TokenState fetching logic up into Portal.tsx so it can be used by Wallet and PortalOnboardingFlow
2018-06-04 10:46:08 -07:00
fragosti
c8421efcd3 Address feedback 2018-06-04 10:27:24 -07:00
fragosti
f382609d01 Implement WETH step logic for continue 2018-06-04 10:25:38 -07:00
fragosti
f9615c18a1 Move trackedTokenStateByAddress logic into portal 2018-06-04 10:25:38 -07:00
Fabio Berger
d50fbac5f9 Merge pull request #636 from 0xProject/refactor/order-utils/for-v2
Refactor order-utils for v2
2018-06-01 17:29:44 -07:00
Fabio Berger
d3c64bd5b4 Merge branch 'v2-prototype' into refactor/order-utils/for-v2
* v2-prototype:
  Set contract expiration time to a constant 10 minutes
  Remove unused promises array
  Make erc20_wrapper and erc721_wrapper serial
  Rename changelogs to changelog
  Add CHANGELOG entry
  Check that git branch is up to date before publishing
  Move prepublish checks before building packages for publishing
  Refactor changelog utils to a separate module
2018-06-01 17:13:02 -07:00
Fabio Berger
7024a7468a Improve comments and remove unused imports 2018-06-01 17:02:54 -07:00
Alex Browne
62e60e2ba6 Merge pull request #651 from 0xProject/serial-contract-wrappers
Make erc20_wrapper and erc721_wrapper serial and increase contract expiration time
2018-06-01 16:56:32 -07:00
Alex Browne
fb3860757c Set contract expiration time to a constant 10 minutes 2018-06-01 16:40:38 -07:00
Alex Browne
e4a8b17522 Remove unused promises array 2018-06-01 16:18:22 -07:00
Alex Browne
448df1bb9c Make erc20_wrapper and erc721_wrapper serial 2018-06-01 16:09:49 -07:00
Leonid Logvinov
bf6900fb2a Merge pull request #650 from 0xProject/feature/publishing
Improve publishing flow
2018-06-01 15:50:13 -07:00
Leonid Logvinov
50552546f3 Rename changelogs to changelog 2018-06-01 15:46:16 -07:00
Fabio Berger
324fab8186 Fix tslint issues 2018-06-01 14:12:18 -07:00
Fabio Berger
7ab80f01b5 Add comment to exported method 2018-06-01 14:09:47 -07:00
Fabio Berger
9ce4a5c7b1 Add missing dep 2018-06-01 14:09:16 -07:00
Fabio Berger
c9a0525a10 Fix types version 2018-06-01 14:02:15 -07:00
Fabio Berger
83465bb7f5 Also manually symlink types package in contracts 2018-06-01 14:02:00 -07:00
Leonid Logvinov
e8771fb36a Add CHANGELOG entry 2018-06-01 13:59:45 -07:00
Leonid Logvinov
d4d03f3d7f Check that git branch is up to date before publishing 2018-06-01 13:55:40 -07:00
Fabio Berger
d567d667e8 Remove usage of prebuild since it doesn't run on watch 2018-06-01 13:49:30 -07:00
Fabio Berger
3d55bbbc29 remove artifactsDir and contracts from compiler.json 2018-06-01 13:42:06 -07:00
Leonid Logvinov
2f8e52f905 Move prepublish checks before building packages for publishing 2018-06-01 13:39:04 -07:00
Fabio Berger
a5896ac6b6 Add postinstall hack to get around yarn not setting up symlinks properly. This is a temporary fix while we wait on: https://github.com/yarnpkg/yarn/issues/5907 2018-06-01 13:36:22 -07:00
Fabio Berger
94b9d5644c Fix type imports 2018-06-01 13:33:46 -07:00
Leonid Logvinov
06e5fc233c Refactor changelog utils to a separate module 2018-06-01 13:12:45 -07:00
Fabio Berger
aefb922a05 Remove ISigner artifact 2018-06-01 13:11:18 -07:00
Fabio Berger
a22434fd73 Merge branch 'v2-prototype' into refactor/order-utils/for-v2
* v2-prototype:
  Update v2 artifacts
  Add IWallet and IValidator to compiled contracts
  Split migrations compile command into one for V1 and another for V2

# Conflicts:
#	packages/migrations/artifacts/2.0.0/Exchange.json
#	packages/migrations/artifacts/2.0.0/TestSignatureValidator.json
2018-06-01 13:08:38 -07:00
Fabio Berger
c41846805d Merge pull request #649 from 0xProject/addArtifacts
Add Updated V2 Artifacts
2018-06-01 13:06:42 -07:00
Fabio Berger
b7b45b69a6 Merge branch 'v2-prototype' into refactor/order-utils/for-v2
* v2-prototype: (33 commits)
  Only show ProviderDisplay in portal
  Improve sol-cov docs
  Remove old parse code
  Refactor order parser and add shared order support to new portal
  Add generate and fill order routes
  Address feedback
  Override ethereumjs-tx version
  Fix missing key
  Update placeholder param ordering
  Change userEtherBalanceInWei to optional so we can know if its loading
  Add loading state to ProviderDisplay
  Tweaks
  Add Placeholder component
  Add StandardIconRow
  Split render into loading and loaaded
  Fix linter errors
  Fix linter errors
  Add ethereum-types to extraFileIncludes
  Introduce ethereum-types package
  Remove merge conflicts from yarn.lock
  ...

# Conflicts:
#	packages/contracts/src/utils/exchange_wrapper.ts
#	packages/contracts/src/utils/match_order_tester.ts
#	packages/contracts/src/utils/types.ts
#	packages/contracts/test/exchange/core.ts
#	packages/contracts/test/exchange/match_orders.ts
#	packages/contracts/test/libraries/lib_bytes.ts
#	packages/sol-cov/package.json
2018-06-01 13:05:17 -07:00
Fabio Berger
ed5528664c Update v2 artifacts 2018-06-01 12:20:54 -07:00
Fabio Berger
fe88d3c225 Add IWallet and IValidator to compiled contracts 2018-06-01 12:20:36 -07:00
Fabio Berger
aed4ee8694 Split migrations compile command into one for V1 and another for V2 2018-06-01 12:05:57 -07:00
Fabio Berger
df9cfe7840 Update json-schemas version to 1.0.0 to avoid possible conflicts 2018-06-01 11:48:55 -07:00
Fabio Berger
8cd4578d83 Add signature specific validation methods, and other refactors 2018-06-01 11:34:12 -07:00
Brandon Millman
9ca41b9536 Merge pull request #648 from 0xProject/feature/website/fill-order
Add shared order support
2018-06-01 11:22:25 -07:00
Brandon Millman
559743c911 Only show ProviderDisplay in portal 2018-06-01 11:05:01 -07:00
Leonid Logvinov
04a0eae241 Improve sol-cov docs 2018-06-01 10:43:33 -07:00
Brandon Millman
0500d2fb6e Remove old parse code 2018-06-01 10:37:44 -07:00
Brandon Millman
31f1a9e5aa Refactor order parser and add shared order support to new portal 2018-06-01 10:37:44 -07:00
Brandon Millman
6387aae471 Add generate and fill order routes 2018-06-01 10:37:44 -07:00
Fabio Berger
152082e182 Fix TODOs 2018-05-31 21:32:20 -07:00
Fabio Berger
08eb2b3df7 Update all artifacts 2018-05-31 21:32:13 -07:00
Fabio Berger
846ec87249 List V2 contracts in compile.json now 2018-05-31 21:28:58 -07:00
Fabio Berger
62690b5159 Fix sol-cov issue by changing it's dep to current version of types 2018-05-31 21:23:28 -07:00
Fabio Berger
719c432ca8 Rename ISigner to IWallet and implement SignatureType.Validator 2018-05-31 21:23:08 -07:00
Fabio Berger
e654616b6d Bump types to a major version to avoid the caret 2018-05-31 20:39:10 -07:00
Fabio Berger
f0473b0320 Fix metadata offsets 2018-05-31 16:12:56 -07:00
Fabio Berger
fcc627e6e1 fix method rename 2018-05-31 16:12:36 -07:00
Fabio Berger
fe17802cd2 Rename Ecrecover to EthSign 2018-05-31 16:12:21 -07:00
Leonid Logvinov
384c05ccc7 Merge pull request #642 from 0xProject/feature/ethereum-types
Introduce ethereum-types package
2018-05-31 14:33:28 -07:00
Leonid Logvinov
193e4f3275 Address feedback 2018-05-31 13:43:53 -07:00
Brandon Millman
6fd87568e7 Merge pull request #643 from 0xProject/feature/website/wallet-loading
Add loading states to wallet and provider display
2018-05-31 13:34:12 -07:00
Alex Browne
484fd68495 Merge pull request #647 from 0xProject/override-ethereumjs-tx-version
Override ethereumjs-tx version
2018-05-31 12:19:37 -07:00
Alex Browne
792be54443 Override ethereumjs-tx version 2018-05-31 12:05:13 -07:00
Brandon Millman
00df102c29 Fix missing key 2018-05-31 11:54:25 -07:00
Brandon Millman
90e68ddd73 Update placeholder param ordering 2018-05-31 11:54:25 -07:00
Brandon Millman
df27f4f118 Change userEtherBalanceInWei to optional so we can know if its loading 2018-05-31 11:54:25 -07:00
Brandon Millman
bee26daf0c Add loading state to ProviderDisplay 2018-05-31 11:54:25 -07:00
Brandon Millman
b76c738785 Tweaks 2018-05-31 11:54:25 -07:00
Brandon Millman
8ca9fb0251 Add Placeholder component 2018-05-31 11:54:25 -07:00
Brandon Millman
3b26a656f7 Add StandardIconRow 2018-05-31 11:54:25 -07:00
Brandon Millman
2f5ac5d993 Split render into loading and loaaded 2018-05-31 11:54:25 -07:00
Leonid Logvinov
a2fc9a964b Fix linter errors 2018-05-31 11:19:18 -07:00
Leonid Logvinov
b8a267370d Fix linter errors 2018-05-31 11:04:06 -07:00
Leonid Logvinov
fa3d011f68 Add ethereum-types to extraFileIncludes 2018-05-31 11:04:05 -07:00
Leonid Logvinov
a7fc9caacb Introduce ethereum-types package 2018-05-31 11:04:05 -07:00
Leonid Logvinov
c284f6dcd4 Merge pull request #624 from 0xProject/feature/fast-ci2
Rebalance CI tests to run faster
2018-05-31 11:02:56 -07:00
Fabio Berger
368d59c3ca Update artifacts 2018-05-31 11:02:45 -07:00
Fabio Berger
94ee82e076 Merge branch 'v2-prototype' into refactor/order-utils/for-v2
* v2-prototype: (45 commits)
  Check length before accessing indices, add awaitTransactionSuccess where needed, and rename function
  Add back before/after snapshots for each test
  Rename Signer to Wallet, rename GAS_ESTIMATE to GAS_LIMIT
  Make preSigned and allowedValidators mappings public
  Change names of signature types
  Fix formatting and tests
  Make AssetProxyId last byte of assetData
  Add signer to txHash, allow approveValidator to be used with executeTransaction
  Update Whitelist
  Fix Exchange interface
  Increase block gas limit
  Use last byte of signature as signature type
  Remove TxOrigin signature type, modify whitelist to use Validator signature type
  Update Whitelist contract with comments, also require maker to be whitelisted
  Fix build
  Add example whitelist contract and minimum tests
  Add sample whitelist contract
  Add TxOrigin signature type and rearrange order of types
  Add approveValidator function
  Add Validator signature type
  ...

# Conflicts:
#	packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
#	packages/contracts/src/utils/types.ts
#	packages/contracts/test/exchange/transactions.ts
#	packages/order-utils/src/asset_proxy_utils.ts
2018-05-31 10:45:34 -07:00
Leonid Logvinov
bfefb6e696 Remove merge conflicts from yarn.lock 2018-05-31 10:36:34 -07:00
Leonid Logvinov
95b7601e2b Don't wait con contract tests to submit coverage 2018-05-31 10:34:24 -07:00
Leonid Logvinov
f9c8bd868c Keep node versions consistent 2018-05-31 10:33:56 -07:00
Leonid Logvinov
a773973b1b Split tests into two buckets 2018-05-31 10:33:56 -07:00
Leonid Logvinov
a60006366b Use a newer version of node/yarn to speed-up deps instaation 2018-05-31 10:33:56 -07:00
Leonid Logvinov
a66bb7889a Try to cache dependencies 2018-05-31 10:32:43 -07:00
Leonid Logvinov
adfba06e85 Combine lint and pretttier tests together 2018-05-31 10:32:43 -07:00
Leonid Logvinov
6ee4e954f6 Rebalance tests 2018-05-31 10:32:43 -07:00
Leonid Logvinov
a11d139ff6 Merge pull request #641 from 0xProject/feature/remove-types
Remove types
2018-05-31 10:29:42 -07:00
Leonid Logvinov
85a3e66314 Add changelog entry for typescript-typings 2018-05-31 10:29:05 -07:00
Leonid Logvinov
1a3958ed60 Remove some types 2018-05-31 10:20:36 -07:00
Leonid Logvinov
743c957918 Remove published types 2018-05-31 10:20:35 -07:00
Amir Bandeali
224a6c192b Fix build 2018-05-31 10:19:10 -07:00
Alex Browne
ae47da3801 Merge pull request #640 from 0xProject/await-transaction-success
Add awaitTransactionSuccess where needed
2018-05-30 22:28:37 -07:00
Alex Browne
a6d669453f Pass in a provider and instantiate a new web3Wrapper in token_registry_wrapper 2018-05-30 22:27:07 -07:00
Fabio Berger
0beab9eec4 Expose isValidPresignedSignatureAsync method 2018-05-30 17:55:33 -07:00
Fabio Berger
aa997f1be5 Move isValidOrderHash to the order_hash_test file 2018-05-30 17:55:16 -07:00
Fabio Berger
4eb58a70bb Decide to throw for Caller signature type for now 2018-05-30 17:54:59 -07:00
Amir Bandeali
5b31d0aa36 Merge pull request #561 from 0xProject/feature/contracts/txorigin
Add Validator signature type
2018-05-30 17:53:22 -07:00
Amir Bandeali
79e7c44884 Check length before accessing indices, add awaitTransactionSuccess where needed, and rename function 2018-05-30 17:52:37 -07:00
Amir Bandeali
1382c1243a Add back before/after snapshots for each test 2018-05-30 17:11:31 -07:00
Amir Bandeali
8f2fd9b603 Rename Signer to Wallet, rename GAS_ESTIMATE to GAS_LIMIT 2018-05-30 17:11:31 -07:00
Amir Bandeali
d625b65a09 Make preSigned and allowedValidators mappings public 2018-05-30 17:11:31 -07:00
Amir Bandeali
101e9be7b9 Change names of signature types 2018-05-30 17:11:31 -07:00
Amir Bandeali
9f93d8f533 Fix formatting and tests 2018-05-30 17:11:31 -07:00
Amir Bandeali
6050a59e4a Make AssetProxyId last byte of assetData 2018-05-30 17:11:30 -07:00
Amir Bandeali
e5b7e29113 Add signer to txHash, allow approveValidator to be used with executeTransaction 2018-05-30 17:11:30 -07:00
Amir Bandeali
ecdd0ce9f2 Update Whitelist 2018-05-30 17:11:30 -07:00
Amir Bandeali
fc5c598f8f Fix Exchange interface 2018-05-30 17:11:30 -07:00
Amir Bandeali
18ebed3c5d Increase block gas limit 2018-05-30 17:11:30 -07:00
Amir Bandeali
822e319efe Use last byte of signature as signature type 2018-05-30 17:11:30 -07:00
Amir Bandeali
6d462fc961 Remove TxOrigin signature type, modify whitelist to use Validator signature type 2018-05-30 17:11:30 -07:00
Amir Bandeali
4b71c65aea Update Whitelist contract with comments, also require maker to be whitelisted 2018-05-30 17:11:30 -07:00
Amir Bandeali
34ab53173d Fix build 2018-05-30 17:11:30 -07:00
Amir Bandeali
d6be6f79ce Add example whitelist contract and minimum tests 2018-05-30 17:11:30 -07:00
Amir Bandeali
87d36f06fd Add sample whitelist contract 2018-05-30 17:11:30 -07:00
Amir Bandeali
3eb05b4505 Add TxOrigin signature type and rearrange order of types 2018-05-30 17:11:30 -07:00
Amir Bandeali
0789c6a3d8 Add approveValidator function 2018-05-30 17:11:30 -07:00
Amir Bandeali
b587f076fe Add Validator signature type 2018-05-30 17:11:30 -07:00
Amir Bandeali
a5a7217c8f Add deepCopyBytes method to LibBytes 2018-05-30 17:11:30 -07:00
Amir Bandeali
c0cf55b40b Merge pull request #639 from 0xProject/fix/contracts/multisigWrapper
Update LogDecoder
2018-05-30 17:10:39 -07:00
Fabio Berger
9200ed2216 Introduce OrderWithoutExchangeAddress type since this is what get's sent to the smart contracts 2018-05-30 14:45:20 -07:00
Fabio Berger
e1f7dd1372 Add ISigner artifacts 2018-05-30 14:08:58 -07:00
Fabio Berger
32833b7301 Fix order-utils tests 2018-05-30 14:08:43 -07:00
Fabio Berger
3302c89284 Revivie the ECSignatureSchema 2018-05-30 13:52:27 -07:00
Francesco Agosti
e18d61b31a Merge pull request #635 from 0xProject/feature/website/custom-onboarding-tooltip
Remove react-joyride and some more refactoring
2018-05-30 11:49:04 -07:00
Francesco Agosti
61cd1ae525 Merge pull request #638 from 0xProject/feature/website/onboarding-eth-flow
Onboarding: implement add ETH step, and stub for add WETH step
2018-05-30 11:17:38 -07:00
Alex Browne
064608a8ef Add awaitTransactionSuccess where needed 2018-05-30 11:10:30 -07:00
Amir Bandeali
5a840c88b5 Change logDecoder back into class, remove awaitTransactionMined from multiSigWrapper 2018-05-30 10:00:58 -07:00
fragosti
b14c3fe48d Onboarding: implement add ETH step, and stub for add WETH step 2018-05-29 17:57:22 -07:00
Fabio Berger
4874d55d03 Initial refactor of order-utils. Move many utils from contracts into this package. 2018-05-29 16:58:30 -07:00
Brandon Millman
b20e40dd6f Fix unselected relayer drawer item 2018-05-29 16:04:25 -07:00
fragosti
bc28a08dd0 Address PR feedback 2018-05-29 15:49:13 -07:00
fragosti
0d3010f6fc Remove react-joyride from deps 2018-05-29 15:27:30 -07:00
fragosti
399a651fa3 Add entry to CHANGELOG.json 2018-05-29 15:24:10 -07:00
fragosti
30ac5fcb5e Remove blacklist concept 2018-05-29 15:18:43 -07:00
fragosti
92cb5e10be Some cleanup 2018-05-29 14:26:38 -07:00
Fabio Berger
10faa47495 Freeze order-utils at 0.0.5 for all packages except contracts 2018-05-29 13:38:19 -07:00
fragosti
f0bbf2cab0 Improve tooltip look 2018-05-29 12:53:18 -07:00
fragosti
338e8be327 Add types for react-popper, remove types for react-joyride 2018-05-29 11:21:14 -07:00
fragosti
d4a366aeb1 Replace react-joyride with react-popper 2018-05-29 10:48:44 -07:00
Fabio Berger
dea322e2c5 Merge branch 'v2-prototype' into refactor/order-utils/for-v2
* v2-prototype:
  Hide wallet management option and expand component on small screens
  Remove registry override
  Revert "Change the registry in yarn.lock"
  Change the registry in yarn.lock
  Remove contracts -> @0xproject/order-utils dependency
2018-05-25 19:54:11 -07:00
Fabio Berger
790af0fd72 Merge branch 'v2-prototype' into refactor/order-utils/for-v2
* v2-prototype:
  Fix imports in order_utils
  Use web3-wrapper instead of 0x.js, update logDecoder
  Cleanup tests
  Add errMsg when throwing on unrecognized error
  Move readFirst4 to LibBytes
  Add old MultiSig to previous contracts, cleanup file structure
  Fix build
  Address feedback, rename contract to AssetProxyOwner
  Update multisig tests and utils
  Update MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress to use a mapping of registered proxies
  Implement design for relayers with no volume or tokens
2018-05-25 15:39:02 -07:00
fragosti
39008372e5 Write custom tooltip component 2018-05-25 15:31:27 -07:00
fragosti
1026952f26 Run linter 2018-05-25 13:13:06 -07:00
fragosti
9631927a8c Add localstorage helper 2018-05-25 12:03:18 -07:00
fragosti
b0e6ce581a Add next button 2018-05-25 12:03:18 -07:00
fragosti
e575323c60 Auto-show onboarding flow on first page view 2018-05-25 12:03:18 -07:00
fragosti
809ac3340c Add ability to blacklist onboarding steps 2018-05-25 12:03:18 -07:00
fragosti
f0af638874 Fix PortalOnboardingFlowProps 2018-05-25 12:03:18 -07:00
fragosti
b49148ec54 Implement metamask installation flow 2018-05-25 12:03:18 -07:00
Fabio Berger
4e5bfae332 Merge branch 'v2-prototype' into refactor/order-utils/for-v2
* v2-prototype:
  Temporarily disable installation tests
  Use domain separator for exchange address
  publicGetOrderSchemaHash -> getOrderSchemaHash
  Update order hash to match latest eip712
  Pin connect in sra-report
  Fix a typo
  Pin types in sra-report
  Fix linter issues
  Unpin types version in @0xproject/connect
  Pin types version in website
  Do a fake version bump on types so that yarn doesn't try to install updated version for not yet migrated packages
  Migrate migrations to v2
2018-05-24 16:31:21 -07:00
Fabio Berger
662dc12877 Add senderAddress to order schema 2018-05-24 16:05:07 -07:00
240 changed files with 8627 additions and 6848 deletions

View File

@@ -3,7 +3,7 @@ version: 2
jobs:
build:
docker:
- image: circleci/node:6.12
- image: circleci/node:9
environment:
CONTRACTS_COMMIT_HASH: '9ed05f5'
working_directory: ~/repo
@@ -11,91 +11,68 @@ jobs:
- checkout
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
name: Restore Yarn Package Cache
keys:
- yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
- yarn-packages-{{ .Branch }}
- yarn-packages-master
- yarn-packages-
- run:
name: yarn
command: yarn --frozen-lockfile
command: yarn --frozen-lockfile install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
name: Save Yarn Package Cache
key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:
- ./node_modules
- run: wget https://s3.amazonaws.com/testrpc-shapshots/${CONTRACTS_COMMIT_HASH}.zip
- run: unzip ${CONTRACTS_COMMIT_HASH}.zip -d testrpc_snapshot
- node_modules/
- run: node ./node_modules/lerna/bin/lerna.js bootstrap
- run: yarn build
- save_cache:
key: repo-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo
test-installation:
test-1:
docker:
- image: circleci/node:6.12
- image: circleci/node:9
working_directory: ~/repo
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn test:installation
test-0xjs:
docker:
- image: circleci/node:6.12
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:6.12
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-sol-compiler:
docker:
- image: circleci/node:6.12
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 @0xproject/contract-wrappers
- run: yarn wsrun test:circleci @0xproject/sol-compiler
- save_cache:
key: coverage-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/contract-wrappers/coverage/lcov.info
- save_cache:
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/sol-compiler/coverage/lcov.info
test-rest:
test-contracts:
docker:
- image: circleci/node:6.12
- 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 --exclude contracts --exclude 0x.js --exclude @0xproject/sol-compiler --stages --exclude-missing
- run: yarn wsrun test:circleci contracts
test-2:
docker:
- image: circleci/node:9
working_directory: ~/repo
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0xproject/assert
- run: yarn wsrun test:circleci @0xproject/connect
- run: yarn wsrun test:circleci @0xproject/dev-utils
- run: yarn wsrun test:circleci @0xproject/json-schemas
- run: yarn wsrun test:circleci @0xproject/subproviders
- run: yarn wsrun test:circleci @0xproject/sol-cov
- run: yarn wsrun test:circleci @0xproject/metacoin
- save_cache:
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
paths:
@@ -124,27 +101,19 @@ jobs:
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/metacoin/coverage/lcov.info
lint:
static-tests:
working_directory: ~/repo
docker:
- image: circleci/node:6.12
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn lerna:run lint
prettier:
working_directory: ~/repo
docker:
- image: circleci/node:6.12
- image: circleci/node:9
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn prettier:ci
- run: yarn lerna:run lint
submit-coverage:
docker:
- image: circleci/node:6.12
- image: circleci/node:9
working_directory: ~/repo
steps:
- restore_cache:
@@ -156,6 +125,9 @@ jobs:
- 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 }}
@@ -168,6 +140,9 @@ jobs:
- restore_cache:
keys:
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
@@ -183,29 +158,19 @@ workflows:
main:
jobs:
- build
# - test-installation:
# requires:
# - build
- test-0xjs:
- test-1:
requires:
- build
- test-2:
requires:
- build
- test-contracts:
requires:
- build
- test-sol-compiler:
requires:
- build
- test-rest:
requires:
- build
- prettier:
requires:
- build
- lint:
- static-tests:
requires:
- build
- submit-coverage:
requires:
- test-0xjs
- test-sol-compiler
- test-rest
- test-1
- test-2

1
.gitignore vendored
View File

@@ -86,6 +86,7 @@ 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/v1/contract_wrappers
packages/migrations/src/v2/contract_wrappers

View File

@@ -13,8 +13,9 @@
"prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}' --config .prettierrc",
"report_coverage": "lcov-result-merger 'packages/*/coverage/lcov.info' | coveralls",
"test:installation": "node ./packages/monorepo-scripts/lib/test_installation.js",
"run:publish": "run-s install:all rebuild script:publish",
"run:publish:dry": "run-s install:all rebuild script:publish:dry",
"run:publish": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild script:publish",
"run:publish:dry": "run-s install:all build:monorepo_scripts script:prepublish_checks rebuild script:publish:dry",
"script:prepublish_checks": "node ./packages/monorepo-scripts/lib/prepublish_checks.js",
"script:publish": "node ./packages/monorepo-scripts/lib/publish.js",
"script:publish:dry": "IS_DRY_RUN=true yarn script:publish",
"install:all": "yarn install",
@@ -22,11 +23,14 @@
"lerna:run": "lerna run",
"watch": "wsrun watch $PKG --fast-exit -r --stages --done-criteria='complete|successfully'",
"build": "wsrun build $PKG --fast-exit -r --stages",
"build:monorepo_scripts": "PKG=@0xproject/monorepo-scripts yarn build",
"clean": "wsrun clean $PKG --fast-exit -r --parallel",
"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"
"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/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"
},
"config": {
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
@@ -35,10 +39,13 @@
"async-child-process": "^1.1.1",
"coveralls": "^3.0.0",
"ganache-cli": "^6.1.0",
"lcov-result-merger": "^2.0.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"
},
"resolutions": {
"ethereumjs-tx": "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default"
}
}

View File

@@ -44,6 +44,7 @@
"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",
@@ -101,13 +102,14 @@
"@0xproject/assert": "^0.2.10",
"@0xproject/base-contract": "^0.3.2",
"@0xproject/contract-wrappers": "^0.0.2",
"@0xproject/order-utils": "^0.0.5",
"@0xproject/order-utils": "0.0.5",
"@0xproject/order-watcher": "^0.0.2",
"@0xproject/sol-compiler": "^0.5.0",
"@0xproject/types": "0.7.0",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",
"ethereum-types": "^0.0.1",
"ethers": "^3.0.15",
"lodash": "^4.17.4"
},

View File

@@ -11,7 +11,7 @@ before('migrate contracts', async function(): Promise<void> {
const mochaTestTimeoutMs = 20000;
this.timeout(mochaTestTimeoutMs);
const txDefaults = {
gas: devConstants.GAS_ESTIMATE,
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const artifactsDir = `../migrations/artifacts/1.0.0`;

View File

@@ -27,9 +27,9 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
"dependencies": {
"@0xproject/types": "^0.7.0",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"ethereum-types": "^0.0.1",
"chalk": "^2.3.0",
"glob": "^7.1.2",
"handlebars": "^4.0.11",

View File

@@ -1,8 +1,8 @@
#!/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';

View File

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

View File

@@ -1,4 +1,4 @@
import { AbiType, ConstructorAbi, DataItem } from '@0xproject/types';
import { AbiType, ConstructorAbi, DataItem } from 'ethereum-types';
import * as fs from 'fs';
import * as _ from 'lodash';
import * as path from 'path';

View File

@@ -42,7 +42,7 @@
"typescript": "2.7.1"
},
"dependencies": {
"@0xproject/types": "^0.7.0",
"ethereum-types": "^0.0.1",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",

View File

@@ -1,3 +1,5 @@
import { abiUtils, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import {
AbiDefinition,
AbiType,
@@ -8,9 +10,7 @@ import {
Provider,
TxData,
TxDataPayable,
} from '@0xproject/types';
import { abiUtils, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
} from 'ethereum-types';
import * as ethers from 'ethers';
import * as _ from 'lodash';

View File

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

View File

@@ -80,11 +80,12 @@
"@0xproject/base-contract": "^0.3.2",
"@0xproject/fill-scenarios": "^0.0.2",
"@0xproject/json-schemas": "0.7.22",
"@0xproject/order-utils": "^0.0.5",
"@0xproject/order-utils": "0.0.5",
"@0xproject/types": "0.7.0",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",
"ethereum-types": "^0.0.1",
"ethereumjs-blockstream": "^2.0.6",
"ethereumjs-util": "^5.1.1",
"ethers": "^3.0.15",

View File

@@ -11,7 +11,7 @@ before('migrate contracts', async function(): Promise<void> {
const mochaTestTimeoutMs = 20000;
this.timeout(mochaTestTimeoutMs);
const txDefaults = {
gas: devConstants.GAS_ESTIMATE,
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const artifactsDir = `../migrations/artifacts/1.0.0`;

View File

@@ -2,11 +2,11 @@
* This file is auto-generated using abi-gen. Don't edit directly.
* Templates can be found at https://github.com/0xProject/0x-monorepo/tree/development/packages/contract_templates.
*/
// tslint:disable:no-consecutive-blank-lines
// tslint:disable:no-consecutive-blank-lines ordered-imports
// tslint:disable-next-line:no-unused-variable
import { BaseContract } from '@0xproject/base-contract';
import { ContractArtifact } from '@0xproject/sol-compiler';
import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, MethodAbi, Provider, TxData, TxDataPayable } from '@0xproject/types';
import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, DecodedLogArgs, MethodAbi, Provider, TxData, TxDataPayable } from 'ethereum-types';
import { BigNumber, classUtils, logUtils, promisify } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as ethers from 'ethers';

View File

@@ -1,4 +1,4 @@
export interface {{name}}ContractEventArgs {
export interface {{name}}ContractEventArgs extends DecodedLogArgs {
{{#each inputs}}
{{name}}: {{#returnType type components}}{{/returnType}};
{{/each}}

View File

@@ -33,6 +33,7 @@
"TestLibs",
"TestSignatureValidator",
"TokenRegistry",
"Whitelist",
"WETH9",
"ZRXToken"
]

View File

@@ -29,7 +29,7 @@
"test:circleci": "yarn test"
},
"config": {
"abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock||TestAssetProxyDispatcher|TestLibBytes|TestLibs|TestSignatureValidator|TokenRegistry|WETH9|ZRXToken).json"
"abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibBytes|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json"
},
"repository": {
"type": "git",
@@ -48,7 +48,9 @@
"@0xproject/subproviders": "^0.10.1",
"@0xproject/sol-cov": "^0.0.11",
"@types/lodash": "4.14.104",
"@types/bn.js": "^4.11.0",
"@types/node": "^8.0.53",
"@types/ethereumjs-abi": "^0.6.0",
"@types/yargs": "^10.0.0",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
@@ -67,12 +69,13 @@
},
"dependencies": {
"@0xproject/base-contract": "^0.3.2",
"@0xproject/order-utils": "^0.0.5",
"@0xproject/order-utils": "^0.0.6",
"@0xproject/sol-compiler": "^0.5.0",
"@0xproject/types": "^0.7.0",
"@0xproject/types": "^1.0.0",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",
"ethereum-types": "^0.0.1",
"bn.js": "^4.11.8",
"ethereumjs-abi": "^0.6.4",
"ethereumjs-util": "^5.1.1",

View File

@@ -47,21 +47,25 @@ contract ERC20Proxy is
bytes memory assetMetadata,
address from,
address to,
uint256 amount)
uint256 amount
)
internal
{
// Data must be intended for this proxy.
uint256 length = assetMetadata.length;
require(
uint8(assetMetadata[0]) == PROXY_ID,
length == 21,
INVALID_METADATA_LENGTH
);
require(
uint8(assetMetadata[length - 1]) == PROXY_ID,
PROXY_ID_MISMATCH
);
// Decode metadata.
require(
assetMetadata.length == 21,
INVALID_METADATA_LENGTH
);
address token = readAddress(assetMetadata, 1);
address token = readAddress(assetMetadata, 0);
// Transfer tokens.
bool success = IERC20Token(token).transferFrom(from, to, amount);

View File

@@ -47,12 +47,20 @@ contract ERC721Proxy is
bytes memory assetMetadata,
address from,
address to,
uint256 amount)
uint256 amount
)
internal
{
// Data must be intended for this proxy.
uint256 length = assetMetadata.length;
require(
uint8(assetMetadata[0]) == PROXY_ID,
length == 53,
INVALID_METADATA_LENGTH
);
require(
uint8(assetMetadata[length - 1]) == PROXY_ID,
PROXY_ID_MISMATCH
);
@@ -63,12 +71,8 @@ contract ERC721Proxy is
);
// Decode metadata
require(
assetMetadata.length == 53,
INVALID_METADATA_LENGTH
);
address token = readAddress(assetMetadata, 1);
uint256 tokenId = readUint256(assetMetadata, 21);
address token = readAddress(assetMetadata, 0);
uint256 tokenId = readUint256(assetMetadata, 20);
// Transfer token.
// Either succeeds or throws.

View File

@@ -36,7 +36,8 @@ contract MixinAssetProxy is
bytes assetMetadata,
address from,
address to,
uint256 amount)
uint256 amount
)
external
onlyAuthorized
{
@@ -57,7 +58,8 @@ contract MixinAssetProxy is
bytes[] memory assetMetadata,
address[] memory from,
address[] memory to,
uint256[] memory amounts)
uint256[] memory amounts
)
public
onlyAuthorized
{

View File

@@ -87,7 +87,10 @@ contract MixinAuthorizable is
/// @dev Removes authorizion of an address.
/// @param target Address to remove authorization from.
/// @param index Index of target in authorities array.
function removeAuthorizedAddressAtIndex(address target, uint256 index)
function removeAuthorizedAddressAtIndex(
address target,
uint256 index
)
external
{
require(

View File

@@ -34,7 +34,8 @@ contract IAssetProxy is
bytes assetMetadata,
address from,
address to,
uint256 amount)
uint256 amount
)
external;
/// @dev Makes multiple transfers of assets. Either succeeds or throws.
@@ -46,7 +47,8 @@ contract IAssetProxy is
bytes[] memory assetMetadata,
address[] memory from,
address[] memory to,
uint256[] memory amounts)
uint256[] memory amounts
)
public;
/// @dev Gets the proxy id associated with the proxy address.

View File

@@ -45,6 +45,9 @@ contract IAuthorizable is
/// @dev Removes authorizion of an address.
/// @param target Address to remove authorization from.
/// @param index Index of target in authorities array.
function removeAuthorizedAddressAtIndex(address target, uint256 index)
function removeAuthorizedAddressAtIndex(
address target,
uint256 index
)
external;
}

View File

@@ -34,6 +34,7 @@ contract MAssetProxy is
bytes memory assetMetadata,
address from,
address to,
uint256 amount)
uint256 amount
)
internal;
}

View File

@@ -38,5 +38,5 @@ contract MAuthorizable is
);
/// @dev Only authorized addresses can invoke functions with this modifier.
modifier onlyAuthorized { _; }
modifier onlyAuthorized { revert(); _; }
}

View File

@@ -39,7 +39,8 @@ contract MixinAssetProxyDispatcher is
function registerAssetProxy(
uint8 assetProxyId,
address newAssetProxy,
address oldAssetProxy)
address oldAssetProxy
)
external
onlyOwner
{
@@ -86,17 +87,20 @@ contract MixinAssetProxyDispatcher is
bytes memory assetMetadata,
address from,
address to,
uint256 amount)
uint256 amount
)
internal
{
// Do nothing if no amount should be transferred.
if (amount > 0) {
// Lookup asset proxy
uint256 length = assetMetadata.length;
require(
assetMetadata.length >= 1,
length > 0,
GT_ZERO_LENGTH_REQUIRED
);
uint8 assetProxyId = uint8(assetMetadata[0]);
uint8 assetProxyId = uint8(assetMetadata[length - 1]);
IAssetProxy assetProxy = assetProxies[assetProxyId];
// transferFrom will either succeed or throw.

View File

@@ -19,18 +19,24 @@
pragma solidity ^0.4.24;
import "./mixins/MSignatureValidator.sol";
import "./interfaces/ISigner.sol";
import "./mixins/MTransactions.sol";
import "./interfaces/IWallet.sol";
import "./interfaces/IValidator.sol";
import "./libs/LibExchangeErrors.sol";
import "../../utils/LibBytes/LibBytes.sol";
contract MixinSignatureValidator is
LibBytes,
LibExchangeErrors,
MSignatureValidator
MSignatureValidator,
MTransactions
{
// Mapping of hash => signer => signed
mapping(bytes32 => mapping(address => bool)) preSigned;
mapping (bytes32 => mapping (address => bool)) public preSigned;
// Mapping of signer => validator => approved
mapping (address => mapping (address => bool)) public allowedValidators;
/// @dev Approves a hash on-chain using any valid signature type.
/// After presigning a hash, the preSign signature type will become valid for that hash and signer.
@@ -39,7 +45,8 @@ contract MixinSignatureValidator is
function preSign(
bytes32 hash,
address signer,
bytes signature)
bytes signature
)
external
{
require(
@@ -49,6 +56,19 @@ contract MixinSignatureValidator is
preSigned[hash][signer] = true;
}
/// @dev Approves/unnapproves a Validator contract to verify signatures on signer's behalf.
/// @param validator Address of Validator contract.
/// @param approval Approval or disapproval of Validator contract.
function setSignatureValidatorApproval(
address validator,
bool approval
)
external
{
address signer = getCurrentContextAddress();
allowedValidators[signer][validator] = approval;
}
/// @dev Verifies that a hash has been signed by the given signer.
/// @param hash Any 32 byte hash.
/// @param signer Address that should have signed the given hash.
@@ -57,71 +77,69 @@ contract MixinSignatureValidator is
function isValidSignature(
bytes32 hash,
address signer,
bytes memory signature)
bytes memory signature
)
internal
view
returns (bool isValid)
{
// TODO: Domain separation: make hash depend on role. (Taker sig should not be valid as maker sig, etc.)
require(
signature.length >= 1,
INVALID_SIGNATURE_LENGTH
);
SignatureType signatureType = SignatureType(uint8(signature[0]));
// Variables are not scoped in Solidity
// Pop last byte off of signature byte array.
SignatureType signatureType = SignatureType(uint8(popByte(signature)));
// Variables are not scoped in Solidity.
uint8 v;
bytes32 r;
bytes32 s;
address recovered;
// Always illegal signature
// Always illegal signature.
// This is always an implicit option since a signer can create a
// signature array with invalid type or length. We may as well make
// it an explicit option. This aids testing and analysis. It is
// also the initialization value for the enum type.
if (signatureType == SignatureType.Illegal) {
// NOTE: Reason cannot be assigned to a variable because of https://github.com/ethereum/solidity/issues/4051
revert("Illegal signature type.");
revert(ILLEGAL_SIGNATURE_TYPE);
// Always invalid signature
// Always invalid signature.
// Like Illegal, this is always implicitly available and therefore
// offered explicitly. It can be implicitly created by providing
// a correctly formatted but incorrect signature.
} else if (signatureType == SignatureType.Invalid) {
require(
signature.length == 1,
signature.length == 0,
INVALID_SIGNATURE_LENGTH
);
isValid = false;
return isValid;
// Implicitly signed by caller
// The signer has initiated the call. In the case of non-contract
// accounts it means the transaction itself was signed.
// Example: let's say for a particular operation three signatures
// A, B and C are required. To submit the transaction, A and B can
// give a signature to C, who can then submit the transaction using
// `Caller` for his own signature. Or A and C can sign and B can
// submit using `Caller`. Having `Caller` allows this flexibility.
} else if (signatureType == SignatureType.Caller) {
// Signature using EIP712
} else if (signatureType == SignatureType.EIP712) {
require(
signature.length == 1,
signature.length == 65,
INVALID_SIGNATURE_LENGTH
);
isValid = signer == msg.sender;
v = uint8(signature[0]);
r = readBytes32(signature, 1);
s = readBytes32(signature, 33);
recovered = ecrecover(hash, v, r, s);
isValid = signer == recovered;
return isValid;
// Signed using web3.eth_sign
} else if (signatureType == SignatureType.Ecrecover) {
} else if (signatureType == SignatureType.EthSign) {
require(
signature.length == 66,
signature.length == 65,
INVALID_SIGNATURE_LENGTH
);
v = uint8(signature[1]);
r = readBytes32(signature, 2);
s = readBytes32(signature, 34);
v = uint8(signature[0]);
r = readBytes32(signature, 1);
s = readBytes32(signature, 33);
recovered = ecrecover(
keccak256("\x19Ethereum Signed Message:\n32", hash),
v,
@@ -131,20 +149,55 @@ contract MixinSignatureValidator is
isValid = signer == recovered;
return isValid;
// Signature using EIP712
} else if (signatureType == SignatureType.EIP712) {
// Implicitly signed by caller.
// The signer has initiated the call. In the case of non-contract
// accounts it means the transaction itself was signed.
// Example: let's say for a particular operation three signatures
// A, B and C are required. To submit the transaction, A and B can
// give a signature to C, who can then submit the transaction using
// `Caller` for his own signature. Or A and C can sign and B can
// submit using `Caller`. Having `Caller` allows this flexibility.
} else if (signatureType == SignatureType.Caller) {
require(
signature.length == 66,
signature.length == 0,
INVALID_SIGNATURE_LENGTH
);
v = uint8(signature[1]);
r = readBytes32(signature, 2);
s = readBytes32(signature, 34);
recovered = ecrecover(hash, v, r, s);
isValid = signer == recovered;
isValid = signer == msg.sender;
return isValid;
// Signature from Trezor hardware wallet
// Signature verified by wallet contract.
// If used with an order, the maker of the order is the wallet contract.
} else if (signatureType == SignatureType.Wallet) {
isValid = IWallet(signer).isValidSignature(hash, signature);
return isValid;
// Signature verified by validator contract.
// If used with an order, the maker of the order can still be an EOA.
// A signature using this type should be encoded as:
// | Offset | Length | Contents |
// | 0x00 | x | Signature to validate |
// | 0x00 + x | 20 | Address of validator contract |
// | 0x14 + x | 1 | Signature type is always "\x06" |
} else if (signatureType == SignatureType.Validator) {
// Pop last 20 bytes off of signature byte array.
address validator = popAddress(signature);
// Ensure signer has approved validator.
if (!allowedValidators[signer][validator]) {
return false;
}
isValid = IValidator(validator).isValidSignature(
hash,
signer,
signature
);
return isValid;
// Signer signed hash previously using the preSign function.
} else if (signatureType == SignatureType.PreSigned) {
isValid = preSigned[hash][signer];
return isValid;
// Signature from Trezor hardware wallet.
// It differs from web3.eth_sign in the encoding of message length
// (Bitcoin varint encoding vs ascii-decimal, the latter is not
// self-terminating which leads to ambiguities).
@@ -154,12 +207,12 @@ contract MixinSignatureValidator is
// https://github.com/trezor/trezor-mcu/blob/master/firmware/crypto.c#L36
} else if (signatureType == SignatureType.Trezor) {
require(
signature.length == 66,
signature.length == 65,
INVALID_SIGNATURE_LENGTH
);
v = uint8(signature[1]);
r = readBytes32(signature, 2);
s = readBytes32(signature, 34);
v = uint8(signature[0]);
r = readBytes32(signature, 1);
s = readBytes32(signature, 33);
recovered = ecrecover(
keccak256("\x19Ethereum Signed Message:\n\x41", hash),
v,
@@ -169,11 +222,6 @@ contract MixinSignatureValidator is
isValid = signer == recovered;
return isValid;
// Signature verified by signer contract
} else if (signatureType == SignatureType.Contract) {
isValid = ISigner(signer).isValidSignature(hash, signature);
return isValid;
// Signer signed hash previously using the preSign function
} else if (signatureType == SignatureType.PreSigned) {
isValid = preSigned[hash][signer];
@@ -185,7 +233,6 @@ contract MixinSignatureValidator is
// that we currently support. In this case returning false
// may lead the caller to incorrectly believe that the
// signature was invalid.)
// NOTE: Reason cannot be assigned to a variable because of https://github.com/ethereum/solidity/issues/4051
revert("Unsupported signature type.");
revert(UNSUPPORTED_SIGNATURE_TYPE);
}
}

View File

@@ -43,15 +43,20 @@ contract MixinTransactions is
uint256 salt,
address signer,
bytes data,
bytes signature)
bytes signature
)
external
{
// Prevent reentrancy
require(currentContextAddress == address(0));
require(
currentContextAddress == address(0),
REENTRANCY_NOT_ALLOWED
);
// Calculate transaction hash
bytes32 transactionHash = keccak256(
address(this),
signer,
salt,
data
);

View File

@@ -20,17 +20,15 @@ pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "./IExchangeCore.sol";
import "./IMatchOrders";
import "./ISettlement";
import "./ISignatureValidator";
import "./ITransactions";
import "./IAssetProxyDispatcher";
import "./IWrapperFunctions";
import "./IMatchOrders.sol";
import "./ISignatureValidator.sol";
import "./ITransactions.sol";
import "./IAssetProxyDispatcher.sol";
import "./IWrapperFunctions.sol";
contract IExchange is
IExchangeCore,
IMatchOrders,
ISettlement,
ISignatureValidator,
ITransactions,
IAssetProxyDispatcher,

View File

@@ -27,6 +27,16 @@ contract ISignatureValidator {
function preSign(
bytes32 hash,
address signer,
bytes signature)
bytes signature
)
external;
/// @dev Approves/unnapproves a Validator contract to verify signatures on signer's behalf.
/// @param validator Address of Validator contract.
/// @param approval Approval or disapproval of Validator contract.
function setSignatureValidatorApproval(
address validator,
bool approval
)
external;
}

View File

@@ -0,0 +1,36 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.4.23;
contract IValidator {
/// @dev Verifies that a signature is valid.
/// @param hash Message hash that is signed.
/// @param signer Address that should have signed the given hash.
/// @param signature Proof of signing.
/// @return Validity of order signature.
function isValidSignature(
bytes32 hash,
address signer,
bytes signature
)
external
view
returns (bool isValid);
}

View File

@@ -18,7 +18,7 @@
pragma solidity ^0.4.24;
contract ISigner {
contract IWallet {
/// @dev Verifies that a signature is valid.
/// @param hash Message hash that is signed.
@@ -26,7 +26,8 @@ contract ISigner {
/// @return Validity of order signature.
function isValidSignature(
bytes32 hash,
bytes signature)
bytes signature
)
external
view
returns (bool isValid);

View File

@@ -19,27 +19,23 @@
pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "./libs/LibOrder.sol";
import "./libs/LibFillResults.sol";
import "../libs/LibOrder.sol";
import "../libs/LibFillResults.sol";
contract IWrapperFunctions is
LibBytes,
LibMath,
LibOrder,
LibFillResults,
LibExchangeErrors,
MExchangeCore
LibFillResults
{
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
/// @param order LibOrder.Order struct containing order specifications.
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
/// @param signature Proof that order has been created by maker.
function fillOrKillOrder(
LibOrder.LibOrder.Order memory order,
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
bytes memory signature)
public
returns (LibFillResults.LibFillResults.FillResults memory fillResults);
returns (LibFillResults.FillResults memory fillResults);
/// @dev Fills an order with specified parameters and ECDSA signature.
/// Returns false if the transaction would otherwise revert.

View File

@@ -32,6 +32,7 @@ contract LibExchangeErrors {
string constant INVALID_ORDER_MAKER_ASSET_AMOUNT = "Invalid order maker asset amount: expected a non-zero value.";
// Transaction revert reasons
string constant REENTRANCY_NOT_ALLOWED = "`executeTransaction` is not allowed to call itself recursively.";
string constant DUPLICATE_TRANSACTION_HASH = "Transaction has already been executed.";
string constant TRANSACTION_EXECUTION_FAILED = "Transaction execution failed.";

View File

@@ -41,6 +41,7 @@ contract MAssetProxyDispatcher is
bytes memory assetMetadata,
address from,
address to,
uint256 amount)
uint256 amount
)
internal;
}

View File

@@ -25,14 +25,15 @@ contract MSignatureValidator is
{
// Allowed signature types.
enum SignatureType {
Illegal, // Default value
Invalid,
Caller,
Ecrecover,
EIP712,
Trezor,
Contract,
PreSigned
Illegal, // 0x00, default value
Invalid, // 0x01
EIP712, // 0x02
EthSign, // 0x03
Caller, // 0x04
Wallet, // 0x05
Validator, // 0x06
PreSigned, // 0x07
Trezor // 0x08
}
/// @dev Verifies that a signature is valid.
@@ -43,7 +44,8 @@ contract MSignatureValidator is
function isValidSignature(
bytes32 hash,
address signer,
bytes memory signature)
bytes memory signature
)
internal
view
returns (bool isValid);

View File

@@ -25,6 +25,30 @@ contract TestLibBytes is
LibBytes
{
/// @dev Pops the last byte off of a byte array by modifying its length.
/// @param b Byte array that will be modified.
/// @return The byte that was popped off.
function publicPopByte(bytes memory b)
public
pure
returns (bytes memory, bytes1 result)
{
result = popByte(b);
return (b, result);
}
/// @dev Pops the last 20 bytes off of a byte array by modifying its length.
/// @param b Byte array that will be modified.
/// @return The 20 byte address that was popped off.
function publicPopAddress(bytes memory b)
public
pure
returns (bytes memory, address result)
{
result = popAddress(b);
return (b, result);
}
/// @dev Tests equality of two byte arrays.
/// @param lhs First byte array to compare.
/// @param rhs Second byte array to compare.

View File

@@ -20,13 +20,18 @@ pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/MixinSignatureValidator.sol";
import "../../protocol/Exchange/MixinTransactions.sol";
contract TestSignatureValidator is MixinSignatureValidator {
contract TestSignatureValidator is
MixinSignatureValidator,
MixinTransactions
{
function publicIsValidSignature(
bytes32 hash,
address signer,
bytes memory signature)
bytes memory signature
)
public
view
returns (bool isValid)

View File

@@ -0,0 +1,133 @@
/*
Copyright 2018 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.4.23;
pragma experimental ABIEncoderV2;
import "../../protocol/Exchange/interfaces/IExchange.sol";
import "../../protocol/Exchange/libs/LibOrder.sol";
import "../../utils/Ownable/Ownable.sol";
contract Whitelist is
Ownable
{
// Revert reasons
string constant MAKER_NOT_WHITELISTED = "Maker address not whitelisted.";
string constant TAKER_NOT_WHITELISTED = "Taker address not whitelisted.";
string constant INVALID_SENDER = "Sender must equal transaction origin.";
// Mapping of address => whitelist status.
mapping (address => bool) public isWhitelisted;
// Exchange contract.
IExchange EXCHANGE;
byte constant VALIDATOR_SIGNATURE_BYTE = "\x06";
bytes TX_ORIGIN_SIGNATURE;
constructor (address _exchange)
public
{
EXCHANGE = IExchange(_exchange);
TX_ORIGIN_SIGNATURE = abi.encodePacked(address(this), VALIDATOR_SIGNATURE_BYTE);
}
/// @dev Adds or removes an address from the whitelist.
/// @param target Address to add or remove from whitelist.
/// @param isApproved Whitelist status to assign to address.
function updateWhitelistStatus(
address target,
bool isApproved
)
external
onlyOwner
{
isWhitelisted[target] = isApproved;
}
/// @dev Fills an order using `msg.sender` as the taker.
/// The transaction will revert if both the maker and taker are not whitelisted.
/// Orders should specify this contract as the `senderAddress` in order to gaurantee
/// that both maker and taker have been whitelisted.
/// @param order Order struct containing order specifications.
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
/// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash.
/// @param orderSignature Proof that order has been created by maker.
function fillOrderIfWhitelisted(
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
uint256 salt,
bytes memory orderSignature
)
public
{
address takerAddress = msg.sender;
// This contract must be the entry point for the transaction.
require(
takerAddress == tx.origin,
INVALID_SENDER
);
// Check if maker is on the whitelist.
require(
isWhitelisted[order.makerAddress],
MAKER_NOT_WHITELISTED
);
// Check if taker is on the whitelist.
require(
isWhitelisted[takerAddress],
TAKER_NOT_WHITELISTED
);
// Encode arguments into byte array.
bytes memory data = abi.encodeWithSelector(
EXCHANGE.fillOrder.selector,
order,
takerAssetFillAmount,
orderSignature
);
// Call `fillOrder` via `executeTransaction`.
EXCHANGE.executeTransaction(
salt,
takerAddress,
data,
TX_ORIGIN_SIGNATURE
);
}
/// @dev Verifies signer is same as signer of current Ethereum transaction.
/// NOTE: This function can currently be used to validate signatures coming from outside of this contract.
/// Extra safety checks can be added for a production contract.
/// @param signer Address that should have signed the given hash.
/// @param signature Proof of signing.
/// @return Validity of order signature.
function isValidSignature(
bytes32 hash,
address signer,
bytes signature
)
external
view
returns (bool isValid)
{
return signer == tx.origin;
}
}

View File

@@ -21,15 +21,68 @@ pragma solidity ^0.4.24;
contract LibBytes {
// Revert reasons
string constant GT_ZERO_LENGTH_REQUIRED = "Length must be greater than 0.";
string constant GTE_4_LENGTH_REQUIRED = "Length must be greater than or equal to 4.";
string constant GTE_20_LENGTH_REQUIRED = "Length must be greater than or equal to 20.";
string constant GTE_32_LENGTH_REQUIRED = "Length must be greater than or equal to 32.";
string constant INDEX_OUT_OF_BOUNDS = "Specified array index is out of bounds.";
/// @dev Pops the last byte off of a byte array by modifying its length.
/// @param b Byte array that will be modified.
/// @return The byte that was popped off.
function popByte(bytes memory b)
internal
pure
returns (bytes1 result)
{
require(
b.length > 0,
GT_ZERO_LENGTH_REQUIRED
);
// Store last byte.
result = b[b.length - 1];
assembly {
// Decrement length of byte array.
let newLen := sub(mload(b), 1)
mstore(b, newLen)
}
return result;
}
/// @dev Pops the last 20 bytes off of a byte array by modifying its length.
/// @param b Byte array that will be modified.
/// @return The 20 byte address that was popped off.
function popAddress(bytes memory b)
internal
pure
returns (address result)
{
require(
b.length >= 20,
GTE_20_LENGTH_REQUIRED
);
// Store last 20 bytes.
result = readAddress(b, b.length - 20);
assembly {
// Subtract 20 from byte array length.
let newLen := sub(mload(b), 20)
mstore(b, newLen)
}
return result;
}
/// @dev Tests equality of two byte arrays.
/// @param lhs First byte array to compare.
/// @param rhs Second byte array to compare.
/// @return True if arrays are the same. False otherwise.
function areBytesEqual(bytes memory lhs, bytes memory rhs)
function areBytesEqual(
bytes memory lhs,
bytes memory rhs
)
internal
pure
returns (bool equal)
@@ -63,7 +116,8 @@ contract LibBytes {
/// @return address from byte array.
function readAddress(
bytes memory b,
uint256 index)
uint256 index
)
internal
pure
returns (address result)
@@ -95,7 +149,8 @@ contract LibBytes {
function writeAddress(
bytes memory b,
uint256 index,
address input)
address input
)
internal
pure
{
@@ -132,7 +187,8 @@ contract LibBytes {
/// @return bytes32 value from byte array.
function readBytes32(
bytes memory b,
uint256 index)
uint256 index
)
internal
pure
returns (bytes32 result)
@@ -159,7 +215,8 @@ contract LibBytes {
function writeBytes32(
bytes memory b,
uint256 index,
bytes32 input)
bytes32 input
)
internal
pure
{
@@ -183,7 +240,8 @@ contract LibBytes {
/// @return uint256 value from byte array.
function readUint256(
bytes memory b,
uint256 index)
uint256 index
)
internal
pure
returns (uint256 result)
@@ -198,7 +256,8 @@ contract LibBytes {
function writeUint256(
bytes memory b,
uint256 index,
uint256 input)
uint256 input
)
internal
pure
{

View File

@@ -1,6 +1,4 @@
import { generatePseudoRandomSalt } from '@0xproject/order-utils';
import { crypto } from './crypto';
import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils';
export const addressUtils = {
generatePseudoRandomAddress(): string {

View File

@@ -15,6 +15,7 @@ import * as TestLibs from '../artifacts/TestLibs.json';
import * as TestSignatureValidator from '../artifacts/TestSignatureValidator.json';
import * as TokenRegistry from '../artifacts/TokenRegistry.json';
import * as EtherToken from '../artifacts/WETH9.json';
import * as Whitelist from '../artifacts/Whitelist.json';
import * as ZRX from '../artifacts/ZRXToken.json';
export const artifacts = {
@@ -33,5 +34,6 @@ export const artifacts = {
TestLibs: (TestLibs as any) as ContractArtifact,
TestSignatureValidator: (TestSignatureValidator as any) as ContractArtifact,
TokenRegistry: (TokenRegistry as any) as ContractArtifact,
Whitelist: (Whitelist as any) as ContractArtifact,
ZRX: (ZRX as any) as ContractArtifact,
};

View File

@@ -28,6 +28,7 @@ export const constants = {
DUMMY_TOKEN_SYMBOL: '',
DUMMY_TOKEN_DECIMALS: new BigNumber(18),
DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(0),
NULL_BYTES: '0x',
NUM_DUMMY_ERC20_TO_DEPLOY: 3,
NUM_DUMMY_ERC721_TO_DEPLOY: 1,
NUM_ERC721_TOKENS_TO_MINT: 2,

View File

@@ -1,6 +1,6 @@
import { Provider } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
import { DummyERC20TokenContract } from '../contract_wrappers/generated/dummy_e_r_c20_token';
@@ -16,18 +16,19 @@ export class ERC20Wrapper {
private _contractOwnerAddress: string;
private _web3Wrapper: Web3Wrapper;
private _provider: Provider;
private _dummyTokenContracts?: DummyERC20TokenContract[];
private _dummyTokenContracts: DummyERC20TokenContract[];
private _proxyContract?: ERC20ProxyContract;
constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._dummyTokenContracts = [];
this._web3Wrapper = new Web3Wrapper(provider);
this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
}
public async deployDummyTokensAsync(): Promise<DummyERC20TokenContract[]> {
this._dummyTokenContracts = await Promise.all(
_.times(constants.NUM_DUMMY_ERC20_TO_DEPLOY, async () =>
DummyERC20TokenContract.deployFrom0xArtifactAsync(
for (let i = 0; i < constants.NUM_DUMMY_ERC20_TO_DEPLOY; i++) {
this._dummyTokenContracts.push(
await DummyERC20TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC20Token,
this._provider,
txDefaults,
@@ -36,8 +37,8 @@ export class ERC20Wrapper {
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
),
),
);
);
}
return this._dummyTokenContracts;
}
public async deployProxyAsync(): Promise<ERC20ProxyContract> {
@@ -51,44 +52,41 @@ export class ERC20Wrapper {
public async setBalancesAndAllowancesAsync(): Promise<void> {
this._validateDummyTokenContractsExistOrThrow();
this._validateProxyContractExistsOrThrow();
const setBalancePromises: Array<Promise<string>> = [];
const setAllowancePromises: Array<Promise<string>> = [];
_.forEach(this._dummyTokenContracts, dummyTokenContract => {
_.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
setBalancePromises.push(
dummyTokenContract.setBalance.sendTransactionAsync(
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
await this._web3Wrapper.awaitTransactionSuccessAsync(
await dummyTokenContract.setBalance.sendTransactionAsync(
tokenOwnerAddress,
constants.INITIAL_ERC20_BALANCE,
{ from: this._contractOwnerAddress },
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
setAllowancePromises.push(
dummyTokenContract.approve.sendTransactionAsync(
await this._web3Wrapper.awaitTransactionSuccessAsync(
await dummyTokenContract.approve.sendTransactionAsync(
(this._proxyContract as ERC20ProxyContract).address,
constants.INITIAL_ERC20_ALLOWANCE,
{ from: tokenOwnerAddress },
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
});
});
const txHashes = await Promise.all([...setBalancePromises, ...setAllowancePromises]);
await Promise.all(_.map(txHashes, async txHash => this._web3Wrapper.awaitTransactionSuccessAsync(txHash)));
}
}
}
public async getBalancesAsync(): Promise<ERC20BalancesByOwner> {
this._validateDummyTokenContractsExistOrThrow();
const balancesByOwner: ERC20BalancesByOwner = {};
const balancePromises: Array<Promise<BigNumber>> = [];
const balances: BigNumber[] = [];
const balanceInfo: Array<{ tokenOwnerAddress: string; tokenAddress: string }> = [];
_.forEach(this._dummyTokenContracts, dummyTokenContract => {
_.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
balancePromises.push(dummyTokenContract.balanceOf.callAsync(tokenOwnerAddress));
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
balances.push(await dummyTokenContract.balanceOf.callAsync(tokenOwnerAddress));
balanceInfo.push({
tokenOwnerAddress,
tokenAddress: dummyTokenContract.address,
});
});
});
const balances = await Promise.all(balancePromises);
}
}
_.forEach(balances, (balance, balanceIndex) => {
const tokenAddress = balanceInfo[balanceIndex].tokenAddress;
const tokenOwnerAddress = balanceInfo[balanceIndex].tokenOwnerAddress;

View File

@@ -1,7 +1,7 @@
import { generatePseudoRandomSalt } from '@0xproject/order-utils';
import { Provider } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
import { DummyERC721TokenContract } from '../contract_wrappers/generated/dummy_e_r_c721_token';
@@ -17,27 +17,28 @@ export class ERC721Wrapper {
private _contractOwnerAddress: string;
private _web3Wrapper: Web3Wrapper;
private _provider: Provider;
private _dummyTokenContracts?: DummyERC721TokenContract[];
private _dummyTokenContracts: DummyERC721TokenContract[];
private _proxyContract?: ERC721ProxyContract;
private _initialTokenIdsByOwner: ERC721TokenIdsByOwner = {};
constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
this._web3Wrapper = new Web3Wrapper(provider);
this._provider = provider;
this._dummyTokenContracts = [];
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
}
public async deployDummyTokensAsync(): Promise<DummyERC721TokenContract[]> {
this._dummyTokenContracts = await Promise.all(
_.times(constants.NUM_DUMMY_ERC721_TO_DEPLOY, async () =>
DummyERC721TokenContract.deployFrom0xArtifactAsync(
for (let i = 0; i < constants.NUM_DUMMY_ERC721_TO_DEPLOY; i++) {
this._dummyTokenContracts.push(
await DummyERC721TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyERC721Token,
this._provider,
txDefaults,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
),
),
);
);
}
return this._dummyTokenContracts;
}
public async deployProxyAsync(): Promise<ERC721ProxyContract> {
@@ -51,17 +52,16 @@ export class ERC721Wrapper {
public async setBalancesAndAllowancesAsync(): Promise<void> {
this._validateDummyTokenContractsExistOrThrow();
this._validateProxyContractExistsOrThrow();
const setBalancePromises: Array<Promise<string>> = [];
const setAllowancePromises: Array<Promise<string>> = [];
this._initialTokenIdsByOwner = {};
_.forEach(this._dummyTokenContracts, dummyTokenContract => {
_.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
_.forEach(_.range(constants.NUM_ERC721_TOKENS_TO_MINT), () => {
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
for (let i = 0; i < constants.NUM_ERC721_TOKENS_TO_MINT; i++) {
const tokenId = generatePseudoRandomSalt();
setBalancePromises.push(
dummyTokenContract.mint.sendTransactionAsync(tokenOwnerAddress, tokenId, {
await this._web3Wrapper.awaitTransactionSuccessAsync(
await dummyTokenContract.mint.sendTransactionAsync(tokenOwnerAddress, tokenId, {
from: this._contractOwnerAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
if (_.isUndefined(this._initialTokenIdsByOwner[tokenOwnerAddress])) {
this._initialTokenIdsByOwner[tokenOwnerAddress] = {
@@ -72,41 +72,39 @@ export class ERC721Wrapper {
this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address] = [];
}
this._initialTokenIdsByOwner[tokenOwnerAddress][dummyTokenContract.address].push(tokenId);
});
}
const shouldApprove = true;
setAllowancePromises.push(
dummyTokenContract.setApprovalForAll.sendTransactionAsync(
await this._web3Wrapper.awaitTransactionSuccessAsync(
await dummyTokenContract.setApprovalForAll.sendTransactionAsync(
(this._proxyContract as ERC721ProxyContract).address,
shouldApprove,
{ from: tokenOwnerAddress },
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
});
});
const txHashes = await Promise.all([...setBalancePromises, ...setAllowancePromises]);
await Promise.all(_.map(txHashes, async txHash => this._web3Wrapper.awaitTransactionSuccessAsync(txHash)));
}
}
}
public async getBalancesAsync(): Promise<ERC721TokenIdsByOwner> {
this._validateDummyTokenContractsExistOrThrow();
this._validateBalancesAndAllowancesSetOrThrow();
const tokenIdsByOwner: ERC721TokenIdsByOwner = {};
const tokenOwnerPromises: Array<Promise<string>> = [];
const tokenOwnerAddresses: string[] = [];
const tokenInfo: Array<{ tokenId: BigNumber; tokenAddress: string }> = [];
_.forEach(this._dummyTokenContracts, dummyTokenContract => {
_.forEach(this._tokenOwnerAddresses, tokenOwnerAddress => {
for (const dummyTokenContract of this._dummyTokenContracts) {
for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
const initialTokenOwnerIds = this._initialTokenIdsByOwner[tokenOwnerAddress][
dummyTokenContract.address
];
_.forEach(initialTokenOwnerIds, tokenId => {
tokenOwnerPromises.push(dummyTokenContract.ownerOf.callAsync(tokenId));
for (const tokenId of initialTokenOwnerIds) {
tokenOwnerAddresses.push(await dummyTokenContract.ownerOf.callAsync(tokenId));
tokenInfo.push({
tokenId,
tokenAddress: dummyTokenContract.address,
});
});
});
});
const tokenOwnerAddresses = await Promise.all(tokenOwnerPromises);
}
}
}
_.forEach(tokenOwnerAddresses, (tokenOwnerAddress, ownerIndex) => {
const tokenAddress = tokenInfo[ownerIndex].tokenAddress;
const tokenId = tokenInfo[ownerIndex].tokenId;

View File

@@ -1,22 +1,25 @@
import { Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { LogEntry, Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { ExchangeContract } from '../contract_wrappers/generated/exchange';
import { constants } from './constants';
import { formatters } from './formatters';
import { logDecoder } from './log_decoder';
import { LogDecoder } from './log_decoder';
import { orderUtils } from './order_utils';
import { AssetProxyId, OrderInfo, SignedTransaction } from './types';
import { OrderInfo, SignedTransaction } from './types';
export class ExchangeWrapper {
private _exchange: ExchangeContract;
private _web3Wrapper: Web3Wrapper;
private _logDecoder: LogDecoder;
constructor(exchangeContract: ExchangeContract, provider: Provider) {
this._exchange = exchangeContract;
this._web3Wrapper = new Web3Wrapper(provider);
this._logDecoder = new LogDecoder(this._web3Wrapper, this._exchange.address);
}
public async fillOrderAsync(
signedOrder: SignedOrder,
@@ -30,13 +33,13 @@ export class ExchangeWrapper {
params.signature,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async cancelOrderAsync(signedOrder: SignedOrder, from: string): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createCancel(signedOrder);
const txHash = await this._exchange.cancelOrder.sendTransactionAsync(params.order, { from });
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async fillOrKillOrderAsync(
@@ -51,7 +54,7 @@ export class ExchangeWrapper {
params.signature,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async fillOrderNoThrowAsync(
@@ -66,7 +69,7 @@ export class ExchangeWrapper {
params.signature,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async batchFillOrdersAsync(
@@ -81,7 +84,7 @@ export class ExchangeWrapper {
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async batchFillOrKillOrdersAsync(
@@ -96,7 +99,7 @@ export class ExchangeWrapper {
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async batchFillOrdersNoThrowAsync(
@@ -111,7 +114,7 @@ export class ExchangeWrapper {
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async marketSellOrdersAsync(
@@ -126,7 +129,7 @@ export class ExchangeWrapper {
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async marketSellOrdersNoThrowAsync(
@@ -141,7 +144,7 @@ export class ExchangeWrapper {
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async marketBuyOrdersAsync(
@@ -156,7 +159,7 @@ export class ExchangeWrapper {
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async marketBuyOrdersNoThrowAsync(
@@ -171,7 +174,7 @@ export class ExchangeWrapper {
params.signatures,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async batchCancelOrdersAsync(
@@ -180,12 +183,12 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchCancel(orders);
const txHash = await this._exchange.batchCancelOrders.sendTransactionAsync(params.orders, { from });
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async cancelOrdersUpToAsync(salt: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
const txHash = await this._exchange.cancelOrdersUpTo.sendTransactionAsync(salt, { from });
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async registerAssetProxyAsync(
@@ -203,7 +206,7 @@ export class ExchangeWrapper {
oldAssetProxyAddress,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async executeTransactionAsync(
@@ -217,7 +220,7 @@ export class ExchangeWrapper {
signedTx.signature,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
@@ -241,13 +244,7 @@ export class ExchangeWrapper {
params.rightSignature,
{ from },
);
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
return tx;
}
private async _getTxWithDecodedExchangeLogsAsync(txHash: string): Promise<TransactionReceiptWithDecodedLogs> {
const tx = await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
tx.logs = _.filter(tx.logs, log => log.address === this._exchange.address);
tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log));
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
}

View File

@@ -13,8 +13,8 @@ export const formatters = {
takerAssetFillAmounts,
};
_.forEach(signedOrders, signedOrder => {
const orderStruct = orderUtils.getOrderStruct(signedOrder);
batchFill.orders.push(orderStruct);
const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
batchFill.orders.push(orderWithoutExchangeAddress);
batchFill.signatures.push(signedOrder.signature);
if (takerAssetFillAmounts.length < signedOrders.length) {
batchFill.takerAssetFillAmounts.push(signedOrder.takerAssetAmount);
@@ -29,8 +29,8 @@ export const formatters = {
takerAssetFillAmount,
};
_.forEach(signedOrders, signedOrder => {
const orderStruct = orderUtils.getOrderStruct(signedOrder);
marketSellOrders.orders.push(orderStruct);
const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
marketSellOrders.orders.push(orderWithoutExchangeAddress);
marketSellOrders.signatures.push(signedOrder.signature);
});
return marketSellOrders;
@@ -42,8 +42,8 @@ export const formatters = {
makerAssetFillAmount,
};
_.forEach(signedOrders, signedOrder => {
const orderStruct = orderUtils.getOrderStruct(signedOrder);
marketBuyOrders.orders.push(orderStruct);
const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
marketBuyOrders.orders.push(orderWithoutExchangeAddress);
marketBuyOrders.signatures.push(signedOrder.signature);
});
return marketBuyOrders;
@@ -53,8 +53,8 @@ export const formatters = {
orders: [],
};
_.forEach(signedOrders, signedOrder => {
const orderStruct = orderUtils.getOrderStruct(signedOrder);
batchCancel.orders.push(orderStruct);
const orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
batchCancel.orders.push(orderWithoutExchangeAddress);
});
return batchCancel;
},

View File

@@ -1,19 +1,24 @@
import { ContractArtifact } from '@0xproject/sol-compiler';
import { AbiDefinition, LogEntry, LogWithDecodedArgs, RawLog } from '@0xproject/types';
import { AbiDecoder, BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import {
AbiDefinition,
DecodedLogArgs,
LogEntry,
LogWithDecodedArgs,
RawLog,
TransactionReceiptWithDecodedLogs,
} from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { constants } from './constants';
const abiArrays: AbiDefinition[][] = [];
_.forEach(artifacts, (artifact: ContractArtifact) => {
const compilerOutput = artifact.compilerOutput;
abiArrays.push(compilerOutput.abi);
});
const abiDecoder = new AbiDecoder(abiArrays);
export const logDecoder = {
wrapLogBigNumbers(log: any): any {
export class LogDecoder {
private _web3Wrapper: Web3Wrapper;
private _contractAddress: string;
private _abiDecoder: AbiDecoder;
public static wrapLogBigNumbers(log: any): any {
const argNames = _.keys(log.args);
for (const argName of argNames) {
const isWeb3BigNumber = _.startsWith(log.args[argName].constructor.toString(), 'function BigNumber(');
@@ -21,13 +26,29 @@ export const logDecoder = {
log.args[argName] = new BigNumber(log.args[argName]);
}
}
},
decodeLogOrThrow<ArgsType>(log: LogEntry): LogWithDecodedArgs<ArgsType> | RawLog {
const logWithDecodedArgsOrLog = abiDecoder.tryToDecodeLogOrNoop(log);
}
constructor(web3Wrapper: Web3Wrapper, contractAddress: string) {
this._web3Wrapper = web3Wrapper;
this._contractAddress = contractAddress;
const abiArrays: AbiDefinition[][] = [];
_.forEach(artifacts, (artifact: ContractArtifact) => {
const compilerOutput = artifact.compilerOutput;
abiArrays.push(compilerOutput.abi);
});
this._abiDecoder = new AbiDecoder(abiArrays);
}
public decodeLogOrThrow<ArgsType extends DecodedLogArgs>(log: LogEntry): LogWithDecodedArgs<ArgsType> | RawLog {
const logWithDecodedArgsOrLog = this._abiDecoder.tryToDecodeLogOrNoop(log);
if (_.isUndefined((logWithDecodedArgsOrLog as LogWithDecodedArgs<ArgsType>).args)) {
throw new Error(`Unable to decode log: ${JSON.stringify(log)}`);
}
logDecoder.wrapLogBigNumbers(logWithDecodedArgsOrLog);
LogDecoder.wrapLogBigNumbers(logWithDecodedArgsOrLog);
return logWithDecodedArgsOrLog;
},
};
}
public async getTxWithDecodedLogsAsync(txHash: string): Promise<TransactionReceiptWithDecodedLogs> {
const tx = await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
tx.logs = _.filter(tx.logs, log => log.address === this._contractAddress);
tx.logs = _.map(tx.logs, log => this.decodeLogOrThrow(log));
return tx;
}
}

View File

@@ -1,7 +1,9 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
import { assetProxyUtils, crypto, orderHashUtils } from '@0xproject/order-utils';
import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
@@ -14,17 +16,13 @@ import {
ExchangeContract,
FillContractEventArgs,
} from '../contract_wrappers/generated/exchange';
import { assetProxyUtils } from '../utils/asset_proxy_utils';
import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
import { crypto } from '../utils/crypto';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { OrderFactory } from '../utils/order_factory';
import { orderUtils } from '../utils/order_utils';
import {
AssetProxyId,
ContractName,
ERC20BalancesByOwner,
ERC721TokenIdsByOwner,
@@ -122,7 +120,7 @@ export class MatchOrderTester {
const feeRecipientAddressRight = signedOrderRight.feeRecipientAddress;
// Verify Left order preconditions
const orderTakerAssetFilledAmountLeft = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrderLeft),
orderHashUtils.getOrderHashHex(signedOrderLeft),
);
const expectedOrderFilledAmountLeft = initialTakerAssetFilledAmountLeft
? initialTakerAssetFilledAmountLeft
@@ -130,7 +128,7 @@ export class MatchOrderTester {
expect(expectedOrderFilledAmountLeft).to.be.bignumber.equal(orderTakerAssetFilledAmountLeft);
// Verify Right order preconditions
const orderTakerAssetFilledAmountRight = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrderRight),
orderHashUtils.getOrderHashHex(signedOrderRight),
);
const expectedOrderFilledAmountRight = initialTakerAssetFilledAmountRight
? initialTakerAssetFilledAmountRight
@@ -181,7 +179,7 @@ export class MatchOrderTester {
orderTakerAssetFilledAmountRight: BigNumber,
): Promise<TransferAmounts> {
let amountBoughtByLeftMaker = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrderLeft),
orderHashUtils.getOrderHashHex(signedOrderLeft),
);
amountBoughtByLeftMaker = amountBoughtByLeftMaker.minus(orderTakerAssetFilledAmountLeft);
const amountSoldByLeftMaker = amountBoughtByLeftMaker
@@ -192,7 +190,7 @@ export class MatchOrderTester {
.dividedToIntegerBy(signedOrderRight.makerAssetAmount);
const amountReceivedByTaker = amountSoldByLeftMaker.minus(amountReceivedByRightMaker);
let amountBoughtByRightMaker = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrderRight),
orderHashUtils.getOrderHashHex(signedOrderRight),
);
amountBoughtByRightMaker = amountBoughtByRightMaker.minus(orderTakerAssetFilledAmountRight);
const amountSoldByRightMaker = amountBoughtByRightMaker

View File

@@ -1,20 +1,22 @@
import { Provider, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { AssetProxyOwnerContract } from '../contract_wrappers/generated/asset_proxy_owner';
import { MultiSigWalletContract } from '../contract_wrappers/generated/multi_sig_wallet';
import { constants } from './constants';
import { logDecoder } from './log_decoder';
import { LogDecoder } from './log_decoder';
export class MultiSigWrapper {
private _multiSig: MultiSigWalletContract;
private _web3Wrapper: Web3Wrapper;
private _logDecoder: LogDecoder;
constructor(multiSigContract: MultiSigWalletContract, provider: Provider) {
this._multiSig = multiSigContract;
this._web3Wrapper = new Web3Wrapper(provider);
this._logDecoder = new LogDecoder(this._web3Wrapper, this._multiSig.address);
}
public async submitTransactionAsync(
destination: string,
@@ -26,17 +28,17 @@ export class MultiSigWrapper {
const txHash = await this._multiSig.submitTransaction.sendTransactionAsync(destination, value, data, {
from,
});
const tx = await this._getTxWithDecodedMultiSigLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async confirmTransactionAsync(txId: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
const txHash = await this._multiSig.confirmTransaction.sendTransactionAsync(txId, { from });
const tx = await this._getTxWithDecodedMultiSigLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async executeTransactionAsync(txId: BigNumber, from: string): Promise<TransactionReceiptWithDecodedLogs> {
const txHash = await this._multiSig.executeTransaction.sendTransactionAsync(txId, { from });
const tx = await this._getTxWithDecodedMultiSigLogsAsync(txHash);
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
public async executeRemoveAuthorizedAddressAsync(
@@ -45,13 +47,7 @@ export class MultiSigWrapper {
): Promise<TransactionReceiptWithDecodedLogs> {
const txHash = await (this
._multiSig as AssetProxyOwnerContract).executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from });
const tx = await this._getTxWithDecodedMultiSigLogsAsync(txHash);
return tx;
}
private async _getTxWithDecodedMultiSigLogsAsync(txHash: string): Promise<TransactionReceiptWithDecodedLogs> {
const tx = await this._web3Wrapper.awaitTransactionMinedAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
tx.logs = _.filter(tx.logs, log => log.address === this._multiSig.address);
tx.logs = _.map(tx.logs, log => logDecoder.decodeLogOrThrow(log));
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
}

View File

@@ -1,25 +1,24 @@
import { generatePseudoRandomSalt } from '@0xproject/order-utils';
import { SignedOrder, UnsignedOrder } from '@0xproject/types';
import { generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils';
import { Order, SignatureType, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { constants } from './constants';
import { orderUtils } from './order_utils';
import { signingUtils } from './signing_utils';
import { SignatureType } from './types';
export class OrderFactory {
private _defaultOrderParams: Partial<UnsignedOrder>;
private _defaultOrderParams: Partial<Order>;
private _privateKey: Buffer;
constructor(privateKey: Buffer, defaultOrderParams: Partial<UnsignedOrder>) {
constructor(privateKey: Buffer, defaultOrderParams: Partial<Order>) {
this._defaultOrderParams = defaultOrderParams;
this._privateKey = privateKey;
}
public newSignedOrder(
customOrderParams: Partial<UnsignedOrder> = {},
signatureType: SignatureType = SignatureType.Ecrecover,
customOrderParams: Partial<Order> = {},
signatureType: SignatureType = SignatureType.EthSign,
): SignedOrder {
const randomExpiration = new BigNumber(Math.floor((Date.now() + Math.random() * 100000000000) / 1000));
const tenMinutes = 10 * 60 * 1000;
const randomExpiration = new BigNumber(Date.now() + tenMinutes);
const order = ({
senderAddress: constants.NULL_ADDRESS,
expirationTimeSeconds: randomExpiration,
@@ -27,8 +26,8 @@ export class OrderFactory {
takerAddress: constants.NULL_ADDRESS,
...this._defaultOrderParams,
...customOrderParams,
} as any) as UnsignedOrder;
const orderHashBuff = orderUtils.getOrderHashBuff(order);
} as any) as Order;
const orderHashBuff = orderHashUtils.getOrderHashBuff(order);
const signature = signingUtils.signMessage(orderHashBuff, this._privateKey, signatureType);
const signedOrder = {
...order,

View File

@@ -1,14 +1,13 @@
import { Order, SignedOrder, UnsignedOrder } from '@0xproject/types';
import { Order, OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import ethUtil = require('ethereumjs-util');
import { crypto } from './crypto';
import { CancelOrder, MatchOrder } from './types';
export const orderUtils = {
createFill: (signedOrder: SignedOrder, takerAssetFillAmount?: BigNumber) => {
const fill = {
order: orderUtils.getOrderStruct(signedOrder),
order: orderUtils.getOrderWithoutExchangeAddress(signedOrder),
takerAssetFillAmount: takerAssetFillAmount || signedOrder.takerAssetAmount,
signature: signedOrder.signature,
};
@@ -16,12 +15,12 @@ export const orderUtils = {
},
createCancel(signedOrder: SignedOrder, takerAssetCancelAmount?: BigNumber): CancelOrder {
const cancel = {
order: orderUtils.getOrderStruct(signedOrder),
order: orderUtils.getOrderWithoutExchangeAddress(signedOrder),
takerAssetCancelAmount: takerAssetCancelAmount || signedOrder.takerAssetAmount,
};
return cancel;
},
getOrderStruct(signedOrder: SignedOrder): Order {
getOrderWithoutExchangeAddress(signedOrder: SignedOrder): OrderWithoutExchangeAddress {
const orderStruct = {
senderAddress: signedOrder.senderAddress,
makerAddress: signedOrder.makerAddress,
@@ -38,75 +37,10 @@ export const orderUtils = {
};
return orderStruct;
},
getDomainSeparatorSchemaHex(): string {
const domainSeparatorSchemaHashBuff = crypto.solSHA3(['DomainSeparator(address contract)']);
const schemaHashHex = `0x${domainSeparatorSchemaHashBuff.toString('hex')}`;
return schemaHashHex;
},
getDomainSeparatorHashHex(exchangeAddress: string): string {
const domainSeparatorHashBuff = crypto.solSHA3([exchangeAddress]);
const domainSeparatorHashHex = `0x${domainSeparatorHashBuff.toString('hex')}`;
return domainSeparatorHashHex;
},
getOrderSchemaHex(): string {
const orderSchemaHashBuff = crypto.solSHA3([
'Order(',
'address makerAddress,',
'address takerAddress,',
'address feeRecipientAddress,',
'address senderAddress,',
'uint256 makerAssetAmount,',
'uint256 takerAssetAmount,',
'uint256 makerFee,',
'uint256 takerFee,',
'uint256 expirationTimeSeconds,',
'uint256 salt,',
'bytes makerAssetData,',
'bytes takerAssetData,',
')',
]);
const schemaHashHex = `0x${orderSchemaHashBuff.toString('hex')}`;
return schemaHashHex;
},
getOrderHashBuff(order: SignedOrder | UnsignedOrder): Buffer {
const makerAssetDataHash = crypto.solSHA3([ethUtil.toBuffer(order.makerAssetData)]);
const takerAssetDataHash = crypto.solSHA3([ethUtil.toBuffer(order.takerAssetData)]);
const orderParamsHashBuff = crypto.solSHA3([
order.makerAddress,
order.takerAddress,
order.feeRecipientAddress,
order.senderAddress,
order.makerAssetAmount,
order.takerAssetAmount,
order.makerFee,
order.takerFee,
order.expirationTimeSeconds,
order.salt,
makerAssetDataHash,
takerAssetDataHash,
]);
const orderParamsHashHex = `0x${orderParamsHashBuff.toString('hex')}`;
const orderSchemaHashHex = orderUtils.getOrderSchemaHex();
const domainSeparatorHashHex = this.getDomainSeparatorHashHex(order.exchangeAddress);
const domainSeparatorSchemaHex = this.getDomainSeparatorSchemaHex();
const orderHashBuff = crypto.solSHA3([
new BigNumber(domainSeparatorSchemaHex),
new BigNumber(domainSeparatorHashHex),
new BigNumber(orderSchemaHashHex),
new BigNumber(orderParamsHashHex),
]);
return orderHashBuff;
},
getOrderHashHex(order: SignedOrder | UnsignedOrder): string {
const orderHashBuff = orderUtils.getOrderHashBuff(order);
const orderHashHex = `0x${orderHashBuff.toString('hex')}`;
return orderHashHex;
},
createMatchOrders(signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder): MatchOrder {
const fill = {
left: orderUtils.getOrderStruct(signedOrderLeft),
right: orderUtils.getOrderStruct(signedOrderRight),
left: orderUtils.getOrderWithoutExchangeAddress(signedOrderLeft),
right: orderUtils.getOrderWithoutExchangeAddress(signedOrderRight),
leftSignature: signedOrderLeft.signature,
rightSignature: signedOrderRight.signature,
};

View File

@@ -1,26 +1,25 @@
import { SignatureType } from '@0xproject/types';
import * as ethUtil from 'ethereumjs-util';
import { SignatureType } from './types';
export const signingUtils = {
signMessage(message: Buffer, privateKey: Buffer, signatureType: SignatureType): Buffer {
if (signatureType === SignatureType.Ecrecover) {
if (signatureType === SignatureType.EthSign) {
const prefixedMessage = ethUtil.hashPersonalMessage(message);
const ecSignature = ethUtil.ecsign(prefixedMessage, privateKey);
const signature = Buffer.concat([
ethUtil.toBuffer(signatureType),
ethUtil.toBuffer(ecSignature.v),
ecSignature.r,
ecSignature.s,
ethUtil.toBuffer(signatureType),
]);
return signature;
} else if (signatureType === SignatureType.EIP712) {
const ecSignature = ethUtil.ecsign(message, privateKey);
const signature = Buffer.concat([
ethUtil.toBuffer(signatureType),
ethUtil.toBuffer(ecSignature.v),
ecSignature.r,
ecSignature.s,
ethUtil.toBuffer(signatureType),
]);
return signature;
} else {

View File

@@ -1,16 +1,21 @@
import * as Web3 from 'web3';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import { TokenRegistryContract } from '../contract_wrappers/generated/token_registry';
import { Token } from './types';
import { constants } from './constants';
export class TokenRegWrapper {
private _tokenReg: TokenRegistryContract;
constructor(tokenRegContract: TokenRegistryContract) {
private _web3Wrapper: Web3Wrapper;
constructor(tokenRegContract: TokenRegistryContract, provider: Provider) {
this._tokenReg = tokenRegContract;
this._web3Wrapper = new Web3Wrapper(provider);
}
public async addTokenAsync(token: Token, from: string): Promise<string> {
const tx = this._tokenReg.addToken.sendTransactionAsync(
const txHash = await this._tokenReg.addToken.sendTransactionAsync(
token.address as string,
token.name,
token.symbol,
@@ -19,7 +24,8 @@ export class TokenRegWrapper {
token.swarmHash,
{ from },
);
return tx;
await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
return txHash;
}
public async getTokenMetaDataAsync(tokenAddress: string): Promise<Token> {
const data = await this._tokenReg.getTokenMetaData.callAsync(tokenAddress);

View File

@@ -1,32 +1,28 @@
import { generatePseudoRandomSalt } from '@0xproject/order-utils';
import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { SignatureType } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as ethUtil from 'ethereumjs-util';
import { crypto } from './crypto';
import { signingUtils } from './signing_utils';
import { SignatureType, SignedTransaction } from './types';
import { SignedTransaction } from './types';
export class TransactionFactory {
private _signer: string;
private _signerBuff: Buffer;
private _exchangeAddress: string;
private _privateKey: Buffer;
constructor(privateKey: Buffer, exchangeAddress: string) {
this._privateKey = privateKey;
this._exchangeAddress = exchangeAddress;
const signerBuff = ethUtil.privateToAddress(this._privateKey);
this._signer = `0x${signerBuff.toString('hex')}`;
this._signerBuff = ethUtil.privateToAddress(this._privateKey);
}
public newSignedTransaction(
data: string,
signatureType: SignatureType = SignatureType.Ecrecover,
): SignedTransaction {
public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction {
const salt = generatePseudoRandomSalt();
const txHash = crypto.solSHA3([this._exchangeAddress, salt, ethUtil.toBuffer(data)]);
const txHash = crypto.solSHA3([this._exchangeAddress, this._signerBuff, salt, ethUtil.toBuffer(data)]);
const signature = signingUtils.signMessage(txHash, this._privateKey, signatureType);
const signedTx = {
exchangeAddress: this._exchangeAddress,
salt,
signer: this._signer,
signer: `0x${this._signerBuff.toString('hex')}`,
data,
signature: `0x${signature.toString('hex')}`,
};

View File

@@ -1,5 +1,6 @@
import { AbiDefinition, ContractAbi, Order } from '@0xproject/types';
import { Order, OrderWithoutExchangeAddress } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { AbiDefinition, ContractAbi } from 'ethereum-types';
export interface ERC20BalancesByOwner {
[ownerAddress: string]: {
@@ -18,37 +19,31 @@ export interface SubmissionContractEventArgs {
}
export interface BatchFillOrders {
orders: Order[];
orders: OrderWithoutExchangeAddress[];
signatures: string[];
takerAssetFillAmounts: BigNumber[];
}
export interface MarketSellOrders {
orders: Order[];
orders: OrderWithoutExchangeAddress[];
signatures: string[];
takerAssetFillAmount: BigNumber;
}
export interface MarketBuyOrders {
orders: Order[];
orders: OrderWithoutExchangeAddress[];
signatures: string[];
makerAssetFillAmount: BigNumber;
}
export interface BatchCancelOrders {
orders: Order[];
orders: OrderWithoutExchangeAddress[];
}
export interface CancelOrdersBefore {
salt: BigNumber;
}
export enum AssetProxyId {
INVALID,
ERC20,
ERC721,
}
export interface TransactionDataParams {
name: string;
abi: AbiDefinition[];
@@ -111,16 +106,7 @@ export enum ContractName {
DummyERC721Token = 'DummyERC721Token',
TestLibBytes = 'TestLibBytes',
Authorizable = 'Authorizable',
}
export enum SignatureType {
Illegal,
Invalid,
Caller,
Ecrecover,
EIP712,
Trezor,
Contract,
Whitelist = 'Whitelist',
}
export interface SignedTransaction {
@@ -158,31 +144,14 @@ export interface OrderInfo {
orderTakerAssetFilledAmount: BigNumber;
}
export interface ERC20ProxyData {
assetProxyId: AssetProxyId;
tokenAddress: string;
}
export interface ERC721ProxyData {
assetProxyId: AssetProxyId;
tokenAddress: string;
tokenId: BigNumber;
}
export interface ProxyData {
assetProxyId: AssetProxyId;
tokenAddress?: string;
data?: any;
}
export interface CancelOrder {
order: Order;
order: OrderWithoutExchangeAddress;
takerAssetCancelAmount: BigNumber;
}
export interface MatchOrder {
left: Order;
right: Order;
left: OrderWithoutExchangeAddress;
right: OrderWithoutExchangeAddress;
leftSignature: string;
rightSignature: string;
}

View File

@@ -1,13 +1,13 @@
import { devConstants, env, EnvVars, web3Factory } from '@0xproject/dev-utils';
import { prependSubprovider } from '@0xproject/subproviders';
import { Provider } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import { coverage } from './coverage';
export const txDefaults = {
from: devConstants.TESTRPC_FIRST_ADDRESS,
gas: devConstants.GAS_ESTIMATE,
gas: devConstants.GAS_LIMIT,
};
const providerConfigs = { shouldUseInProcessGanache: true };
export const provider = web3Factory.getRpcProvider(providerConfigs);

View File

@@ -1,4 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
@@ -8,12 +10,10 @@ import { DummyERC20TokenContract } from '../../src/contract_wrappers/generated/d
import { DummyERC721TokenContract } from '../../src/contract_wrappers/generated/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../../src/contract_wrappers/generated/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/contract_wrappers/generated/e_r_c721_proxy';
import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { AssetProxyId } from '../../src/utils/types';
import { provider, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();

View File

@@ -1,7 +1,7 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { LogWithDecodedArgs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import 'make-promises-safe';
import * as Web3 from 'web3';
@@ -35,6 +35,12 @@ describe('AssetProxyOwner', () => {
let multiSig: AssetProxyOwnerContract;
let multiSigWrapper: MultiSigWrapper;
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
owners = [accounts[0], accounts[1]];
@@ -60,8 +66,14 @@ describe('AssetProxyOwner', () => {
SECONDS_TIME_LOCKED,
);
multiSigWrapper = new MultiSigWrapper(multiSig, provider);
await erc20Proxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: initialOwner });
await erc721Proxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: initialOwner });
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: initialOwner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: initialOwner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();

View File

@@ -83,7 +83,10 @@ describe('EtherToken', () => {
it('should convert ether tokens to ether with sufficient balance', async () => {
const ethToDeposit = new BigNumber(Web3Wrapper.toWei(new BigNumber(1)));
await etherToken.deposit.sendTransactionAsync({ value: ethToDeposit });
await web3Wrapper.awaitTransactionSuccessAsync(
await etherToken.deposit.sendTransactionAsync({ value: ethToDeposit }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
const initEthTokenBalance = await etherToken.balanceOf.callAsync(account);
const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
const ethTokensToWithdraw = initEthTokenBalance;

View File

@@ -1,8 +1,10 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
import { assetProxyUtils, crypto, orderHashUtils } from '@0xproject/order-utils';
import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util');
import 'make-promises-safe';
@@ -17,16 +19,13 @@ import {
FillContractEventArgs,
} from '../../src/contract_wrappers/generated/exchange';
import { artifacts } from '../../src/utils/artifacts';
import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { crypto } from '../../src/utils/crypto';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils';
import { AssetProxyId, ContractName, ERC20BalancesByOwner, ExchangeStatus } from '../../src/utils/types';
import { ContractName, ERC20BalancesByOwner, ExchangeStatus } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
@@ -127,7 +126,6 @@ describe('Exchange core', () => {
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('fillOrder', () => {
beforeEach(async () => {
erc20Balances = await erc20Wrapper.getBalancesAsync();
@@ -141,7 +139,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -151,7 +149,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountAfter1 = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountAfter1).to.be.bignumber.equal(fillTakerAssetAmount1);
@@ -161,7 +159,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountAfter2 = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountAfter2).to.be.bignumber.equal(takerAssetFilledAmountAfter1);
});
@@ -173,7 +171,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -181,7 +179,7 @@ describe('Exchange core', () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
@@ -226,7 +224,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -234,7 +232,7 @@ describe('Exchange core', () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
@@ -279,7 +277,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -287,7 +285,7 @@ describe('Exchange core', () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(takerAssetFillAmount);
@@ -333,7 +331,7 @@ describe('Exchange core', () => {
});
const takerAssetFilledAmountBefore = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
expect(takerAssetFilledAmountBefore).to.be.bignumber.equal(0);
@@ -341,7 +339,7 @@ describe('Exchange core', () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const makerAmountBoughtAfter = await exchangeWrapper.getTakerAssetFilledAmountAsync(
orderUtils.getOrderHashHex(signedOrder),
orderHashUtils.getOrderHashHex(signedOrder),
);
const expectedMakerAmountBoughtAfter = takerAssetFillAmount.add(takerAssetFilledAmountBefore);
expect(makerAmountBoughtAfter).to.be.bignumber.equal(expectedMakerAmountBoughtAfter);
@@ -441,7 +439,7 @@ describe('Exchange core', () => {
expect(expectedFilledTakerAssetAmount).to.be.bignumber.equal(logArgs.takerAssetFilledAmount);
expect(expectedFeeMPaid).to.be.bignumber.equal(logArgs.makerFeePaid);
expect(expectedFeeTPaid).to.be.bignumber.equal(logArgs.takerFeePaid);
expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
});
it('should throw when taker is specified and order is claimed by other', async () => {
@@ -460,10 +458,11 @@ describe('Exchange core', () => {
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
});
const v = ethUtil.toBuffer(signedOrder.signature.slice(0, 4));
const invalidR = ethUtil.sha3('invalidR');
const invalidS = ethUtil.sha3('invalidS');
const signatureTypeAndV = signedOrder.signature.slice(0, 6);
const invalidSigBuff = Buffer.concat([ethUtil.toBuffer(signatureTypeAndV), invalidR, invalidS]);
const signatureType = ethUtil.toBuffer(`0x${signedOrder.signature.slice(-2)}`);
const invalidSigBuff = Buffer.concat([v, invalidR, invalidS, signatureType]);
const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`;
signedOrder.signature = invalidSigHex;
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(
@@ -534,12 +533,6 @@ describe('Exchange core', () => {
await expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(
constants.REVERT,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, {
from: makerAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
});
it('should throw if taker allowances are too low to fill order', async () => {
@@ -555,12 +548,6 @@ describe('Exchange core', () => {
await expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(
constants.REVERT,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, constants.INITIAL_ERC20_ALLOWANCE, {
from: takerAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
});
it('should not change erc20Balances if an order is expired', async () => {
@@ -651,7 +638,7 @@ describe('Exchange core', () => {
expect(signedOrder.feeRecipientAddress).to.be.equal(logArgs.feeRecipientAddress);
expect(signedOrder.makerAssetData).to.be.equal(logArgs.makerAssetData);
expect(signedOrder.takerAssetData).to.be.equal(logArgs.takerAssetData);
expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
});
it('should log an error if already cancelled', async () => {

View File

@@ -1,4 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as Web3 from 'web3';
@@ -8,12 +10,10 @@ import { ERC20ProxyContract } from '../../src/contract_wrappers/generated/e_r_c2
import { ERC721ProxyContract } from '../../src/contract_wrappers/generated/e_r_c721_proxy';
import { TestAssetProxyDispatcherContract } from '../../src/contract_wrappers/generated/test_asset_proxy_dispatcher';
import { artifacts } from '../../src/utils/artifacts';
import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { AssetProxyId } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();

View File

@@ -1,4 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -7,11 +8,9 @@ import ethUtil = require('ethereumjs-util');
import { TestLibsContract } from '../../src/contract_wrappers/generated/test_libs';
import { addressUtils } from '../../src/utils/address_utils';
import { artifacts } from '../../src/utils/artifacts';
import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
@@ -49,7 +48,6 @@ describe('Exchange libs', () => {
beforeEach(async () => {
await blockchainLifecycle.startAsync();
signedOrder = orderFactory.newSignedOrder();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
@@ -59,19 +57,20 @@ describe('Exchange libs', () => {
describe('getOrderSchema', () => {
it('should output the correct order schema hash', async () => {
const orderSchema = await libs.getOrderSchemaHash.callAsync();
expect(orderUtils.getOrderSchemaHex()).to.be.equal(orderSchema);
expect(orderHashUtils._getOrderSchemaHex()).to.be.equal(orderSchema);
});
});
describe('getDomainSeparatorSchema', () => {
it('should output the correct domain separator schema hash', async () => {
const domainSeparatorSchema = await libs.getDomainSeparatorSchemaHash.callAsync();
expect(orderUtils.getDomainSeparatorSchemaHex()).to.be.equal(domainSeparatorSchema);
expect(orderHashUtils._getDomainSeparatorSchemaHex()).to.be.equal(domainSeparatorSchema);
});
});
describe('getOrderHash', () => {
it('should output the correct order hash', async () => {
it('should output the correct orderHash', async () => {
signedOrder = orderFactory.newSignedOrder();
const orderHashHex = await libs.publicGetOrderHash.callAsync(signedOrder);
expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
});
});
});

View File

@@ -1,8 +1,10 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { LogWithDecodedArgs, SignedOrder } from '@0xproject/types';
import { assetProxyUtils, crypto } from '@0xproject/order-utils';
import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
@@ -17,17 +19,14 @@ import {
FillContractEventArgs,
} from '../../src/contract_wrappers/generated/exchange';
import { artifacts } from '../../src/utils/artifacts';
import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { crypto } from '../../src/utils/crypto';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { MatchOrderTester } from '../../src/utils/match_order_tester';
import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils';
import {
AssetProxyId,
ContractName,
ERC20BalancesByOwner,
ERC721TokenIdsByOwner,
@@ -36,8 +35,6 @@ import {
} from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
import { MatchOrderTester } from '../../src/utils/match_order_tester';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);

View File

@@ -1,4 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -7,11 +8,9 @@ import ethUtil = require('ethereumjs-util');
import { TestSignatureValidatorContract } from '../../src/contract_wrappers/generated/test_signature_validator';
import { addressUtils } from '../../src/utils/address_utils';
import { artifacts } from '../../src/utils/artifacts';
import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
@@ -53,7 +52,6 @@ describe('MixinSignatureValidator', () => {
beforeEach(async () => {
await blockchainLifecycle.startAsync();
signedOrder = orderFactory.newSignedOrder();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
@@ -65,7 +63,7 @@ describe('MixinSignatureValidator', () => {
});
it('should return true with a valid signature', async () => {
const orderHashHex = orderUtils.getOrderHashHex(signedOrder);
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync(
orderHashHex,
signedOrder.makerAddress,
@@ -75,16 +73,14 @@ describe('MixinSignatureValidator', () => {
});
it('should return false with an invalid signature', async () => {
const v = ethUtil.toBuffer(signedOrder.signature.slice(0, 4));
const invalidR = ethUtil.sha3('invalidR');
const invalidS = ethUtil.sha3('invalidS');
const invalidSigBuff = Buffer.concat([
ethUtil.toBuffer(signedOrder.signature.slice(0, 6)),
invalidR,
invalidS,
]);
const signatureType = ethUtil.toBuffer(`0x${signedOrder.signature.slice(-2)}`);
const invalidSigBuff = Buffer.concat([v, invalidR, invalidS, signatureType]);
const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`;
signedOrder.signature = invalidSigHex;
const orderHashHex = orderUtils.getOrderHashHex(signedOrder);
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
const isValidSignature = await signatureValidator.publicIsValidSignature.callAsync(
orderHashHex,
signedOrder.makerAddress,

View File

@@ -1,5 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { Order, SignedOrder } from '@0xproject/types';
import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { AssetProxyId, Order, OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as ethUtil from 'ethereumjs-util';
@@ -8,8 +9,8 @@ import * as Web3 from 'web3';
import { DummyERC20TokenContract } from '../../src/contract_wrappers/generated/dummy_e_r_c20_token';
import { ERC20ProxyContract } from '../../src/contract_wrappers/generated/e_r_c20_proxy';
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
import { WhitelistContract } from '../../src/contract_wrappers/generated/whitelist';
import { artifacts } from '../../src/utils/artifacts';
import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@@ -17,13 +18,7 @@ import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils';
import { TransactionFactory } from '../../src/utils/transaction_factory';
import {
AssetProxyId,
ERC20BalancesByOwner,
ExchangeStatus,
SignatureType,
SignedTransaction,
} from '../../src/utils/types';
import { ERC20BalancesByOwner, ExchangeStatus, SignedTransaction } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
@@ -46,7 +41,7 @@ describe('Exchange transactions', () => {
let erc20Balances: ERC20BalancesByOwner;
let signedOrder: SignedOrder;
let signedTx: SignedTransaction;
let order: Order;
let orderWithoutExchangeAddress: OrderWithoutExchangeAddress;
let orderFactory: OrderFactory;
let makerTransactionFactory: TransactionFactory;
let takerTransactionFactory: TransactionFactory;
@@ -55,6 +50,8 @@ describe('Exchange transactions', () => {
let defaultMakerTokenAddress: string;
let defaultTakerTokenAddress: string;
let makerPrivateKey: Buffer;
let takerPrivateKey: Buffer;
before(async () => {
await blockchainLifecycle.startAsync();
@@ -98,8 +95,8 @@ describe('Exchange transactions', () => {
makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerTokenAddress),
takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerTokenAddress),
};
const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams);
makerTransactionFactory = new TransactionFactory(makerPrivateKey, exchange.address);
takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchange.address);
@@ -117,11 +114,11 @@ describe('Exchange transactions', () => {
beforeEach(async () => {
erc20Balances = await erc20Wrapper.getBalancesAsync();
signedOrder = orderFactory.newSignedOrder();
order = orderUtils.getOrderStruct(signedOrder);
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
const data = exchange.fillOrder.getABIEncodedTransactionData(
order,
orderWithoutExchangeAddress,
takerAssetFillAmount,
signedOrder.signature,
);
@@ -185,7 +182,7 @@ describe('Exchange transactions', () => {
describe('cancelOrder', () => {
beforeEach(async () => {
const data = exchange.cancelOrder.getABIEncodedTransactionData(order);
const data = exchange.cancelOrder.getABIEncodedTransactionData(orderWithoutExchangeAddress);
signedTx = makerTransactionFactory.newSignedTransaction(data);
});
@@ -203,4 +200,131 @@ describe('Exchange transactions', () => {
});
});
});
describe('Whitelist', () => {
let whitelist: WhitelistContract;
let whitelistOrderFactory: OrderFactory;
before(async () => {
whitelist = await WhitelistContract.deployFrom0xArtifactAsync(
artifacts.Whitelist,
provider,
txDefaults,
exchange.address,
);
const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await exchange.setSignatureValidatorApproval.sendTransactionAsync(whitelist.address, isApproved, {
from: takerAddress,
}),
);
const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS,
senderAddress: whitelist.address,
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerTokenAddress),
takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerTokenAddress),
};
whitelistOrderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams);
});
beforeEach(async () => {
signedOrder = whitelistOrderFactory.newSignedOrder();
erc20Balances = await erc20Wrapper.getBalancesAsync();
});
it('should revert if maker has not been whitelisted', async () => {
const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await whitelist.updateWhitelistStatus.sendTransactionAsync(takerAddress, isApproved, { from: owner }),
);
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const takerAssetFillAmount = signedOrder.takerAssetAmount;
const salt = generatePseudoRandomSalt();
return expect(
whitelist.fillOrderIfWhitelisted.sendTransactionAsync(
orderWithoutExchangeAddress,
takerAssetFillAmount,
salt,
signedOrder.signature,
{ from: takerAddress },
),
).to.be.rejectedWith(constants.REVERT);
});
it('should revert if taker has not been whitelisted', async () => {
const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await whitelist.updateWhitelistStatus.sendTransactionAsync(makerAddress, isApproved, { from: owner }),
);
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const takerAssetFillAmount = signedOrder.takerAssetAmount;
const salt = generatePseudoRandomSalt();
return expect(
whitelist.fillOrderIfWhitelisted.sendTransactionAsync(
orderWithoutExchangeAddress,
takerAssetFillAmount,
salt,
signedOrder.signature,
{ from: takerAddress },
),
).to.be.rejectedWith(constants.REVERT);
});
it('should fill the order if maker and taker have been whitelisted', async () => {
const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await whitelist.updateWhitelistStatus.sendTransactionAsync(makerAddress, isApproved, { from: owner }),
);
await web3Wrapper.awaitTransactionSuccessAsync(
await whitelist.updateWhitelistStatus.sendTransactionAsync(takerAddress, isApproved, { from: owner }),
);
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const takerAssetFillAmount = signedOrder.takerAssetAmount;
const salt = generatePseudoRandomSalt();
await web3Wrapper.awaitTransactionSuccessAsync(
await whitelist.fillOrderIfWhitelisted.sendTransactionAsync(
orderWithoutExchangeAddress,
takerAssetFillAmount,
salt,
signedOrder.signature,
{ from: takerAddress },
),
);
const newBalances = await erc20Wrapper.getBalancesAsync();
const makerAssetFillAmount = signedOrder.makerAssetAmount;
const makerFeePaid = signedOrder.makerFee;
const takerFeePaid = signedOrder.takerFee;
expect(newBalances[makerAddress][defaultMakerTokenAddress]).to.be.bignumber.equal(
erc20Balances[makerAddress][defaultMakerTokenAddress].minus(makerAssetFillAmount),
);
expect(newBalances[makerAddress][defaultTakerTokenAddress]).to.be.bignumber.equal(
erc20Balances[makerAddress][defaultTakerTokenAddress].add(takerAssetFillAmount),
);
expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[makerAddress][zrxToken.address].minus(makerFeePaid),
);
expect(newBalances[takerAddress][defaultTakerTokenAddress]).to.be.bignumber.equal(
erc20Balances[takerAddress][defaultTakerTokenAddress].minus(takerAssetFillAmount),
);
expect(newBalances[takerAddress][defaultMakerTokenAddress]).to.be.bignumber.equal(
erc20Balances[takerAddress][defaultMakerTokenAddress].add(makerAssetFillAmount),
);
expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[takerAddress][zrxToken.address].minus(takerFeePaid),
);
expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
);
});
});
});

View File

@@ -1,5 +1,6 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
import { SignedOrder } from '@0xproject/types';
import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -14,14 +15,13 @@ import { ERC721ProxyContract } from '../../src/contract_wrappers/generated/e_r_c
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry';
import { artifacts } from '../../src/utils/artifacts';
import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { OrderFactory } from '../../src/utils/order_factory';
import { AssetProxyId, ERC20BalancesByOwner } from '../../src/utils/types';
import { ERC20BalancesByOwner } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();

View File

@@ -1,9 +1,10 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import BN = require('bn.js');
import * as chai from 'chai';
import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util');
import * as Web3 from 'web3';
@@ -11,7 +12,6 @@ import { TestLibBytesContract } from '../../src/contract_wrappers/generated/test
import { artifacts } from '../../src/utils/artifacts';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { AssetProxyId } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
@@ -22,6 +22,7 @@ describe('LibBytes', () => {
let owner: string;
let libBytes: TestLibBytesContract;
const byteArrayShorterThan32Bytes = '0x012345';
const byteArrayShorterThan20Bytes = byteArrayShorterThan32Bytes;
const byteArrayLongerThan32Bytes =
'0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
const byteArrayLongerThan32BytesFirstBytesSwapped =
@@ -60,6 +61,36 @@ describe('LibBytes', () => {
await blockchainLifecycle.revertAsync();
});
describe('popByte', () => {
it('should revert if length is 0', async () => {
return expect(libBytes.publicPopByte.callAsync(constants.NULL_BYTES)).to.be.rejectedWith(constants.REVERT);
});
it('should pop the last byte from the input and return it', async () => {
const [newBytes, poppedByte] = await libBytes.publicPopByte.callAsync(byteArrayLongerThan32Bytes);
const expectedNewBytes = byteArrayLongerThan32Bytes.slice(0, -2);
const expectedPoppedByte = `0x${byteArrayLongerThan32Bytes.slice(-2)}`;
expect(newBytes).to.equal(expectedNewBytes);
expect(poppedByte).to.equal(expectedPoppedByte);
});
});
describe('popAddress', () => {
it('should revert if length is less than 20', async () => {
return expect(libBytes.publicPopAddress.callAsync(byteArrayShorterThan20Bytes)).to.be.rejectedWith(
constants.REVERT,
);
});
it('should pop the last 20 bytes from the input and return it', async () => {
const [newBytes, poppedAddress] = await libBytes.publicPopAddress.callAsync(byteArrayLongerThan32Bytes);
const expectedNewBytes = byteArrayLongerThan32Bytes.slice(0, -40);
const expectedPoppedAddress = `0x${byteArrayLongerThan32Bytes.slice(-40)}`;
expect(newBytes).to.equal(expectedNewBytes);
expect(poppedAddress).to.equal(expectedPoppedAddress);
});
});
describe('areBytesEqual', () => {
it('should return true if byte arrays are equal (both arrays < 32 bytes)', async () => {
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(

View File

@@ -1,8 +1,8 @@
import { BlockchainLifecycle, web3Factory } from '@0xproject/dev-utils';
import { LogWithDecodedArgs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import 'make-promises-safe';
import * as Web3 from 'web3';
@@ -26,6 +26,12 @@ describe('MultiSigWalletWithTimeLock', () => {
const REQUIRED_APPROVALS = new BigNumber(2);
const SECONDS_TIME_LOCKED = new BigNumber(1000000);
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
owners = [accounts[0], accounts[1]];

View File

@@ -23,6 +23,7 @@ describe('TokenRegistry', () => {
let notOwner: string;
let tokenReg: TokenRegistryContract;
let tokenRegWrapper: TokenRegWrapper;
before(async () => {
await blockchainLifecycle.startAsync();
});
@@ -34,7 +35,7 @@ describe('TokenRegistry', () => {
owner = accounts[0];
notOwner = accounts[1];
tokenReg = await TokenRegistryContract.deployFrom0xArtifactAsync(artifacts.TokenRegistry, provider, txDefaults);
tokenRegWrapper = new TokenRegWrapper(tokenReg);
tokenRegWrapper = new TokenRegWrapper(tokenReg, provider);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();

View File

@@ -1,6 +1,6 @@
// import { ECSignature, SignedOrder, ZeroEx } from '0x.js';
// import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
// import { ExchangeContractErrs } from '@0xproject/types';
// import { ExchangeContractErrs } from 'ethereum-types';
// import { BigNumber } from '@0xproject/utils';
// import { Web3Wrapper } from '@0xproject/web3-wrapper';
// import * as chai from 'chai';

View File

@@ -64,7 +64,10 @@ describe('UnlimitedAllowanceToken', () => {
const receiver = spender;
const initOwnerBalance = await token.balanceOf.callAsync(owner);
const amountToTransfer = new BigNumber(1);
await token.transfer.sendTransactionAsync(receiver, amountToTransfer, { from: owner });
await web3Wrapper.awaitTransactionSuccessAsync(
await token.transfer.sendTransactionAsync(receiver, amountToTransfer, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
const finalOwnerBalance = await token.balanceOf.callAsync(owner);
const finalReceiverBalance = await token.balanceOf.callAsync(receiver);
@@ -86,7 +89,10 @@ describe('UnlimitedAllowanceToken', () => {
it('should throw if owner has insufficient balance', async () => {
const ownerBalance = await token.balanceOf.callAsync(owner);
const amountToTransfer = ownerBalance.plus(1);
await token.approve.sendTransactionAsync(spender, amountToTransfer, { from: owner });
await web3Wrapper.awaitTransactionSuccessAsync(
await token.approve.sendTransactionAsync(spender, amountToTransfer, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
return expect(
token.transferFrom.callAsync(owner, spender, amountToTransfer, {
from: spender,
@@ -121,11 +127,17 @@ describe('UnlimitedAllowanceToken', () => {
const initOwnerBalance = await token.balanceOf.callAsync(owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
await token.approve.sendTransactionAsync(spender, initSpenderAllowance, { from: owner });
await token.transferFrom.sendTransactionAsync(owner, spender, amountToTransfer, {
from: spender,
gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
});
await web3Wrapper.awaitTransactionSuccessAsync(
await token.approve.sendTransactionAsync(spender, initSpenderAllowance, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await token.transferFrom.sendTransactionAsync(owner, spender, amountToTransfer, {
from: spender,
gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
const newSpenderAllowance = await token.allowance.callAsync(owner, spender);
expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance);
@@ -135,11 +147,17 @@ describe('UnlimitedAllowanceToken', () => {
const initOwnerBalance = await token.balanceOf.callAsync(owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
await token.approve.sendTransactionAsync(spender, initSpenderAllowance, { from: owner });
await token.transferFrom.sendTransactionAsync(owner, spender, amountToTransfer, {
from: spender,
gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
});
await web3Wrapper.awaitTransactionSuccessAsync(
await token.approve.sendTransactionAsync(spender, initSpenderAllowance, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await token.transferFrom.sendTransactionAsync(owner, spender, amountToTransfer, {
from: spender,
gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
const newOwnerBalance = await token.balanceOf.callAsync(owner);
const newSpenderBalance = await token.balanceOf.callAsync(spender);
@@ -152,11 +170,17 @@ describe('UnlimitedAllowanceToken', () => {
const initOwnerBalance = await token.balanceOf.callAsync(owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
await token.approve.sendTransactionAsync(spender, initSpenderAllowance, { from: owner });
await token.transferFrom.sendTransactionAsync(owner, spender, amountToTransfer, {
from: spender,
gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
});
await web3Wrapper.awaitTransactionSuccessAsync(
await token.approve.sendTransactionAsync(spender, initSpenderAllowance, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await token.transferFrom.sendTransactionAsync(owner, spender, amountToTransfer, {
from: spender,
gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
const newSpenderAllowance = await token.allowance.callAsync(owner, spender);
expect(newSpenderAllowance).to.be.bignumber.equal(0);

View File

@@ -46,6 +46,7 @@
"dependencies": {
"@0xproject/subproviders": "^0.10.2",
"@0xproject/types": "^0.7.0",
"ethereum-types": "^0.0.1",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/web3-wrapper": "^0.6.4",
"lodash": "^4.17.4",

View File

@@ -1,6 +1,6 @@
export const constants = {
RPC_URL: 'http://localhost:8545',
RPC_PORT: 8545,
GAS_ESTIMATE: 5000000,
GAS_LIMIT: 7000000,
TESTRPC_FIRST_ADDRESS: '0x5409ed021d9299bf6814279a6a1411a7e866a631',
};

View File

@@ -7,7 +7,7 @@ import ProviderEngine = require('web3-provider-engine');
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
import { EmptyWalletSubprovider, FakeGasEstimateSubprovider, GanacheSubprovider } from '@0xproject/subproviders';
import { Provider } from '@0xproject/types';
import { Provider } from 'ethereum-types';
import * as fs from 'fs';
import * as _ from 'lodash';
import * as process from 'process';
@@ -28,7 +28,7 @@ export const web3Factory = {
if (!hasAddresses) {
provider.addProvider(new EmptyWalletSubprovider());
}
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_ESTIMATE));
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_LIMIT));
const logger = {
log: (arg: any) => {
fs.appendFileSync('ganache.log', `${arg}\n`);
@@ -41,6 +41,7 @@ export const web3Factory = {
}
provider.addProvider(
new GanacheSubprovider({
gasLimit: constants.GAS_LIMIT,
logger,
verbose: env.parseBoolean(EnvVars.VerboseGanache),
port: 8545,

View File

@@ -1,6 +1,6 @@
import { BlockParamLiteral } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import { BlockParamLiteral } from 'ethereum-types';
import 'make-promises-safe';
import 'mocha';

View File

@@ -1,6 +1,6 @@
import { BlockParamLiteral } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import { BlockParamLiteral } from 'ethereum-types';
import 'make-promises-safe';
import 'mocha';

View File

@@ -0,0 +1,6 @@
.*
yarn-error.log
/scripts/
/src/
tsconfig.json
/lib/monorepo_scripts/

View File

@@ -0,0 +1,11 @@
[
{
"version": "0.0.1",
"changes": [
{
"note": "Initial publish",
"pr": "642"
}
]
}
]

View File

@@ -0,0 +1,61 @@
## ethereum-types
Typescript types shared across Ethereum-related packages/libraries/tools.
## Installation
```bash
yarn add -D ethereum-types
```
## Usage
```javascript
import { TransactionReceipt, TxData, TxDataPayable } from 'ethereum-types';
```
## Contributing
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
### Install dependencies
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
```bash
yarn config set workspaces-experimental true
```
Then install dependencies
```bash
yarn install
```
### Build
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
```bash
PKG=ethereum-types yarn build
```
Or continuously rebuild on change:
```bash
PKG=ethereum-types yarn watch
```
### Clean
```bash
yarn clean
```
### Lint
```bash
yarn lint
```

View File

@@ -0,0 +1,42 @@
{
"name": "ethereum-types",
"version": "0.0.1",
"engines": {
"node": ">=6.12"
},
"description": "Ethereum types",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"watch": "tsc -w",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib scripts",
"lint": "tslint --project .",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x-monorepo.git"
},
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/ethereum-types/README.md",
"devDependencies": {
"@0xproject/monorepo-scripts": "^0.1.20",
"@0xproject/tslint-config": "^0.4.18",
"copyfiles": "^1.2.0",
"make-promises-safe": "^1.1.0",
"shx": "^0.2.2",
"tslint": "5.8.0",
"typescript": "2.7.1"
},
"dependencies": {
"@types/node": "^8.0.53",
"bignumber.js": "~4.1.0"
},
"publishConfig": {
"access": "public"
}
}

View File

@@ -0,0 +1,6 @@
declare module '*.json' {
const json: any;
/* tslint:disable */
export default json;
/* tslint:enable */
}

View File

@@ -0,0 +1,281 @@
import { BigNumber } from 'bignumber.js';
export type JSONRPCErrorCallback = (err: Error | null, result?: JSONRPCResponsePayload) => void;
/**
* Do not create your own provider. Use an existing provider from a Web3 or ProviderEngine library
* Read more about Providers in the 0x wiki.
*/
export interface Provider {
sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): void;
}
export type ContractAbi = AbiDefinition[];
export type AbiDefinition = FunctionAbi | EventAbi;
export type FunctionAbi = MethodAbi | ConstructorAbi | FallbackAbi;
export type ConstructorStateMutability = 'nonpayable' | 'payable';
export type StateMutability = 'pure' | 'view' | ConstructorStateMutability;
export interface MethodAbi {
type: AbiType.Function;
name: string;
inputs: DataItem[];
outputs: DataItem[];
constant: boolean;
stateMutability: StateMutability;
payable: boolean;
}
export interface ConstructorAbi {
type: AbiType.Constructor;
inputs: DataItem[];
payable: boolean;
stateMutability: ConstructorStateMutability;
}
export interface FallbackAbi {
type: AbiType.Fallback;
payable: boolean;
}
export interface EventParameter extends DataItem {
indexed: boolean;
}
export interface EventAbi {
type: AbiType.Event;
name: string;
inputs: EventParameter[];
anonymous: boolean;
}
export interface DataItem {
name: string;
type: string;
components?: DataItem[];
}
export enum OpCode {
DelegateCall = 'DELEGATECALL',
Revert = 'REVERT',
Create = 'CREATE',
Stop = 'STOP',
Invalid = 'INVALID',
CallCode = 'CALLCODE',
StaticCall = 'STATICCALL',
Return = 'RETURN',
Call = 'CALL',
SelfDestruct = 'SELFDESTRUCT',
}
export interface StructLog {
depth: number;
error: string;
gas: number;
gasCost: number;
memory: string[];
op: OpCode;
pc: number;
stack: string[];
storage: { [location: string]: string };
}
export interface TransactionTrace {
gas: number;
returnValue: any;
structLogs: StructLog[];
}
export type Unit =
| 'kwei'
| 'ada'
| 'mwei'
| 'babbage'
| 'gwei'
| 'shannon'
| 'szabo'
| 'finney'
| 'ether'
| 'kether'
| 'grand'
| 'einstein'
| 'mether'
| 'gether'
| 'tether';
export interface JSONRPCRequestPayload {
params: any[];
method: string;
id: number;
jsonrpc: string;
}
export interface JSONRPCResponsePayload {
result: any;
id: number;
jsonrpc: string;
}
export interface AbstractBlock {
number: number | null;
hash: string | null;
parentHash: string;
nonce: string | null;
sha3Uncles: string;
logsBloom: string | null;
transactionsRoot: string;
stateRoot: string;
miner: string;
difficulty: BigNumber;
totalDifficulty: BigNumber;
extraData: string;
size: number;
gasLimit: number;
gasUsed: number;
timestamp: number;
uncles: string[];
}
export interface BlockWithoutTransactionData extends AbstractBlock {
transactions: string[];
}
export interface BlockWithTransactionData extends AbstractBlock {
transactions: Transaction[];
}
export interface Transaction {
hash: string;
nonce: number;
blockHash: string | null;
blockNumber: number | null;
transactionIndex: number | null;
from: string;
to: string | null;
value: BigNumber;
gasPrice: BigNumber;
gas: number;
input: string;
}
export interface CallTxDataBase {
to?: string;
value?: number | string | BigNumber;
gas?: number | string | BigNumber;
gasPrice?: number | string | BigNumber;
data?: string;
nonce?: number;
}
export interface TxData extends CallTxDataBase {
from: string;
}
export interface CallData extends CallTxDataBase {
from?: string;
}
export interface FilterObject {
fromBlock?: number | string;
toBlock?: number | string;
address?: string;
topics?: LogTopic[];
}
export type LogTopic = null | string | string[];
export interface DecodedLogEntry<A> extends LogEntry {
event: string;
args: A;
}
export interface DecodedLogEntryEvent<A> extends DecodedLogEntry<A> {
removed: boolean;
}
export interface LogEntryEvent extends LogEntry {
removed: boolean;
}
export interface LogEntry {
logIndex: number | null;
transactionIndex: number | null;
transactionHash: string;
blockHash: string | null;
blockNumber: number | null;
address: string;
data: string;
topics: string[];
}
export interface TxDataPayable extends TxData {
value?: BigNumber;
}
export interface TransactionReceipt {
blockHash: string;
blockNumber: number;
transactionHash: string;
transactionIndex: number;
from: string;
to: string;
status: null | string | 0 | 1;
cumulativeGasUsed: number;
gasUsed: number;
contractAddress: string | null;
logs: LogEntry[];
}
export enum AbiType {
Function = 'function',
Constructor = 'constructor',
Event = 'event',
Fallback = 'fallback',
}
export type ContractEventArg = string | BigNumber | number | boolean;
export interface DecodedLogArgs {
[argName: string]: ContractEventArg;
}
export interface LogWithDecodedArgs<ArgsType extends DecodedLogArgs> extends DecodedLogEntry<ArgsType> {}
export type RawLog = LogEntry;
export enum BlockParamLiteral {
Earliest = 'earliest',
Latest = 'latest',
Pending = 'pending',
}
export type BlockParam = BlockParamLiteral | number;
export interface RawLogEntry {
logIndex: string | null;
transactionIndex: string | null;
transactionHash: string;
blockHash: string | null;
blockNumber: string | null;
address: string;
data: string;
topics: string[];
}
export enum SolidityTypes {
Address = 'address',
Uint256 = 'uint256',
Uint8 = 'uint8',
Uint = 'uint',
}
/**
* Contains the logs returned by a TransactionReceipt. We attempt to decode the
* logs using AbiDecoder. If we have the logs corresponding ABI, we decode it,
* otherwise we don't.
*/
export interface TransactionReceiptWithDecodedLogs extends TransactionReceipt {
logs: Array<LogWithDecodedArgs<DecodedLogArgs> | LogEntry>;
}

View File

@@ -0,0 +1,8 @@
import { postpublishUtils } from '@0xproject/monorepo-scripts';
import * as packageJSON from '../package.json';
import * as tsConfigJSON from '../tsconfig.json';
const cwd = `${__dirname}/..`;
// tslint:disable-next-line:no-floating-promises
postpublishUtils.runAsync(packageJSON, tsConfigJSON, cwd);

View File

@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"typeRoots": ["../../node_modules/@types"],
"outDir": "lib"
},
"include": ["src/**/*"]
}

View File

@@ -0,0 +1,3 @@
{
"extends": ["@0xproject/tslint-config"]
}

View File

@@ -37,8 +37,9 @@
},
"dependencies": {
"@0xproject/base-contract": "^0.3.2",
"@0xproject/order-utils": "^0.0.5",
"@0xproject/order-utils": "0.0.5",
"@0xproject/types": "0.7.0",
"ethereum-types": "^0.0.1",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/json-schemas",
"version": "0.7.24",
"version": "1.0.0",
"engines": {
"node": ">=6.12"
},
@@ -27,7 +27,8 @@
"assets": [],
"docPublishConfigs": {
"extraFileIncludes": [
"../types/src/index.ts"
"../types/src/index.ts",
"../ethereum-types/src/index.ts"
],
"s3BucketPath": "s3://doc-jsons/json-schemas/",
"s3StagingBucketPath": "s3://staging-doc-jsons/json-schemas/"

View File

@@ -0,0 +1,20 @@
export const ecSignatureParameterSchema = {
id: '/ECSignatureParameter',
type: 'string',
pattern: '^0[xX][0-9A-Fa-f]{64}$',
};
export const ecSignatureSchema = {
id: '/ECSignature',
properties: {
v: {
type: 'number',
minimum: 27,
maximum: 28,
},
r: { $ref: '/ECSignatureParameter' },
s: { $ref: '/ECSignatureParameter' },
},
required: ['v', 'r', 's'],
type: 'object',
};

View File

@@ -5,11 +5,13 @@ export const orderSchema = {
takerAddress: { $ref: '/Address' },
makerFee: { $ref: '/Number' },
takerFee: { $ref: '/Number' },
senderAddress: { $ref: '/Address' },
makerAssetAmount: { $ref: '/Number' },
takerAssetAmount: { $ref: '/Number' },
makerAssetData: { $ref: '/Hex' },
takerAssetData: { $ref: '/Hex' },
salt: { $ref: '/Number' },
exchangeAddress: { $ref: '/Address' },
feeRecipientAddress: { $ref: '/Address' },
expirationTimeSeconds: { $ref: '/Number' },
},
@@ -18,11 +20,13 @@ export const orderSchema = {
'takerAddress',
'makerFee',
'takerFee',
'senderAddress',
'makerAssetAmount',
'takerAssetAmount',
'makerAssetData',
'takerAssetData',
'salt',
'exchangeAddress',
'feeRecipientAddress',
'expirationTimeSeconds',
],

View File

@@ -1,5 +1,6 @@
import { addressSchema, hexSchema, numberSchema } from '../schemas/basic_type_schemas';
import { blockParamSchema, blockRangeSchema } from '../schemas/block_range_schema';
import { ecSignatureSchema } from '../schemas/ec_signature_schema';
import { indexFilterValuesSchema } from '../schemas/index_filter_values_schema';
import { orderCancellationRequestsSchema } from '../schemas/order_cancel_schema';
import { orderFillOrKillRequestsSchema } from '../schemas/order_fill_or_kill_requests_schema';
@@ -31,6 +32,7 @@ export const schemas = {
numberSchema,
addressSchema,
hexSchema,
ecSignatureSchema,
indexFilterValuesSchema,
orderCancellationRequestsSchema,
orderFillOrKillRequestsSchema,

View File

@@ -171,6 +171,7 @@ describe('Schema', () => {
const order = {
makerAddress: NULL_ADDRESS,
takerAddress: NULL_ADDRESS,
senderAddress: NULL_ADDRESS,
makerFee: '1',
takerFee: '2',
makerAssetAmount: '1',
@@ -179,6 +180,7 @@ describe('Schema', () => {
takerAssetData: NULL_ADDRESS,
salt: '67006738228878699843088602623665307406148487219438534730168799356281242528500',
feeRecipientAddress: NULL_ADDRESS,
exchangeAddress: NULL_ADDRESS,
expirationTimeSeconds: '42',
};
describe('#orderSchema', () => {

View File

@@ -35,6 +35,7 @@
"@0xproject/types": "^0.7.0",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",
"ethereum-types": "^0.0.1",
"ethers": "^3.0.15",
"lodash": "^4.17.4",
"web3-provider-engine": "^14.0.4"

View File

@@ -1,9 +1,9 @@
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
import { ContractArtifact } from '@0xproject/sol-compiler';
import { LogWithDecodedArgs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import 'make-promises-safe';
import * as MetacoinArtifact from '../artifacts/Metacoin.json';

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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