Compare commits
	
		
			231 Commits
		
	
	
		
			@0xproject
			...
			@0xproject
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d4631e14b2 | ||
|  | 8df2cc103e | ||
|  | 8e0e9c7d3a | ||
|  | 913930b561 | ||
|  | 994c8db1f3 | ||
|  | 6811bdec40 | ||
|  | 6682abf89d | ||
|  | 78fbf0f7ba | ||
|  | 89547332ee | ||
|  | 75539bf675 | ||
|  | eaeb715e56 | ||
|  | ca55cc99ed | ||
|  | 7cc4a8f5ce | ||
|  | fa35768fc9 | ||
|  | 4d0ff0dce4 | ||
|  | 8aac6e46d4 | ||
|  | 1feac1a308 | ||
|  | d3e42e4b3e | ||
|  | ecf86d1d13 | ||
|  | adc6170f02 | ||
|  | 02600f40d2 | ||
|  | 16ea0348a9 | ||
|  | 57acb8db5c | ||
|  | 2bcb7d5639 | ||
|  | a99e54330a | ||
|  | e219772b2a | ||
|  | 144a507a2e | ||
|  | 5019c51940 | ||
|  | da1071526f | ||
|  | 7ad314472d | ||
|  | 4f6168a982 | ||
|  | 218a872968 | ||
|  | 0043c5e1ac | ||
|  | d0e7046a89 | ||
|  | 52ad16b920 | ||
|  | 5a4c0bff6a | ||
|  | 6205209fbb | ||
|  | 6ebf8a57d1 | ||
|  | c02dfc4fb1 | ||
|  | 9d62e5fb6f | ||
|  | 6f13d107c4 | ||
|  | e56b2ceebb | ||
|  | 7de244ed62 | ||
|  | 1e9147b8bb | ||
|  | 2f65fadeaa | ||
|  | a17091b394 | ||
|  | ed77c6cb54 | ||
|  | bc37cc8a91 | ||
|  | 387363283c | ||
|  | 709026bf1a | ||
|  | f2b2b86786 | ||
|  | d0fbea76d8 | ||
|  | 8269610a5c | ||
|  | 20c88a46d9 | ||
|  | 661029f7cc | ||
|  | 850d32d60c | ||
|  | eb881b9729 | ||
|  | 091ba473ff | ||
|  | fca051c565 | ||
|  | 6463cda204 | ||
|  | d004df56e3 | ||
|  | 359dd482c4 | ||
|  | 89e98240b4 | ||
|  | 8d30058a6d | ||
|  | 69151c06e4 | ||
|  | 2e3c02887e | ||
|  | 7603cef308 | ||
|  | be370c4e19 | ||
|  | c6dece6bd1 | ||
|  | 93a5b3f457 | ||
|  | 4242176d29 | ||
|  | 1cadbeed88 | ||
|  | 86cc011212 | ||
|  | c0facfc28f | ||
|  | ad52a82190 | ||
|  | 60b6ed514f | ||
|  | ef32822b31 | ||
|  | bb0cedd2de | ||
|  | 8175c7c085 | ||
|  | 5c2d725721 | ||
|  | 72571628da | ||
|  | fa6130c907 | ||
|  | 8ccdd54974 | ||
|  | 6c1409b00d | ||
|  | 542a1a11b9 | ||
|  | 63ffa80c5c | ||
|  | 609342be7a | ||
|  | 52394884da | ||
|  | af08177f79 | ||
|  | 45fdfc2d3d | ||
|  | d18554e0e8 | ||
|  | 3c3f9ca85b | ||
|  | 005a02efeb | ||
|  | 6206ebc994 | ||
|  | dd9f5adc2e | ||
|  | 748d805a32 | ||
|  | 4b59bf01b3 | ||
|  | b4faa4851a | ||
|  | f37fcc147c | ||
|  | dc5694e544 | ||
|  | e588f6f8c3 | ||
|  | d227f2ad7c | ||
|  | 97c228031a | ||
|  | ad85011d62 | ||
|  | a70379625d | ||
|  | 7350333129 | ||
|  | 216420fdc5 | ||
|  | c559fbbe8c | ||
|  | 71d68f975c | ||
|  | 390534497e | ||
|  | 3f0ec89f11 | ||
|  | d3aa4f2bc7 | ||
|  | f58f0ddb67 | ||
|  | 633e3129d4 | ||
|  | 877bdce4c8 | ||
|  | 6e1fbd2d97 | ||
|  | 36bfe62a8f | ||
|  | b08bd0f9ab | ||
|  | 3998b47d84 | ||
|  | d965fdb11d | ||
|  | ddb64b3ec1 | ||
|  | 5055ec8617 | ||
|  | 8a858501f2 | ||
|  | e1af25c8a6 | ||
|  | 6091f818da | ||
|  | a45f9b4802 | ||
|  | 9ccf63b44a | ||
|  | d34135ae43 | ||
|  | a81f6f9ad1 | ||
|  | 8a80b10cc2 | ||
|  | 22b1ee132a | ||
|  | ab7f681f15 | ||
|  | 2ac806ef08 | ||
|  | 13ec8ed03c | ||
|  | fb77817c2d | ||
|  | ceb8a492b1 | ||
|  | cfc868bf4d | ||
|  | 7b4e2257d8 | ||
|  | 4ac6e5477d | ||
|  | 614ea14a7f | ||
|  | ce45f99006 | ||
|  | 9203813a61 | ||
|  | ba987b0574 | ||
|  | b20f34adb7 | ||
|  | 63d0d810b1 | ||
|  | 5491400684 | ||
|  | 6a5165e9b3 | ||
|  | 9a7c4442d2 | ||
|  | 0e5363b5c3 | ||
|  | d41bce36be | ||
|  | 1380cd811e | ||
|  | d99bb3a87c | ||
|  | 4b9501318d | ||
|  | e5eec04f92 | ||
|  | f9c21efc30 | ||
|  | ae72b71895 | ||
|  | 87e3fe725d | ||
|  | 807d9e3eef | ||
|  | 9e569b3791 | ||
|  | 024f093585 | ||
|  | 996e9e9102 | ||
|  | d58bfb46cf | ||
|  | eb0d7df50b | ||
|  | 547bee38c0 | ||
|  | 60614ba250 | ||
|  | 278f68ae77 | ||
|  | b4375d6f64 | ||
|  | 9f47c72d31 | ||
|  | de3bf03f42 | ||
|  | 59a39ac57d | ||
|  | df9c2b193e | ||
|  | 3894311d68 | ||
|  | 35501dd4fc | ||
|  | e2ca713658 | ||
|  | a45de6d427 | ||
|  | a350638526 | ||
|  | 59f9605ed9 | ||
|  | 9521bf8d4f | ||
|  | 7c1c94d39b | ||
|  | 8a74963815 | ||
|  | 3ebd8b7f45 | ||
|  | ae8cb2e6a8 | ||
|  | 1ccb978612 | ||
|  | 7040a01cf2 | ||
|  | 6bc0e815e9 | ||
|  | 593f7e826c | ||
|  | 835fa0af13 | ||
|  | 0e3bd0c6c1 | ||
|  | 86668eb7b9 | ||
|  | 771f65c858 | ||
|  | 89d6326a83 | ||
|  | 8b81ea162f | ||
|  | a53e6db537 | ||
|  | 62e3feeb94 | ||
|  | a950494503 | ||
|  | 3cb310122e | ||
|  | feace988b4 | ||
|  | 6a56f20928 | ||
|  | 80a46d14be | ||
|  | fbcbf066cd | ||
|  | 4d30e1115f | ||
|  | 897cfb491c | ||
|  | c2c7512431 | ||
|  | 568cf4d182 | ||
|  | f54330f1c5 | ||
|  | 97e01d7a42 | ||
|  | 4be3e000e1 | ||
|  | b47baa9ee1 | ||
|  | f6c98112df | ||
|  | 94d29ab22e | ||
|  | b0b179550a | ||
|  | 41c7ab4f9c | ||
|  | 432c7c63fe | ||
|  | 2bba1ae292 | ||
|  | 7830d518e0 | ||
|  | 571b3c4da8 | ||
|  | 5b6f8d4c3f | ||
|  | ae57b21b98 | ||
|  | 292c3bbff8 | ||
|  | 065570ebf5 | ||
|  | 1f5dfd71d5 | ||
|  | 31b3ac4b98 | ||
|  | ec3d8a034f | ||
|  | c452294bcc | ||
|  | d5757499bc | ||
|  | 139c8c2e78 | ||
|  | 215e33fa6c | ||
|  | 3d12b84f1d | ||
|  | d8adc88c52 | ||
|  | 5119e49e47 | ||
|  | cfb9f87418 | 
| @@ -6,24 +6,117 @@ jobs: | ||||
|       - image: circleci/node:6.12 | ||||
|     environment: | ||||
|       CONTRACTS_COMMIT_HASH: '9ed05f5' | ||||
|     working_directory: ~/repo | ||||
|     steps: | ||||
|       - checkout | ||||
|       - run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV | ||||
|       - restore_cache: | ||||
|           key: dependency-cache-{{ checksum "package.json" }} | ||||
|       - run: | ||||
|           name: yarn | ||||
|           command: yarn | ||||
|           command: yarn --frozen-lockfile | ||||
|       - save_cache: | ||||
|           key: dependency-cache-{{ checksum "package.json" }} | ||||
|           paths: | ||||
|             - ~/.cache/yarn | ||||
|             - ./node_modules | ||||
|       - run: wget https://s3.amazonaws.com/testrpc-shapshots/${CONTRACTS_COMMIT_HASH}.zip | ||||
|       - run: unzip ${CONTRACTS_COMMIT_HASH}.zip -d testrpc_snapshot | ||||
|       - run: node ./node_modules/lerna/bin/lerna.js bootstrap | ||||
|       - run: yarn lerna:run build | ||||
|       - save_cache: | ||||
|           key: repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|           paths: | ||||
|             - ~/repo | ||||
|   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 lerna:run test:circleci | ||||
|       - run: yarn lerna:run --scope 0x.js test:circleci | ||||
|   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 lerna:run --scope contracts test:circleci | ||||
|   test-deployer: | ||||
|     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 lerna:run --scope @0xproject/deployer test:circleci | ||||
|   test-rest: | ||||
|     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 lerna:run --ignore contracts --ignore 0x.js --ignore @0xproject/deployer test:circleci | ||||
|   lint: | ||||
|     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 | ||||
|     steps: | ||||
|       - restore_cache: | ||||
|           keys: | ||||
|             - repo-{{ .Environment.CIRCLE_SHA1 }} | ||||
|       - run: yarn prettier:ci | ||||
| workflows: | ||||
|   version: 2 | ||||
|   main: | ||||
|     jobs: | ||||
|       - build | ||||
|       - test-0xjs: | ||||
|           requires: | ||||
|             - build | ||||
|       - test-contracts: | ||||
|           requires: | ||||
|             - build | ||||
|       - test-deployer: | ||||
|           requires: | ||||
|             - build | ||||
|       - test-rest: | ||||
|           requires: | ||||
|             - build | ||||
|       - prettier: | ||||
|           requires: | ||||
|             - build | ||||
|       - lint: | ||||
|           requires: | ||||
|             - build | ||||
|   | ||||
							
								
								
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| *.sol linguist-language=Solidity | ||||
| @@ -2,3 +2,4 @@ lib | ||||
| generated | ||||
| .nyc_output | ||||
| /packages/contracts/build/contracts | ||||
| package.json | ||||
|   | ||||
							
								
								
									
										62
									
								
								ISSUE_TEMPLATE.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								ISSUE_TEMPLATE.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| <!--- Thank you for taking the time to file an Issue --> | ||||
|  | ||||
| <!--- Before submitting please check to see if this issue was already reported --> | ||||
|  | ||||
| <!--- Provide a general summary of the issue in the Title above --> | ||||
|  | ||||
| ## Expected Behavior | ||||
|  | ||||
| <!--- If you're describing a bug, tell us what should happen --> | ||||
|  | ||||
| <!--- If you're suggesting a package change/improvement, tell us how it should work --> | ||||
|  | ||||
| <!--- If you're suggesting a contract or protocol change/improvement, visit our ZEIPs repo --> | ||||
|  | ||||
| ## Current Behavior | ||||
|  | ||||
| <!--- If describing a bug, tell us what happens instead of the expected behavior --> | ||||
|  | ||||
| <!--- If suggesting a change/improvement, explain the difference from current behavior --> | ||||
|  | ||||
| ## Possible Solution | ||||
|  | ||||
| <!--- Not obligatory, but suggest a fix/reason for the bug, --> | ||||
|  | ||||
| <!--- or ideas how to implement the addition or change --> | ||||
|  | ||||
| ## Steps to Reproduce (for bugs) | ||||
|  | ||||
| <!--- Provide a link to a live example, or an unambiguous set of steps to --> | ||||
|  | ||||
| <!--- reproduce this bug. Include code to reproduce, if relevant --> | ||||
|  | ||||
| ``` | ||||
| 1. | ||||
| 2. | ||||
| 3. | ||||
| ``` | ||||
|  | ||||
| ## Context | ||||
|  | ||||
| <!--- How has this issue affected you? What are you trying to accomplish? --> | ||||
|  | ||||
| <!--- Providing context helps us come up with a solution that is most useful in the real world --> | ||||
|  | ||||
| ## Your Environment | ||||
|  | ||||
| <!--- Include as many relevant details about the environment you experienced the bug in --> | ||||
|  | ||||
| |             Package | Version | | ||||
| | ------------------: | :------ | | ||||
| |             `0x.js` | 0.25.0  | | ||||
| | `Exchange Contract` | v1      | | ||||
|  | ||||
| | Network | | ||||
| | ------- | | ||||
| | NAME    | | ||||
|  | ||||
| <!-- For example: | ||||
| | mainnet | | ||||
| | kovan | | ||||
| | testrpc | | ||||
| --> | ||||
| @@ -1,3 +1,36 @@ | ||||
| This PR: | ||||
| <!--- Thank you for taking the time to submit a Pull Request --> | ||||
|  | ||||
| \* | ||||
| <!--- Provide a general summary of the issue in the Title above --> | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| <!--- Describe your changes in detail --> | ||||
|  | ||||
| ## Motivation and Context | ||||
|  | ||||
| <!--- Why is this change required? What problem does it solve? --> | ||||
|  | ||||
| <!--- If it fixes an open issue, please link to the issue here. --> | ||||
|  | ||||
| ## How Has This Been Tested? | ||||
|  | ||||
| <!--- Please describe in detail how you tested your changes. --> | ||||
|  | ||||
| <!--- Include details of your testing environment, and the tests you ran to --> | ||||
|  | ||||
| <!--- see how your change affects other areas of the code, etc. --> | ||||
|  | ||||
| ## Types of changes | ||||
|  | ||||
| <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: | ||||
| - [ ] Bug fix (non-breaking change which fixes an issue) | ||||
| - [ ] New feature (non-breaking change which adds functionality) | ||||
| - [ ] Breaking change (fix or feature that would cause existing functionality to change) | ||||
|  | ||||
| ## Checklist: | ||||
| <!--- Go over all the following points, and put an `x` in all the boxes that apply. --> | ||||
|  | ||||
| <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> | ||||
|  | ||||
| * [ ] Change requires a change to the documentation. | ||||
| * [ ] Added tests to cover my changes. | ||||
|   | ||||
							
								
								
									
										30
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								README.md
									
									
									
									
									
								
							| @@ -18,26 +18,30 @@ This repository contains all the 0x developer tools written in TypeScript. Our h | ||||
|  | ||||
| ### Published Packages | ||||
|  | ||||
| | Package                                               | Version                                                                                                                     | Description                                                        | | ||||
| | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | | ||||
| | [`0x.js`](/packages/0x.js)                            | [](https://www.npmjs.com/package/0x.js)                                       | A Javascript library for interacting with the 0x protocol          | | ||||
| | [`@0xproject/abi-gen`](/packages/abi-gen)             | [](https://www.npmjs.com/package/@0xproject/abi-gen)             | Tool to generate TS wrappers from smart contract ABIs              | | ||||
| | [`@0xproject/assert`](/packages/assert)               | [](https://www.npmjs.com/package/@0xproject/assert)               | Type and schema assertions used by our packages                    | | ||||
| | [`@0xproject/connect`](/packages/connect)             | [](https://www.npmjs.com/package/@0xproject/connect)             | A Javascript library for interacting with the standard relayer api | | ||||
| | [`@0xproject/json-schemas`](/packages/json-schemas)   | [](https://www.npmjs.com/package/@0xproject/json-schemas)   | 0x-related json schemas                                            | | ||||
| | [`@0xproject/subproviders`](/packages/subproviders)   | [](https://www.npmjs.com/package/@0xproject/subproviders)   | Useful web3 subproviders (e.g LedgerSubprovider)                   | | ||||
| | [`@0xproject/tslint-config`](/packages/tslint-config) | [](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules                                 | | ||||
| | [`@0xproject/types`](/packages/types)                 | [](https://www.npmjs.com/package/@0xproject/types)                 | Shared type declarations                                           | | ||||
| | [`@0xproject/utils`](/packages/utils)                 | [](https://www.npmjs.com/package/@0xproject/utils)                 | Shared utilities                                                   | | ||||
| | [`@0xproject/web3-wrapper`](/packages/web3-wrapper)   | [](https://www.npmjs.com/package/@0xproject/web3-wrapper)   | Web3 wrapper                                                       | | ||||
| | Package                                                                                | Version                                                                                                                                           | Description                                                        | | ||||
| | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | | ||||
| | [`0x.js`](/packages/0x.js)                                                             | [](https://www.npmjs.com/package/0x.js)                                                             | A Javascript library for interacting with the 0x protocol          | | ||||
| | [`chai-as-promised-typescript-typings`](/packages/chai-as-promised-typescript-typings) | [](https://www.npmjs.com/package/chai-as-promised-typescript-typings) | Chai as promised typescript typings                                | | ||||
| | [`chai-typescript-typings`](/packages/chai-typescript-typings)                         | [](https://www.npmjs.com/package/chai-typescript-typings)                         | Chai typescript typings                                            | | ||||
| | [`web3-typescript-typings`](/packages/web3-typescript-typings)                         | [](https://www.npmjs.com/package/web3-typescript-typings)                         | Web3 typescript typings                                            | | ||||
| | [`@0xproject/abi-gen`](/packages/abi-gen)                                              | [](https://www.npmjs.com/package/@0xproject/abi-gen)                                   | Tool to generate TS wrappers from smart contract ABIs              | | ||||
| | [`@0xproject/assert`](/packages/assert)                                                | [](https://www.npmjs.com/package/@0xproject/assert)                                     | Type and schema assertions used by our packages                    | | ||||
| | [`@0xproject/connect`](/packages/connect)                                              | [](https://www.npmjs.com/package/@0xproject/connect)                                   | A Javascript library for interacting with the standard relayer api | | ||||
| | [`@0xproject/dev-utils`](/packages/dev-utils)                                          | [](https://www.npmjs.com/package/@0xproject/dev-utils)                               | Dev utils to be shared across 0x projects and packages             | | ||||
| | [`@0xproject/json-schemas`](/packages/json-schemas)                                    | [](https://www.npmjs.com/package/@0xproject/json-schemas)                         | 0x-related json schemas                                            | | ||||
| | [`@0xproject/subproviders`](/packages/subproviders)                                    | [](https://www.npmjs.com/package/@0xproject/subproviders)                         | Useful web3 subproviders (e.g LedgerSubprovider)                   | | ||||
| | [`@0xproject/tslint-config`](/packages/tslint-config)                                  | [](https://www.npmjs.com/package/@0xproject/tslint-config)                       | Custom 0x development TSLint rules                                 | | ||||
| | [`@0xproject/types`](/packages/types)                                                  | [](https://www.npmjs.com/package/@0xproject/types)                                       | Shared type declarations                                           | | ||||
| | [`@0xproject/utils`](/packages/utils)                                                  | [](https://www.npmjs.com/package/@0xproject/utils)                                       | Shared utilities                                                   | | ||||
| | [`@0xproject/web3-wrapper`](/packages/web3-wrapper)                                    | [](https://www.npmjs.com/package/@0xproject/web3-wrapper)                         | Web3 wrapper                                                       | | ||||
|  | ||||
| ### Private Packages | ||||
|  | ||||
| | Package                                                     | Description                                                      | | ||||
| | ----------------------------------------------------------- | ---------------------------------------------------------------- | | ||||
| | [`@0xproject/contracts`](/packages/contracts)               | 0x solidity smart contracts & tests                              | | ||||
| | [`@0xproject/kovan_faucets`](/packages/kovan-faucets)       | A faucet micro-service that dispenses test ERC20 tokens or Ether | | ||||
| | [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | Shared monorepo scripts                                          | | ||||
| | [`@0xproject/testnet-faucets`](/packages/testnet-faucets)   | A faucet micro-service that dispenses test ERC20 tokens or Ether | | ||||
| | [`@0xproject/website`](/packages/website)                   | 0x website & Portal DApp                                         | | ||||
|  | ||||
| ## Usage | ||||
|   | ||||
| @@ -4,8 +4,8 @@ | ||||
|     "workspaces": ["packages/*"], | ||||
|     "scripts": { | ||||
|         "testrpc": "testrpc -p 8545 --networkId 50 -m \"${npm_package_config_mnemonic}\"", | ||||
|         "prettier": "prettier --write '**/*.{ts,tsx,json,md}'", | ||||
|         "prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}'", | ||||
|         "prettier": "prettier --write '**/*.{ts,tsx,json,md}' --config .prettierrc", | ||||
|         "prettier:ci": "prettier --list-different '**/*.{ts,tsx,json,md}' --config .prettierrc", | ||||
|         "lerna:run": "lerna run", | ||||
|         "lerna:rebuild": "lerna run clean; lerna run build;", | ||||
|         "lerna:publish": | ||||
| @@ -15,9 +15,9 @@ | ||||
|         "mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0xproject/utils": "^0.1.0", | ||||
|         "@0xproject/utils": "^0.2.0", | ||||
|         "async-child-process": "^1.1.1", | ||||
|         "ethereumjs-testrpc": "6.0.3", | ||||
|         "ethereumjs-testrpc": "^6.0.3", | ||||
|         "lerna": "^2.5.1", | ||||
|         "prettier": "1.9.2", | ||||
|         "publish-release": "0xproject/publish-release", | ||||
|   | ||||
| @@ -1,5 +1,32 @@ | ||||
| # CHANGELOG | ||||
|  | ||||
| ## v0.31.1 - _February 1, 2018_ | ||||
|  | ||||
|     * Fix the bug causing order watcher to throw is makerToken === zrx (#357) | ||||
|  | ||||
| ## v0.31.0 - _January 30, 2018_ | ||||
|  | ||||
|     * Add the `shouldAddPersonalMessagePrefix` parameter to `signOrderHashAsync` so that the | ||||
|     caller can decide on whether to add the personalMessage prefix before relaying the request | ||||
|     to the signer. Parity Signer, Ledger and TestRPC add the prefix themselves, Metamask expects | ||||
|     it to have already been added. (#349) | ||||
|  | ||||
| ## v0.30.2 - _January 29, 2018_ | ||||
|  | ||||
|     * Add Rinkeby testnet addresses to artifacts  (#337) | ||||
|     * Move @0xproject/types to dependencies from devDependencies fixing missing type errors | ||||
|  | ||||
| ## v0.30.1 - _January 24, 2018_ | ||||
|  | ||||
|     * Fix a bug allowing negative fill values  (#212) | ||||
|     * Fix a bug that made it impossible to pass a custom ZRX address  (#341) | ||||
|  | ||||
| ## v0.30.0 - _January 17, 2018_ | ||||
|  | ||||
|     * Add an error parameter to the order watcher callback (#312) | ||||
|     * Fix a bug making it impossible to catch some errors from awaitTransactionMinedAsync (#312) | ||||
|     * Fix a bug in fillOrdersUpTo validation making it impossible to fill up to if user doesn't have enough balance to fully fill all the orders (#321) | ||||
|  | ||||
| ## v0.29.1 - _January 11, 2018_ | ||||
|  | ||||
|     * Fixed bignumber config issue #301 (#305) | ||||
|   | ||||
| @@ -20,6 +20,6 @@ export class {{contractName}}Contract extends BaseContract { | ||||
| {{/each}} | ||||
|     constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) { | ||||
|         super(web3ContractInstance, defaults); | ||||
|         classUtils.bindAll(this, ['web3ContractInstance', 'defaults']); | ||||
|         classUtils.bindAll(this, ['_web3ContractInstance', '_defaults']); | ||||
|     } | ||||
| } // tslint:disable:max-file-line-count | ||||
| @@ -5,8 +5,8 @@ public {{this.name}} = { | ||||
|     ): Promise<{{> return_type outputs=outputs}}> { | ||||
|         const self = this as {{contractName}}Contract; | ||||
|         const result = await promisify<{{> return_type outputs=outputs}}>( | ||||
|             self.web3ContractInstance.{{this.name}}.call, | ||||
|             self.web3ContractInstance, | ||||
|             self._web3ContractInstance.{{this.name}}.call, | ||||
|             self._web3ContractInstance, | ||||
|         )( | ||||
|             {{> params inputs=inputs}} | ||||
|         ); | ||||
| @@ -9,7 +9,7 @@ public {{this.name}} = { | ||||
|     {{/this.payable}} | ||||
|     ): Promise<string> { | ||||
|         const self = this as {{contractName}}Contract; | ||||
|         const txDataWithDefaults = await self.applyDefaultsToTxDataAsync( | ||||
|         const txDataWithDefaults = await self._applyDefaultsToTxDataAsync( | ||||
|             txData, | ||||
|             self.{{this.name}}.estimateGasAsync.bind( | ||||
|                 self, | ||||
| @@ -17,7 +17,7 @@ public {{this.name}} = { | ||||
|             ), | ||||
|         ); | ||||
|         const txHash = await promisify<string>( | ||||
|             self.web3ContractInstance.{{this.name}}, self.web3ContractInstance, | ||||
|             self._web3ContractInstance.{{this.name}}, self._web3ContractInstance, | ||||
|         )( | ||||
|             {{> params inputs=inputs}} | ||||
|             txDataWithDefaults, | ||||
| @@ -29,11 +29,11 @@ public {{this.name}} = { | ||||
|         txData: TxData = {}, | ||||
|     ): Promise<number> { | ||||
|         const self = this as {{contractName}}Contract; | ||||
|         const txDataWithDefaults = await self.applyDefaultsToTxDataAsync( | ||||
|         const txDataWithDefaults = await self._applyDefaultsToTxDataAsync( | ||||
|             txData, | ||||
|         ); | ||||
|         const gas = await promisify<number>( | ||||
|             self.web3ContractInstance.{{this.name}}.estimateGas, self.web3ContractInstance, | ||||
|             self._web3ContractInstance.{{this.name}}.estimateGas, self._web3ContractInstance, | ||||
|         )( | ||||
|             {{> params inputs=inputs}} | ||||
|             txDataWithDefaults, | ||||
| @@ -45,7 +45,7 @@ public {{this.name}} = { | ||||
|         txData: TxData = {}, | ||||
|     ): string { | ||||
|         const self = this as {{contractName}}Contract; | ||||
|         const abiEncodedTransactionData = self.web3ContractInstance.{{this.name}}.getData(); | ||||
|         const abiEncodedTransactionData = self._web3ContractInstance.{{this.name}}.getData(); | ||||
|         return abiEncodedTransactionData; | ||||
|     }, | ||||
| }; | ||||
| @@ -1,34 +1,32 @@ | ||||
| { | ||||
|     "name": "0x.js", | ||||
|     "version": "0.29.0", | ||||
|     "version": "0.31.1", | ||||
|     "description": "A javascript library for interacting with the 0x protocol", | ||||
|     "keywords": ["0x.js", "0xproject", "ethereum", "tokens", "exchange"], | ||||
|     "keywords": [ | ||||
|         "0x.js", | ||||
|         "0xproject", | ||||
|         "ethereum", | ||||
|         "tokens", | ||||
|         "exchange" | ||||
|     ], | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
|     "scripts": { | ||||
|         "prebuild": "run-s clean generate_contract_wrappers", | ||||
|         "build": "run-p build:umd:prod build:commonjs; exit 0;", | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR", | ||||
|         "upload_docs_json": | ||||
|             "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json", | ||||
|         "generate_contract_wrappers": | ||||
|             "node ../abi-gen/lib/index.js --abiGlob 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --templates contract_templates --output src/contract_wrappers/generated", | ||||
|         "upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json", | ||||
|         "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template contract_templates/contract.handlebars --partials 'contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated", | ||||
|         "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", | ||||
|         "test:circleci": | ||||
|             "run-s test:coverage report_test_coverage && if [ $CIRCLE_BRANCH = \"development\" ]; then yarn test:umd; fi", | ||||
|         "test:circleci": "run-s test:coverage report_test_coverage", | ||||
|         "test": "run-s clean test:commonjs", | ||||
|         "test:umd": "./scripts/test_umd.sh", | ||||
|         "test:coverage": "nyc npm run test --all", | ||||
|         "report_test_coverage": "nyc report --reporter=text-lcov | coveralls", | ||||
|         "update_contracts": | ||||
|             "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../0x.js/src/artifacts; done;", | ||||
|         "update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../0x.js/src/artifacts; done;", | ||||
|         "clean": "shx rm -rf _bundles lib test_temp", | ||||
|         "build:umd:dev": "webpack", | ||||
|         "build:umd:prod": "NODE_ENV=production webpack", | ||||
|         "build:commonjs": "tsc && copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts;", | ||||
|         "test:commonjs": "run-s build:commonjs run_mocha", | ||||
|         "pretest:umd": "run-s clean build:umd:dev build:commonjs", | ||||
|         "substitute_umd_bundle": "shx mv _bundles/* lib/src", | ||||
|         "run_mocha": "mocha lib/test/**/*_test.js --timeout 10000 --bail --exit" | ||||
|     }, | ||||
|     "config": { | ||||
| @@ -43,10 +41,9 @@ | ||||
|         "node": ">=6.0.0" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0xproject/abi-gen": "^0.0.4", | ||||
|         "@0xproject/dev-utils": "^0.0.3", | ||||
|         "@0xproject/tslint-config": "^0.4.0", | ||||
|         "@0xproject/types": "^0.1.2", | ||||
|         "@0xproject/abi-gen": "^0.1.6", | ||||
|         "@0xproject/dev-utils": "^0.0.9", | ||||
|         "@0xproject/tslint-config": "^0.4.6", | ||||
|         "@types/bintrees": "^1.0.2", | ||||
|         "@types/jsonschema": "^1.1.1", | ||||
|         "@types/lodash": "^4.14.86", | ||||
| @@ -57,9 +54,9 @@ | ||||
|         "awesome-typescript-loader": "^3.1.3", | ||||
|         "chai": "^4.0.1", | ||||
|         "chai-as-promised": "^7.1.0", | ||||
|         "chai-as-promised-typescript-typings": "^0.0.3", | ||||
|         "chai-as-promised-typescript-typings": "^0.0.8", | ||||
|         "chai-bignumber": "^2.0.1", | ||||
|         "chai-typescript-typings": "^0.0.1", | ||||
|         "chai-typescript-typings": "^0.0.2", | ||||
|         "copyfiles": "^1.2.0", | ||||
|         "coveralls": "^3.0.0", | ||||
|         "dirty-chai": "^2.0.1", | ||||
| @@ -69,7 +66,7 @@ | ||||
|         "nyc": "^11.0.1", | ||||
|         "opn-cli": "^3.1.0", | ||||
|         "request": "^2.81.0", | ||||
|         "request-promise-native": "^1.0.4", | ||||
|         "request-promise-native": "^1.0.5", | ||||
|         "shx": "^0.2.2", | ||||
|         "sinon": "^4.0.0", | ||||
|         "source-map-support": "^0.5.0", | ||||
| @@ -78,22 +75,21 @@ | ||||
|         "typedoc": "~0.8.0", | ||||
|         "typescript": "~2.6.1", | ||||
|         "web3-provider-engine": "^13.0.1", | ||||
|         "web3-typescript-typings": "^0.9.0", | ||||
|         "web3-typescript-typings": "^0.9.8", | ||||
|         "webpack": "^3.1.0" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0xproject/assert": "^0.0.9", | ||||
|         "@0xproject/json-schemas": "^0.7.1", | ||||
|         "@0xproject/utils": "^0.1.2", | ||||
|         "@0xproject/web3-wrapper": "^0.1.2", | ||||
|         "@0xproject/assert": "^0.0.15", | ||||
|         "@0xproject/json-schemas": "^0.7.7", | ||||
|         "@0xproject/types": "^0.1.8", | ||||
|         "@0xproject/utils": "^0.2.4", | ||||
|         "@0xproject/web3-wrapper": "^0.1.9", | ||||
|         "bintrees": "^1.0.2", | ||||
|         "bn.js": "^4.11.8", | ||||
|         "compare-versions": "^3.0.1", | ||||
|         "ethereumjs-abi": "^0.6.4", | ||||
|         "ethereumjs-blockstream": "^2.0.6", | ||||
|         "ethereumjs-util": "^5.1.1", | ||||
|         "find-versions": "^2.0.0", | ||||
|         "js-sha3": "^0.6.1", | ||||
|         "js-sha3": "^0.7.0", | ||||
|         "lodash": "^4.17.4", | ||||
|         "uuid": "^3.1.0", | ||||
|         "web3": "^0.20.0" | ||||
|   | ||||
| @@ -8,26 +8,21 @@ const S3BucketPath = 's3://0xjs-docs-jsons/'; | ||||
|  | ||||
| let tag; | ||||
| let version; | ||||
| postpublish_utils.getLatestTagAndVersionAsync(subPackageName) | ||||
| postpublish_utils | ||||
|     .getLatestTagAndVersionAsync(subPackageName) | ||||
|     .then(function(result) { | ||||
|         tag = result.tag; | ||||
|         version = result.version; | ||||
|          const releaseName = postpublish_utils.getReleaseName(subPackageName, version); | ||||
|          const assets = [ | ||||
|              __dirname + '/../_bundles/index.js', | ||||
|              __dirname + '/../_bundles/index.min.js', | ||||
|          ]; | ||||
|          return postpublish_utils.publishReleaseNotes(tag, releaseName, assets); | ||||
|         const releaseName = postpublish_utils.getReleaseName(subPackageName, version); | ||||
|         const assets = [__dirname + '/../_bundles/index.js', __dirname + '/../_bundles/index.min.js']; | ||||
|         return postpublish_utils.publishReleaseNotes(tag, releaseName, assets); | ||||
|     }) | ||||
|     .then(function(release) { | ||||
|         console.log('POSTPUBLISH: Release successful, generating docs...'); | ||||
|         const jsonFilePath = __dirname + '/../' + postpublish_utils.generatedDocsDirectoryName + '/index.json'; | ||||
|         return execAsync( | ||||
|             'JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_DIR=' + __dirname + '/.. yarn docs:json', | ||||
|             { | ||||
|                 cwd, | ||||
|             } | ||||
|         ); | ||||
|         return execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_DIR=' + __dirname + '/.. yarn docs:json', { | ||||
|             cwd, | ||||
|         }); | ||||
|     }) | ||||
|     .then(function(result) { | ||||
|         if (result.stderr !== '') { | ||||
| @@ -39,6 +34,7 @@ postpublish_utils.getLatestTagAndVersionAsync(subPackageName) | ||||
|         return execAsync('S3_URL=' + s3Url + ' yarn upload_docs_json', { | ||||
|             cwd, | ||||
|         }); | ||||
|     }).catch (function(err) { | ||||
|     }) | ||||
|     .catch(function(err) { | ||||
|         throw err; | ||||
|     }); | ||||
|   | ||||
| @@ -1,6 +0,0 @@ | ||||
| #!/usr/bin/env bash | ||||
| # This script runs umd tests and cleans up after them while preserving the `return_code` for CI | ||||
| # UMD tests should only be run after building the commonjs because they reuse some of the commonjs build artifacts | ||||
| run-s substitute_umd_bundle run_mocha | ||||
| return_code=$? | ||||
| exit $return_code | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { schemas, SchemaValidator } from '@0xproject/json-schemas'; | ||||
| import { BigNumber, intervalUtils } from '@0xproject/utils'; | ||||
| import { TransactionReceiptWithDecodedLogs } from '@0xproject/types'; | ||||
| import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as ethUtil from 'ethereumjs-util'; | ||||
| import * as _ from 'lodash'; | ||||
| @@ -12,16 +13,7 @@ import { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_pr | ||||
| import { TokenWrapper } from './contract_wrappers/token_wrapper'; | ||||
| import { OrderStateWatcher } from './order_watcher/order_state_watcher'; | ||||
| import { zeroExConfigSchema } from './schemas/zero_ex_config_schema'; | ||||
| import { | ||||
|     ECSignature, | ||||
|     Order, | ||||
|     SignedOrder, | ||||
|     TransactionReceiptWithDecodedLogs, | ||||
|     Web3Provider, | ||||
|     ZeroExConfig, | ||||
|     ZeroExError, | ||||
| } from './types'; | ||||
| import { AbiDecoder } from './utils/abi_decoder'; | ||||
| import { ECSignature, Order, SignedOrder, Web3Provider, ZeroExConfig, ZeroExError } from './types'; | ||||
| import { assert } from './utils/assert'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { decorators } from './utils/decorators'; | ||||
| @@ -191,6 +183,7 @@ export class ZeroEx { | ||||
|             this._abiDecoder, | ||||
|             this.token, | ||||
|             config.exchangeContractAddress, | ||||
|             config.zrxContractAddress, | ||||
|         ); | ||||
|         this.tokenRegistry = new TokenRegistryWrapper( | ||||
|             this._web3Wrapper, | ||||
| @@ -239,20 +232,22 @@ export class ZeroEx { | ||||
|      * @param   orderHash       Hex encoded orderHash to sign. | ||||
|      * @param   signerAddress   The hex encoded Ethereum address you wish to sign it with. This address | ||||
|      *          must be available via the Web3.Provider supplied to 0x.js. | ||||
|      * @param   shouldAddPersonalMessagePrefix  Some signers add the personal message prefix `\x19Ethereum Signed Message` | ||||
|      *          themselves (e.g Parity Signer, Ledger, TestRPC) and others expect it to already be done by the client | ||||
|      *          (e.g Metamask). Depending on which signer this request is going to, decide on whether to add the prefix | ||||
|      *          before sending the request. | ||||
|      * @return  An object containing the Elliptic curve signature parameters generated by signing the orderHash. | ||||
|      */ | ||||
|     public async signOrderHashAsync(orderHash: string, signerAddress: string): Promise<ECSignature> { | ||||
|     public async signOrderHashAsync( | ||||
|         orderHash: string, | ||||
|         signerAddress: string, | ||||
|         shouldAddPersonalMessagePrefix: boolean, | ||||
|     ): Promise<ECSignature> { | ||||
|         assert.isHexString('orderHash', orderHash); | ||||
|         await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper); | ||||
|  | ||||
|         let msgHashHex; | ||||
|         const nodeVersion = await this._web3Wrapper.getNodeVersionAsync(); | ||||
|         const isParityNode = utils.isParityNode(nodeVersion); | ||||
|         const isTestRpc = utils.isTestRpc(nodeVersion); | ||||
|         if (isParityNode || isTestRpc) { | ||||
|             // Parity and TestRpc nodes add the personalMessage prefix itself | ||||
|             msgHashHex = orderHash; | ||||
|         } else { | ||||
|         let msgHashHex = orderHash; | ||||
|         if (shouldAddPersonalMessagePrefix) { | ||||
|             const orderHashBuff = ethUtil.toBuffer(orderHash); | ||||
|             const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff); | ||||
|             msgHashHex = ethUtil.bufferToHex(msgHashBuff); | ||||
| @@ -302,30 +297,37 @@ export class ZeroEx { | ||||
|  | ||||
|         const txReceiptPromise = new Promise( | ||||
|             (resolve: (receipt: TransactionReceiptWithDecodedLogs) => void, reject) => { | ||||
|                 const intervalId = intervalUtils.setAsyncExcludingInterval(async () => { | ||||
|                     if (timeoutExceeded) { | ||||
|                         intervalUtils.clearAsyncExcludingInterval(intervalId); | ||||
|                         return reject(ZeroExError.TransactionMiningTimeout); | ||||
|                     } | ||||
|                 const intervalId = intervalUtils.setAsyncExcludingInterval( | ||||
|                     async () => { | ||||
|                         if (timeoutExceeded) { | ||||
|                             intervalUtils.clearAsyncExcludingInterval(intervalId); | ||||
|                             return reject(ZeroExError.TransactionMiningTimeout); | ||||
|                         } | ||||
|  | ||||
|                     const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash); | ||||
|                     if (!_.isNull(transactionReceipt)) { | ||||
|                         const transactionReceipt = await this._web3Wrapper.getTransactionReceiptAsync(txHash); | ||||
|                         if (!_.isNull(transactionReceipt)) { | ||||
|                             intervalUtils.clearAsyncExcludingInterval(intervalId); | ||||
|                             const logsWithDecodedArgs = _.map( | ||||
|                                 transactionReceipt.logs, | ||||
|                                 this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder), | ||||
|                             ); | ||||
|                             const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = { | ||||
|                                 ...transactionReceipt, | ||||
|                                 logs: logsWithDecodedArgs, | ||||
|                             }; | ||||
|                             resolve(transactionReceiptWithDecodedLogArgs); | ||||
|                         } | ||||
|                     }, | ||||
|                     pollingIntervalMs, | ||||
|                     (err: Error) => { | ||||
|                         intervalUtils.clearAsyncExcludingInterval(intervalId); | ||||
|                         const logsWithDecodedArgs = _.map( | ||||
|                             transactionReceipt.logs, | ||||
|                             this._abiDecoder.tryToDecodeLogOrNoop.bind(this._abiDecoder), | ||||
|                         ); | ||||
|                         const transactionReceiptWithDecodedLogArgs: TransactionReceiptWithDecodedLogs = { | ||||
|                             ...transactionReceipt, | ||||
|                             logs: logsWithDecodedArgs, | ||||
|                         }; | ||||
|                         resolve(transactionReceiptWithDecodedLogArgs); | ||||
|                     } | ||||
|                 }, pollingIntervalMs); | ||||
|                         reject(err); | ||||
|                     }, | ||||
|                 ); | ||||
|             }, | ||||
|         ); | ||||
|  | ||||
|         return txReceiptPromise; | ||||
|         const txReceipt = await txReceiptPromise; | ||||
|         return txReceipt; | ||||
|     } | ||||
|     /* | ||||
|      * HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from | ||||
|   | ||||
| @@ -274,6 +274,9 @@ | ||||
|         "3": { | ||||
|             "address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a" | ||||
|         }, | ||||
|         "4": { | ||||
|             "address": "0xc778417e063141139fce010982780140aa0cd5ab" | ||||
|         }, | ||||
|         "42": { | ||||
|             "address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1" | ||||
|         }, | ||||
|   | ||||
| @@ -597,6 +597,9 @@ | ||||
|         "3": { | ||||
|             "address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac" | ||||
|         }, | ||||
|         "4": { | ||||
|             "address": "0x1d16ef40fac01cec8adac2ac49427b9384192c05" | ||||
|         }, | ||||
|         "42": { | ||||
|             "address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364" | ||||
|         }, | ||||
|   | ||||
| @@ -534,6 +534,9 @@ | ||||
|         "3": { | ||||
|             "address": "0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed" | ||||
|         }, | ||||
|         "4": { | ||||
|             "address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6" | ||||
|         }, | ||||
|         "42": { | ||||
|             "address": "0xf18e504561f4347bea557f3d4558f559dddbae7f" | ||||
|         }, | ||||
|   | ||||
| @@ -174,6 +174,9 @@ | ||||
|         "3": { | ||||
|             "address": "0x4e9aad8184de8833365fea970cd9149372fdf1e6" | ||||
|         }, | ||||
|         "4": { | ||||
|             "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d" | ||||
|         }, | ||||
|         "42": { | ||||
|             "address": "0x087eed4bc1ee3de49befbd66c662b434b15d49d4" | ||||
|         }, | ||||
|   | ||||
| @@ -7,6 +7,9 @@ | ||||
|         "3": { | ||||
|             "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d" | ||||
|         }, | ||||
|         "4": { | ||||
|             "address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8" | ||||
|         }, | ||||
|         "42": { | ||||
|             "address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570" | ||||
|         }, | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import { intervalUtils } from '@0xproject/utils'; | ||||
| import { LogWithDecodedArgs, RawLog } from '@0xproject/types'; | ||||
| import { AbiDecoder, intervalUtils } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream'; | ||||
| import * as _ from 'lodash'; | ||||
| @@ -13,11 +14,8 @@ import { | ||||
|     EventCallback, | ||||
|     IndexedFilterValues, | ||||
|     InternalZeroExError, | ||||
|     LogWithDecodedArgs, | ||||
|     RawLog, | ||||
|     ZeroExError, | ||||
| } from '../types'; | ||||
| import { AbiDecoder } from '../utils/abi_decoder'; | ||||
| import { constants } from '../utils/constants'; | ||||
| import { filterUtils } from '../utils/filter_utils'; | ||||
|  | ||||
| @@ -54,7 +52,7 @@ export class ContractWrapper { | ||||
|         this._onLogAddedSubscriptionToken = undefined; | ||||
|         this._onLogRemovedSubscriptionToken = undefined; | ||||
|     } | ||||
|     protected unsubscribeAll(): void { | ||||
|     protected _unsubscribeAll(): void { | ||||
|         const filterTokens = _.keys(this._filterCallbacks); | ||||
|         _.each(filterTokens, filterToken => { | ||||
|             this._unsubscribe(filterToken); | ||||
| @@ -167,6 +165,7 @@ export class ContractWrapper { | ||||
|         this._blockAndLogStreamInterval = intervalUtils.setAsyncExcludingInterval( | ||||
|             this._reconcileBlockAsync.bind(this), | ||||
|             constants.DEFAULT_BLOCK_POLLING_INTERVAL, | ||||
|             this._onReconcileBlockError.bind(this), | ||||
|         ); | ||||
|         let isRemoved = false; | ||||
|         this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded( | ||||
| @@ -177,6 +176,12 @@ export class ContractWrapper { | ||||
|             this._onLogStateChanged.bind(this, isRemoved), | ||||
|         ); | ||||
|     } | ||||
|     private _onReconcileBlockError(err: Error): void { | ||||
|         const filterTokens = _.keys(this._filterCallbacks); | ||||
|         _.each(filterTokens, filterToken => { | ||||
|             this._unsubscribe(filterToken, err); | ||||
|         }); | ||||
|     } | ||||
|     private _setNetworkId(networkId: number): void { | ||||
|         this._networkId = networkId; | ||||
|     } | ||||
| @@ -190,18 +195,11 @@ export class ContractWrapper { | ||||
|         delete this._blockAndLogStreamerIfExists; | ||||
|     } | ||||
|     private async _reconcileBlockAsync(): Promise<void> { | ||||
|         try { | ||||
|             const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest); | ||||
|             // We need to coerce to Block type cause Web3.Block includes types for mempool blocks | ||||
|             if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { | ||||
|                 // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined | ||||
|                 await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block); | ||||
|             } | ||||
|         } catch (err) { | ||||
|             const filterTokens = _.keys(this._filterCallbacks); | ||||
|             _.each(filterTokens, filterToken => { | ||||
|                 this._unsubscribe(filterToken, err); | ||||
|             }); | ||||
|         const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest); | ||||
|         // We need to coerce to Block type cause Web3.Block includes types for mempool blocks | ||||
|         if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { | ||||
|             // If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined | ||||
|             await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { schemas } from '@0xproject/json-schemas'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { LogWithDecodedArgs } from '@0xproject/types'; | ||||
| import { AbiDecoder, BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| @@ -10,11 +11,9 @@ import { | ||||
|     EtherTokenEvents, | ||||
|     EventCallback, | ||||
|     IndexedFilterValues, | ||||
|     LogWithDecodedArgs, | ||||
|     TransactionOpts, | ||||
|     ZeroExError, | ||||
| } from '../types'; | ||||
| import { AbiDecoder } from '../utils/abi_decoder'; | ||||
| import { assert } from '../utils/assert'; | ||||
|  | ||||
| import { ContractWrapper } from './contract_wrapper'; | ||||
| @@ -160,11 +159,11 @@ export class EtherTokenWrapper extends ContractWrapper { | ||||
|     /** | ||||
|      * Cancels all existing subscriptions | ||||
|      */ | ||||
|     public unsubscribeAll(): void { | ||||
|         super.unsubscribeAll(); | ||||
|     public _unsubscribeAll(): void { | ||||
|         super._unsubscribeAll(); | ||||
|     } | ||||
|     private _invalidateContractInstance(): void { | ||||
|         this.unsubscribeAll(); | ||||
|         this._unsubscribeAll(); | ||||
|         this._etherTokenContractsByAddress = {}; | ||||
|     } | ||||
|     private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<EtherTokenContract> { | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { schemas } from '@0xproject/json-schemas'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { DecodedLogArgs, LogWithDecodedArgs } from '@0xproject/types'; | ||||
| import { AbiDecoder, BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as _ from 'lodash'; | ||||
| import * as Web3 from 'web3'; | ||||
| @@ -8,7 +9,6 @@ import { artifacts } from '../artifacts'; | ||||
| import { | ||||
|     BlockParamLiteral, | ||||
|     BlockRange, | ||||
|     DecodedLogArgs, | ||||
|     ECSignature, | ||||
|     EventCallback, | ||||
|     ExchangeContractErrCodes, | ||||
| @@ -17,7 +17,6 @@ import { | ||||
|     ExchangeEvents, | ||||
|     IndexedFilterValues, | ||||
|     LogErrorContractEventArgs, | ||||
|     LogWithDecodedArgs, | ||||
|     MethodOpts, | ||||
|     Order, | ||||
|     OrderAddresses, | ||||
| @@ -28,7 +27,6 @@ import { | ||||
|     SignedOrder, | ||||
|     ValidateOrderFillableOpts, | ||||
| } from '../types'; | ||||
| import { AbiDecoder } from '../utils/abi_decoder'; | ||||
| import { assert } from '../utils/assert'; | ||||
| import { decorators } from '../utils/decorators'; | ||||
| import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator'; | ||||
| @@ -87,11 +85,13 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         abiDecoder: AbiDecoder, | ||||
|         tokenWrapper: TokenWrapper, | ||||
|         contractAddressIfExists?: string, | ||||
|         zrxContractAddressIfExists?: string, | ||||
|     ) { | ||||
|         super(web3Wrapper, networkId, abiDecoder); | ||||
|         this._tokenWrapper = tokenWrapper; | ||||
|         this._orderValidationUtils = new OrderValidationUtils(this); | ||||
|         this._contractAddressIfExists = contractAddressIfExists; | ||||
|         this._zrxContractAddressIfExists = zrxContractAddressIfExists; | ||||
|     } | ||||
|     /** | ||||
|      * Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total | ||||
| @@ -258,16 +258,18 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|             ? SHOULD_VALIDATE_BY_DEFAULT | ||||
|             : orderTransactionOpts.shouldValidate; | ||||
|         if (shouldValidate) { | ||||
|             let filledTakerTokenAmount = new BigNumber(0); | ||||
|             const zrxTokenAddress = this.getZRXTokenAddress(); | ||||
|             const exchangeTradeEmulator = new ExchangeTransferSimulator(this._tokenWrapper, BlockParamLiteral.Latest); | ||||
|             for (const signedOrder of signedOrders) { | ||||
|                 await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( | ||||
|                 const singleFilledTakerTokenAmount = await this._orderValidationUtils.validateFillOrderThrowIfInvalidAsync( | ||||
|                     exchangeTradeEmulator, | ||||
|                     signedOrder, | ||||
|                     fillTakerTokenAmount, | ||||
|                     fillTakerTokenAmount.minus(filledTakerTokenAmount), | ||||
|                     takerAddress, | ||||
|                     zrxTokenAddress, | ||||
|                 ); | ||||
|                 filledTakerTokenAmount = filledTakerTokenAmount.plus(singleFilledTakerTokenAmount); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -676,8 +678,8 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|     /** | ||||
|      * Cancels all existing subscriptions | ||||
|      */ | ||||
|     public unsubscribeAll(): void { | ||||
|         super.unsubscribeAll(); | ||||
|     public _unsubscribeAll(): void { | ||||
|         super._unsubscribeAll(); | ||||
|     } | ||||
|     /** | ||||
|      * Gets historical logs without creating a subscription | ||||
| @@ -842,9 +844,9 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|     public throwLogErrorsAsErrors(logs: Array<LogWithDecodedArgs<DecodedLogArgs> | Web3.LogEntry>): void { | ||||
|         const errLog = _.find(logs, { | ||||
|             event: ExchangeEvents.LogError, | ||||
|         }) as LogWithDecodedArgs<LogErrorContractEventArgs> | undefined; | ||||
|         }); | ||||
|         if (!_.isUndefined(errLog)) { | ||||
|             const logArgs = errLog.args; | ||||
|             const logArgs = (errLog as LogWithDecodedArgs<LogErrorContractEventArgs>).args; | ||||
|             const errCode = logArgs.errorId.toNumber(); | ||||
|             const errMessage = this._exchangeContractErrCodesToMsg[errCode]; | ||||
|             throw new Error(errMessage); | ||||
| @@ -859,7 +861,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         return contractAddress; | ||||
|     } | ||||
|     private _invalidateContractInstances(): void { | ||||
|         this.unsubscribeAll(); | ||||
|         this._unsubscribeAll(); | ||||
|         delete this._exchangeContractIfExists; | ||||
|     } | ||||
|     private async _isValidSignatureUsingContractCallAsync( | ||||
|   | ||||
| @@ -3,9 +3,9 @@ import * as _ from 'lodash'; | ||||
| import * as Web3 from 'web3'; | ||||
|  | ||||
| export class BaseContract { | ||||
|     protected web3ContractInstance: Web3.ContractInstance; | ||||
|     protected defaults: Partial<TxData>; | ||||
|     protected async applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>( | ||||
|     protected _web3ContractInstance: Web3.ContractInstance; | ||||
|     protected _defaults: Partial<TxData>; | ||||
|     protected async _applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>( | ||||
|         txData: T, | ||||
|         estimateGasAsync?: (txData: T) => Promise<number>, | ||||
|     ): Promise<TxData> { | ||||
| @@ -15,7 +15,7 @@ export class BaseContract { | ||||
|         // 3. Gas estimate calculation + safety margin | ||||
|         const removeUndefinedProperties = _.pickBy; | ||||
|         const txDataWithDefaults = { | ||||
|             ...removeUndefinedProperties(this.defaults), | ||||
|             ...removeUndefinedProperties(this._defaults), | ||||
|             ...removeUndefinedProperties(txData as any), | ||||
|             // HACK: TS can't prove that T is spreadable. | ||||
|             // Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged | ||||
| @@ -27,7 +27,7 @@ export class BaseContract { | ||||
|         return txDataWithDefaults; | ||||
|     } | ||||
|     constructor(web3ContractInstance: Web3.ContractInstance, defaults: Partial<TxData>) { | ||||
|         this.web3ContractInstance = web3ContractInstance; | ||||
|         this.defaults = defaults; | ||||
|         this._web3ContractInstance = web3ContractInstance; | ||||
|         this._defaults = defaults; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { schemas } from '@0xproject/json-schemas'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { LogWithDecodedArgs } from '@0xproject/types'; | ||||
| import { AbiDecoder, BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| @@ -8,14 +9,12 @@ import { | ||||
|     BlockRange, | ||||
|     EventCallback, | ||||
|     IndexedFilterValues, | ||||
|     LogWithDecodedArgs, | ||||
|     MethodOpts, | ||||
|     TokenContractEventArgs, | ||||
|     TokenEvents, | ||||
|     TransactionOpts, | ||||
|     ZeroExError, | ||||
| } from '../types'; | ||||
| import { AbiDecoder } from '../utils/abi_decoder'; | ||||
| import { assert } from '../utils/assert'; | ||||
| import { constants } from '../utils/constants'; | ||||
|  | ||||
| @@ -343,8 +342,8 @@ export class TokenWrapper extends ContractWrapper { | ||||
|     /** | ||||
|      * Cancels all existing subscriptions | ||||
|      */ | ||||
|     public unsubscribeAll(): void { | ||||
|         super.unsubscribeAll(); | ||||
|     public _unsubscribeAll(): void { | ||||
|         super._unsubscribeAll(); | ||||
|     } | ||||
|     /** | ||||
|      * Gets historical logs without creating a subscription | ||||
| @@ -375,7 +374,7 @@ export class TokenWrapper extends ContractWrapper { | ||||
|         return logs; | ||||
|     } | ||||
|     private _invalidateContractInstances(): void { | ||||
|         this.unsubscribeAll(); | ||||
|         this._unsubscribeAll(); | ||||
|         this._tokenContractsByAddress = {}; | ||||
|     } | ||||
|     private async _getTokenContractAsync(tokenAddress: string): Promise<TokenContract> { | ||||
|   | ||||
							
								
								
									
										30
									
								
								packages/0x.js/src/globals.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								packages/0x.js/src/globals.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,3 @@ | ||||
| /// <reference types='chai-typescript-typings' /> | ||||
| /// <reference types='chai-as-promised-typescript-typings' /> | ||||
| declare module 'web3_beta'; | ||||
| declare module 'chai-bignumber'; | ||||
| declare module 'dirty-chai'; | ||||
| @@ -27,18 +25,6 @@ declare module '*.json' { | ||||
|     /* tslint:enable */ | ||||
| } | ||||
|  | ||||
| // find-version declarations | ||||
| declare function findVersions(version: string): string[]; | ||||
| declare module 'find-versions' { | ||||
|     export = findVersions; | ||||
| } | ||||
|  | ||||
| // compare-version declarations | ||||
| declare function compareVersions(firstVersion: string, secondVersion: string): number; | ||||
| declare module 'compare-versions' { | ||||
|     export = compareVersions; | ||||
| } | ||||
|  | ||||
| declare module 'ethereumjs-abi' { | ||||
|     const soliditySHA3: (argTypes: string[], args: any[]) => Buffer; | ||||
| } | ||||
| @@ -55,19 +41,3 @@ declare module 'truffle-hdwallet-provider' { | ||||
|     } | ||||
|     export = HDWalletProvider; | ||||
| } | ||||
|  | ||||
| // abi-decoder declarations | ||||
| interface DecodedLogArg {} | ||||
| interface DecodedLog { | ||||
|     name: string; | ||||
|     events: DecodedLogArg[]; | ||||
| } | ||||
| declare module 'abi-decoder' { | ||||
|     import * as Web3 from 'web3'; | ||||
|     const addABI: (abi: Web3.AbiDefinition) => void; | ||||
|     const decodeLogs: (logs: Web3.LogEntry[]) => DecodedLog[]; | ||||
| } | ||||
|  | ||||
| declare module 'web3/lib/solidity/coder' { | ||||
|     const decodeParams: (types: string[], data: string) => any[]; | ||||
| } | ||||
|   | ||||
| @@ -28,12 +28,9 @@ export { | ||||
|     WithdrawalContractEventArgs, | ||||
|     DepositContractEventArgs, | ||||
|     ContractEventArgs, | ||||
|     ContractEventArg, | ||||
|     Web3Provider, | ||||
|     ZeroExConfig, | ||||
|     EtherTokenEvents, | ||||
|     TransactionReceiptWithDecodedLogs, | ||||
|     LogWithDecodedArgs, | ||||
|     MethodOpts, | ||||
|     OrderTransactionOpts, | ||||
|     TransactionOpts, | ||||
| @@ -47,4 +44,6 @@ export { | ||||
|     OrderState, | ||||
| } from './types'; | ||||
|  | ||||
| export { ContractEventArg, LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from '@0xproject/types'; | ||||
|  | ||||
| export { TransactionReceipt } from '@0xproject/types'; | ||||
|   | ||||
| @@ -36,6 +36,10 @@ export class EventWatcher { | ||||
|         this._intervalIdIfExists = intervalUtils.setAsyncExcludingInterval( | ||||
|             this._pollForBlockchainEventsAsync.bind(this, callback), | ||||
|             this._pollingIntervalMs, | ||||
|             (err: Error) => { | ||||
|                 this.unsubscribe(); | ||||
|                 callback(err); | ||||
|             }, | ||||
|         ); | ||||
|     } | ||||
|     public unsubscribe(): void { | ||||
| @@ -47,6 +51,10 @@ export class EventWatcher { | ||||
|     } | ||||
|     private async _pollForBlockchainEventsAsync(callback: EventWatcherCallback): Promise<void> { | ||||
|         const pendingEvents = await this._getEventsAsync(); | ||||
|         if (_.isUndefined(pendingEvents)) { | ||||
|             // HACK: This should never happen, but happens frequently on CI due to a ganache bug | ||||
|             return; | ||||
|         } | ||||
|         if (pendingEvents.length === 0) { | ||||
|             // HACK: Sometimes when node rebuilds the pending block we get back the empty result. | ||||
|             // We don't want to emit a lot of removal events and bring them back after a couple of miliseconds, | ||||
| @@ -78,7 +86,7 @@ export class EventWatcher { | ||||
|                 ...log, | ||||
|             }; | ||||
|             if (!_.isUndefined(this._intervalIdIfExists)) { | ||||
|                 callback(logEvent); | ||||
|                 callback(null, logEvent); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -30,16 +30,17 @@ export class ExpirationWatcher { | ||||
|         if (!_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) { | ||||
|             throw new Error(ZeroExError.SubscriptionAlreadyPresent); | ||||
|         } | ||||
|         this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval( | ||||
|         this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setInterval( | ||||
|             this._pruneExpiredOrders.bind(this, callback), | ||||
|             this._orderExpirationCheckingIntervalMs, | ||||
|             _.noop, // _pruneExpiredOrders never throws | ||||
|         ); | ||||
|     } | ||||
|     public unsubscribe(): void { | ||||
|         if (_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) { | ||||
|             throw new Error(ZeroExError.SubscriptionNotFound); | ||||
|         } | ||||
|         intervalUtils.clearAsyncExcludingInterval(this._orderExpirationCheckingIntervalIdIfExists); | ||||
|         intervalUtils.clearInterval(this._orderExpirationCheckingIntervalIdIfExists); | ||||
|         delete this._orderExpirationCheckingIntervalIdIfExists; | ||||
|     } | ||||
|     public addOrder(orderHash: string, expirationUnixTimestampMs: BigNumber): void { | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { schemas } from '@0xproject/json-schemas'; | ||||
| import { intervalUtils } from '@0xproject/utils'; | ||||
| import { LogWithDecodedArgs } from '@0xproject/types'; | ||||
| import { AbiDecoder, intervalUtils } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| @@ -19,7 +20,6 @@ import { | ||||
|     LogCancelContractEventArgs, | ||||
|     LogEvent, | ||||
|     LogFillContractEventArgs, | ||||
|     LogWithDecodedArgs, | ||||
|     OnOrderStateChangeCallback, | ||||
|     OrderState, | ||||
|     OrderStateWatcherConfig, | ||||
| @@ -29,7 +29,6 @@ import { | ||||
|     WithdrawalContractEventArgs, | ||||
|     ZeroExError, | ||||
| } from '../types'; | ||||
| import { AbiDecoder } from '../utils/abi_decoder'; | ||||
| import { assert } from '../utils/assert'; | ||||
| import { OrderStateUtils } from '../utils/order_state_utils'; | ||||
| import { utils } from '../utils/utils'; | ||||
| @@ -134,8 +133,12 @@ export class OrderStateWatcher { | ||||
|         delete this._orderStateByOrderHashCache[orderHash]; | ||||
|         const exchange = (this._orderFilledCancelledLazyStore as any)._exchange as ExchangeWrapper; | ||||
|         const zrxTokenAddress = exchange.getZRXTokenAddress(); | ||||
|  | ||||
|         this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash); | ||||
|         this._removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash); | ||||
|         if (zrxTokenAddress !== signedOrder.makerTokenAddress) { | ||||
|             this._removeFromDependentOrderHashes(signedOrder.maker, signedOrder.makerTokenAddress, orderHash); | ||||
|         } | ||||
|  | ||||
|         this._expirationWatcher.removeOrder(orderHash); | ||||
|     } | ||||
|     /** | ||||
| @@ -155,6 +158,10 @@ export class OrderStateWatcher { | ||||
|         this._cleanupJobIntervalIdIfExists = intervalUtils.setAsyncExcludingInterval( | ||||
|             this._cleanupAsync.bind(this), | ||||
|             this._cleanupJobInterval, | ||||
|             (err: Error) => { | ||||
|                 this.unsubscribe(); | ||||
|                 callback(err); | ||||
|             }, | ||||
|         ); | ||||
|     } | ||||
|     /** | ||||
| @@ -207,17 +214,25 @@ export class OrderStateWatcher { | ||||
|         if (!_.isUndefined(this._orderByOrderHash[orderHash])) { | ||||
|             this.removeOrder(orderHash); | ||||
|             if (!_.isUndefined(this._callbackIfExists)) { | ||||
|                 this._callbackIfExists(orderState); | ||||
|                 this._callbackIfExists(null, orderState); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     private async _onEventWatcherCallbackAsync(log: LogEvent): Promise<void> { | ||||
|         const maybeDecodedLog = this._abiDecoder.tryToDecodeLogOrNoop(log); | ||||
|         const isLogDecoded = !_.isUndefined((maybeDecodedLog as LogWithDecodedArgs<any>).event); | ||||
|     private async _onEventWatcherCallbackAsync(err: Error | null, logIfExists?: LogEvent): Promise<void> { | ||||
|         if (!_.isNull(err)) { | ||||
|             if (!_.isUndefined(this._callbackIfExists)) { | ||||
|                 this._callbackIfExists(err); | ||||
|                 this.unsubscribe(); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         const log = logIfExists as LogEvent; // At this moment we are sure that no error occured and log is defined. | ||||
|         const maybeDecodedLog = this._abiDecoder.tryToDecodeLogOrNoop<ContractEventArgs>(log); | ||||
|         const isLogDecoded = !_.isUndefined(((maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>).event); | ||||
|         if (!isLogDecoded) { | ||||
|             return; // noop | ||||
|         } | ||||
|         const decodedLog = maybeDecodedLog as LogWithDecodedArgs<ContractEventArgs>; | ||||
|         const decodedLog = (maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>; | ||||
|         let makerToken: string; | ||||
|         let makerAddress: string; | ||||
|         switch (decodedLog.event) { | ||||
| @@ -332,7 +347,7 @@ export class OrderStateWatcher { | ||||
|             } else { | ||||
|                 this._orderStateByOrderHashCache[orderHash] = orderState; | ||||
|             } | ||||
|             this._callbackIfExists(orderState); | ||||
|             this._callbackIfExists(null, orderState); | ||||
|         } | ||||
|     } | ||||
|     private _addToDependentOrderHashes(signedOrder: SignedOrder, orderHash: string): void { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { TransactionReceipt } from '@0xproject/types'; | ||||
| import { ContractEventArg, LogWithDecodedArgs } from '@0xproject/types'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as Web3 from 'web3'; | ||||
|  | ||||
| @@ -51,14 +51,7 @@ export interface DecodedLogEvent<ArgsType> { | ||||
| } | ||||
|  | ||||
| export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void; | ||||
| export type EventWatcherCallback = (log: LogEvent) => void; | ||||
|  | ||||
| export enum SolidityTypes { | ||||
|     Address = 'address', | ||||
|     Uint256 = 'uint256', | ||||
|     Uint8 = 'uint8', | ||||
|     Uint = 'uint', | ||||
| } | ||||
| export type EventWatcherCallback = (err: null | Error, log?: LogEvent) => void; | ||||
|  | ||||
| export enum ExchangeContractErrCodes { | ||||
|     ERROR_FILL_EXPIRED, // Order has already expired | ||||
| @@ -94,8 +87,6 @@ export enum ExchangeContractErrs { | ||||
|     BatchOrdersMustHaveAtLeastOneItem = 'BATCH_ORDERS_MUST_HAVE_AT_LEAST_ONE_ITEM', | ||||
| } | ||||
|  | ||||
| export type RawLog = Web3.LogEntry; | ||||
|  | ||||
| export interface ContractEvent { | ||||
|     logIndex: number; | ||||
|     transactionIndex: number; | ||||
| @@ -163,7 +154,6 @@ export type EtherTokenContractEventArgs = | ||||
|     | DepositContractEventArgs | ||||
|     | WithdrawalContractEventArgs; | ||||
| export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs; | ||||
| export type ContractEventArg = string | BigNumber; | ||||
|  | ||||
| export interface Order { | ||||
|     maker: string; | ||||
| @@ -267,11 +257,6 @@ export type SyncMethod = (...args: any[]) => any; | ||||
|  */ | ||||
| export type Web3Provider = Web3.Provider; | ||||
|  | ||||
| export interface JSONRPCPayload { | ||||
|     params: any[]; | ||||
|     method: string; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * orderExpirationCheckingIntervalMs: How often to check for expired orders. Default: 50 | ||||
|  * eventPollingIntervalMs: How often to poll the Ethereum node for new events. Defaults: 200 | ||||
| @@ -290,6 +275,7 @@ export interface OrderStateWatcherConfig { | ||||
|  * networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 42-kovan, 50-testrpc) | ||||
|  * gasPrice: Gas price to use with every transaction | ||||
|  * exchangeContractAddress: The address of an exchange contract to use | ||||
|  * zrxContractAddress: The address of the ZRX contract to use | ||||
|  * tokenRegistryContractAddress: The address of a token registry contract to use | ||||
|  * tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use | ||||
|  * orderWatcherConfig: All the configs related to the orderWatcher | ||||
| @@ -298,28 +284,12 @@ export interface ZeroExConfig { | ||||
|     networkId: number; | ||||
|     gasPrice?: BigNumber; | ||||
|     exchangeContractAddress?: string; | ||||
|     zrxContractAddress?: string; | ||||
|     tokenRegistryContractAddress?: string; | ||||
|     tokenTransferProxyContractAddress?: string; | ||||
|     orderWatcherConfig?: OrderStateWatcherConfig; | ||||
| } | ||||
|  | ||||
| export enum AbiType { | ||||
|     Function = 'function', | ||||
|     Constructor = 'constructor', | ||||
|     Event = 'event', | ||||
|     Fallback = 'fallback', | ||||
| } | ||||
|  | ||||
| export interface DecodedLogArgs { | ||||
|     [argName: string]: ContractEventArg; | ||||
| } | ||||
|  | ||||
| export interface LogWithDecodedArgs<ArgsType> extends Web3.DecodedLogEntry<ArgsType> {} | ||||
|  | ||||
| export interface TransactionReceiptWithDecodedLogs extends TransactionReceipt { | ||||
|     logs: Array<LogWithDecodedArgs<DecodedLogArgs> | Web3.LogEntry>; | ||||
| } | ||||
|  | ||||
| export type ArtifactContractName = 'ZRX' | 'TokenTransferProxy' | 'TokenRegistry' | 'Token' | 'Exchange' | 'EtherToken'; | ||||
|  | ||||
| export interface Artifact { | ||||
| @@ -406,5 +376,5 @@ export interface OrderStateInvalid { | ||||
|  | ||||
| export type OrderState = OrderStateValid | OrderStateInvalid; | ||||
|  | ||||
| export type OnOrderStateChangeCallback = (orderState: OrderState) => void; | ||||
| export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void; | ||||
| // tslint:disable:max-file-line-count | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| import { SolidityTypes } from '@0xproject/types'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import BN = require('bn.js'); | ||||
| import * as ethABI from 'ethereumjs-abi'; | ||||
| import * as ethUtil from 'ethereumjs-util'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { Order, SignedOrder, SolidityTypes } from '../types'; | ||||
| import { Order, SignedOrder } from '../types'; | ||||
|  | ||||
| export const utils = { | ||||
|     /** | ||||
| @@ -20,12 +21,6 @@ export const utils = { | ||||
|         // tslint:disable-next-line: no-console | ||||
|         console.log(message); | ||||
|     }, | ||||
|     isParityNode(nodeVersion: string): boolean { | ||||
|         return _.includes(nodeVersion, 'Parity'); | ||||
|     }, | ||||
|     isTestRpc(nodeVersion: string): boolean { | ||||
|         return _.includes(nodeVersion, 'TestRPC'); | ||||
|     }, | ||||
|     spawnSwitchErr(name: string, value: any): Error { | ||||
|         return new Error(`Unexpected switch value: ${value} encountered for ${name}`); | ||||
|     }, | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import * as _ from 'lodash'; | ||||
| @@ -10,12 +10,13 @@ import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, Zero | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { TokenUtils } from './utils/token_utils'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
|  | ||||
| const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false; | ||||
|  | ||||
| describe('ZeroEx library', () => { | ||||
|     const web3 = web3Factory.create(); | ||||
|     const config = { | ||||
| @@ -198,7 +199,11 @@ describe('ZeroEx library', () => { | ||||
|                 r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33', | ||||
|                 s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', | ||||
|             }; | ||||
|             const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress); | ||||
|             const ecSignature = await zeroEx.signOrderHashAsync( | ||||
|                 orderHash, | ||||
|                 makerAddress, | ||||
|                 SHOULD_ADD_PERSONAL_MESSAGE_PREFIX, | ||||
|             ); | ||||
|             expect(ecSignature).to.deep.equal(expectedECSignature); | ||||
|         }); | ||||
|         it('should return the correct ECSignature for signatureHex concatenated as R + S + V', async () => { | ||||
| @@ -215,7 +220,11 @@ describe('ZeroEx library', () => { | ||||
|                 Sinon.stub(ZeroEx, 'isValidSignature').returns(true), | ||||
|             ]; | ||||
|  | ||||
|             const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress); | ||||
|             const ecSignature = await zeroEx.signOrderHashAsync( | ||||
|                 orderHash, | ||||
|                 makerAddress, | ||||
|                 SHOULD_ADD_PERSONAL_MESSAGE_PREFIX, | ||||
|             ); | ||||
|             expect(ecSignature).to.deep.equal(expectedECSignature); | ||||
|         }); | ||||
|         it('should return the correct ECSignature for signatureHex concatenated as V + R + S', async () => { | ||||
| @@ -232,7 +241,11 @@ describe('ZeroEx library', () => { | ||||
|                 Sinon.stub(ZeroEx, 'isValidSignature').returns(true), | ||||
|             ]; | ||||
|  | ||||
|             const ecSignature = await zeroEx.signOrderHashAsync(orderHash, makerAddress); | ||||
|             const ecSignature = await zeroEx.signOrderHashAsync( | ||||
|                 orderHash, | ||||
|                 makerAddress, | ||||
|                 SHOULD_ADD_PERSONAL_MESSAGE_PREFIX, | ||||
|             ); | ||||
|             expect(ecSignature).to.deep.equal(expectedECSignature); | ||||
|         }); | ||||
|     }); | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| import { web3Factory } from '@0xproject/dev-utils'; | ||||
| import * as chai from 'chai'; | ||||
| import 'mocha'; | ||||
|  | ||||
| @@ -5,7 +6,6 @@ import { ZeroEx } from '../src'; | ||||
| import { assert } from '../src/utils/assert'; | ||||
|  | ||||
| import { constants } from './utils/constants'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| const expect = chai.expect; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import 'mocha'; | ||||
| @@ -24,11 +24,10 @@ import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { reportNodeCallbackErrors } from './utils/report_callback_errors'; | ||||
| import { TokenUtils } from './utils/token_utils'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| // Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction, | ||||
| // a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between | ||||
| @@ -145,7 +144,7 @@ describe('EtherTokenWrapper', () => { | ||||
|             etherTokenAddress = etherToken.address; | ||||
|         }); | ||||
|         afterEach(() => { | ||||
|             zeroEx.etherToken.unsubscribeAll(); | ||||
|             zeroEx.etherToken._unsubscribeAll(); | ||||
|         }); | ||||
|         // Hack: Mocha does not allow a test to be both async and have a `done` callback | ||||
|         // Since we need to await the receipt of the event in the `subscribe` callback, | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| import { web3Factory } from '@0xproject/dev-utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import * as _ from 'lodash'; | ||||
| @@ -10,7 +11,7 @@ import { EventWatcher } from '../src/order_watcher/event_watcher'; | ||||
| import { DoneCallback } from '../src/types'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
| import { reportNodeCallbackErrors } from './utils/report_callback_errors'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| @@ -77,13 +78,14 @@ describe('EventWatcher', () => { | ||||
|         const getLogsStub = Sinon.stub(web3Wrapper, 'getLogsAsync'); | ||||
|         getLogsStub.onCall(0).returns(logs); | ||||
|         stubs.push(getLogsStub); | ||||
|         const callback = (event: LogEvent) => { | ||||
|         const expectedToBeCalledOnce = false; | ||||
|         const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => { | ||||
|             const expectedLogEvent = expectedLogEvents.shift(); | ||||
|             expect(event).to.be.deep.equal(expectedLogEvent); | ||||
|             if (_.isEmpty(expectedLogEvents)) { | ||||
|                 done(); | ||||
|             } | ||||
|         }; | ||||
|         }); | ||||
|         eventWatcher.subscribe(callback); | ||||
|     }); | ||||
|     it('correctly computes the difference and emits only changes', (done: DoneCallback) => { | ||||
| @@ -111,13 +113,14 @@ describe('EventWatcher', () => { | ||||
|         getLogsStub.onCall(0).returns(initialLogs); | ||||
|         getLogsStub.onCall(1).returns(changedLogs); | ||||
|         stubs.push(getLogsStub); | ||||
|         const callback = (event: LogEvent) => { | ||||
|         const expectedToBeCalledOnce = false; | ||||
|         const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => { | ||||
|             const expectedLogEvent = expectedLogEvents.shift(); | ||||
|             expect(event).to.be.deep.equal(expectedLogEvent); | ||||
|             if (_.isEmpty(expectedLogEvents)) { | ||||
|                 done(); | ||||
|             } | ||||
|         }; | ||||
|         }); | ||||
|         eventWatcher.subscribe(callback); | ||||
|     }); | ||||
| }); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
|  | ||||
| @@ -8,11 +8,10 @@ import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simula | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| describe('ExchangeTransferSimulator', () => { | ||||
|     const web3 = web3Factory.create(); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import * as _ from 'lodash'; | ||||
| @@ -25,11 +25,10 @@ import { constants } from './utils/constants'; | ||||
| import { FillScenarios } from './utils/fill_scenarios'; | ||||
| import { reportNodeCallbackErrors } from './utils/report_callback_errors'; | ||||
| import { TokenUtils } from './utils/token_utils'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| const NON_EXISTENT_ORDER_HASH = '0x79370342234e7acd6bbeac335bd3bb1d368383294b64b8160a00f4060e4d3777'; | ||||
|  | ||||
| @@ -390,6 +389,29 @@ describe('ExchangeWrapper', () => { | ||||
|                     ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); | ||||
|                 }); | ||||
|             }); | ||||
|             describe('negative fill amount', async () => { | ||||
|                 let signedOrder: SignedOrder; | ||||
|                 const negativeFillTakerAmount = new BigNumber(-100); | ||||
|                 beforeEach(async () => { | ||||
|                     signedOrder = await fillScenarios.createFillableSignedOrderAsync( | ||||
|                         makerTokenAddress, | ||||
|                         takerTokenAddress, | ||||
|                         makerAddress, | ||||
|                         takerAddress, | ||||
|                         fillableAmount, | ||||
|                     ); | ||||
|                 }); | ||||
|                 it('should not allow the exchange wrapper to fill if amount is negative', async () => { | ||||
|                     return expect( | ||||
|                         zeroEx.exchange.fillOrderAsync( | ||||
|                             signedOrder, | ||||
|                             negativeFillTakerAmount, | ||||
|                             shouldThrowOnInsufficientBalanceOrAllowance, | ||||
|                             takerAddress, | ||||
|                         ), | ||||
|                     ).to.be.rejected(); | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|         describe('#batchFillOrdersAsync', () => { | ||||
|             let signedOrder: SignedOrder; | ||||
| @@ -498,6 +520,30 @@ describe('ExchangeWrapper', () => { | ||||
|                     ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); | ||||
|                 }); | ||||
|             }); | ||||
|             describe('negative batch fill amount', async () => { | ||||
|                 beforeEach(async () => { | ||||
|                     const negativeFillTakerAmount = new BigNumber(-100); | ||||
|                     orderFillBatch = [ | ||||
|                         { | ||||
|                             signedOrder, | ||||
|                             takerTokenFillAmount, | ||||
|                         }, | ||||
|                         { | ||||
|                             signedOrder: anotherSignedOrder, | ||||
|                             takerTokenFillAmount: negativeFillTakerAmount, | ||||
|                         }, | ||||
|                     ]; | ||||
|                 }); | ||||
|                 it('should not allow the exchange wrapper to batch fill if any amount is negative', async () => { | ||||
|                     return expect( | ||||
|                         zeroEx.exchange.batchFillOrdersAsync( | ||||
|                             orderFillBatch, | ||||
|                             shouldThrowOnInsufficientBalanceOrAllowance, | ||||
|                             takerAddress, | ||||
|                         ), | ||||
|                     ).to.be.rejected(); | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|         describe('#fillOrdersUpTo', () => { | ||||
|             let signedOrder: SignedOrder; | ||||
| @@ -536,7 +582,7 @@ describe('ExchangeWrapper', () => { | ||||
|                         ), | ||||
|                     ).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); | ||||
|                 }); | ||||
|                 it('should successfully fill up to specified amount', async () => { | ||||
|                 it('should successfully fill up to specified amount when all orders are fully funded', async () => { | ||||
|                     const txHash = await zeroEx.exchange.fillOrdersUpToAsync( | ||||
|                         signedOrders, | ||||
|                         fillUpToAmount, | ||||
| @@ -550,6 +596,37 @@ describe('ExchangeWrapper', () => { | ||||
|                     const remainingFillAmount = fillableAmount.minus(1); | ||||
|                     expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount); | ||||
|                 }); | ||||
|                 it('should successfully fill up to specified amount even if filling all orders would fail', async () => { | ||||
|                     const missingBalance = new BigNumber(1); // User will still have enough balance to fill up to 9, | ||||
|                     // but won't have 10 to fully fill all orders in a batch. | ||||
|                     await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, missingBalance); | ||||
|                     const txHash = await zeroEx.exchange.fillOrdersUpToAsync( | ||||
|                         signedOrders, | ||||
|                         fillUpToAmount, | ||||
|                         shouldThrowOnInsufficientBalanceOrAllowance, | ||||
|                         takerAddress, | ||||
|                     ); | ||||
|                     await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|                     const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex); | ||||
|                     const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex); | ||||
|                     expect(filledAmount).to.be.bignumber.equal(fillableAmount); | ||||
|                     const remainingFillAmount = fillableAmount.minus(1); | ||||
|                     expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount); | ||||
|                 }); | ||||
|             }); | ||||
|             describe('failed batch fills', () => { | ||||
|                 it("should fail validation if user doesn't have enough balance without fill up to", async () => { | ||||
|                     const missingBalance = new BigNumber(2); // User will only have enough balance to fill up to 8 | ||||
|                     await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, missingBalance); | ||||
|                     return expect( | ||||
|                         zeroEx.exchange.fillOrdersUpToAsync( | ||||
|                             signedOrders, | ||||
|                             fillUpToAmount, | ||||
|                             shouldThrowOnInsufficientBalanceOrAllowance, | ||||
|                             takerAddress, | ||||
|                         ), | ||||
|                     ).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance); | ||||
|                 }); | ||||
|             }); | ||||
|             describe('order transaction options', () => { | ||||
|                 const emptyFillUpToAmount = new BigNumber(0); | ||||
| @@ -844,7 +921,7 @@ describe('ExchangeWrapper', () => { | ||||
|             ); | ||||
|         }); | ||||
|         afterEach(async () => { | ||||
|             zeroEx.exchange.unsubscribeAll(); | ||||
|             zeroEx.exchange._unsubscribeAll(); | ||||
|         }); | ||||
|         // Hack: Mocha does not allow a test to be both async and have a `done` callback | ||||
|         // Since we need to await the receipt of the event in the `subscribe` callback, | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import * as _ from 'lodash'; | ||||
| @@ -13,15 +13,13 @@ import { constants } from '../src/utils/constants'; | ||||
| import { utils } from '../src/utils/utils'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants as testConstants } from './utils/constants'; | ||||
| import { FillScenarios } from './utils/fill_scenarios'; | ||||
| import { reportNoErrorCallbackErrors } from './utils/report_callback_errors'; | ||||
| import { TokenUtils } from './utils/token_utils'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(testConstants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| describe('ExpirationWatcher', () => { | ||||
|     let web3: Web3; | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import * as _ from 'lodash'; | ||||
| @@ -20,15 +20,14 @@ import { DoneCallback } from '../src/types'; | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { FillScenarios } from './utils/fill_scenarios'; | ||||
| import { reportNoErrorCallbackErrors } from './utils/report_callback_errors'; | ||||
| import { reportNodeCallbackErrors } from './utils/report_callback_errors'; | ||||
| import { TokenUtils } from './utils/token_utils'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| const TIMEOUT_MS = 150; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| describe('OrderStateWatcher', () => { | ||||
|     let web3: Web3; | ||||
| @@ -134,7 +133,7 @@ describe('OrderStateWatcher', () => { | ||||
|                 ); | ||||
|                 const orderHash = ZeroEx.getOrderHashHex(signedOrder); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|                 const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                 const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     expect(orderState.isValid).to.be.false(); | ||||
|                     const invalidOrderState = orderState as OrderStateInvalid; | ||||
|                     expect(invalidOrderState.orderHash).to.be.equal(orderHash); | ||||
| @@ -154,7 +153,7 @@ describe('OrderStateWatcher', () => { | ||||
|                     fillableAmount, | ||||
|                 ); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|                 const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                 const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     throw new Error('OrderState callback fired for irrelevant order'); | ||||
|                 }); | ||||
|                 zeroEx.orderStateWatcher.subscribe(callback); | ||||
| @@ -178,7 +177,7 @@ describe('OrderStateWatcher', () => { | ||||
|                 ); | ||||
|                 const orderHash = ZeroEx.getOrderHashHex(signedOrder); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|                 const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                 const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     expect(orderState.isValid).to.be.false(); | ||||
|                     const invalidOrderState = orderState as OrderStateInvalid; | ||||
|                     expect(invalidOrderState.orderHash).to.be.equal(orderHash); | ||||
| @@ -202,7 +201,7 @@ describe('OrderStateWatcher', () => { | ||||
|                 const orderHash = ZeroEx.getOrderHashHex(signedOrder); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                 const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                 const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     expect(orderState.isValid).to.be.false(); | ||||
|                     const invalidOrderState = orderState as OrderStateInvalid; | ||||
|                     expect(invalidOrderState.orderHash).to.be.equal(orderHash); | ||||
| @@ -234,7 +233,7 @@ describe('OrderStateWatcher', () => { | ||||
|                 const orderHash = ZeroEx.getOrderHashHex(signedOrder); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                 const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                 const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     expect(orderState.isValid).to.be.true(); | ||||
|                     const validOrderState = orderState as OrderStateValid; | ||||
|                     expect(validOrderState.orderHash).to.be.equal(orderHash); | ||||
| @@ -273,7 +272,7 @@ describe('OrderStateWatcher', () => { | ||||
|                     fillableAmount, | ||||
|                     taker, | ||||
|                 ); | ||||
|                 const callback = reportNoErrorCallbackErrors(done)(); | ||||
|                 const callback = reportNodeCallbackErrors(done)(); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|                 zeroEx.orderStateWatcher.subscribe(callback); | ||||
|                 await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0)); | ||||
| @@ -295,7 +294,7 @@ describe('OrderStateWatcher', () => { | ||||
|                     const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals); | ||||
|                     const orderHash = ZeroEx.getOrderHashHex(signedOrder); | ||||
|                     zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|                     const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                         expect(orderState.isValid).to.be.true(); | ||||
|                         const validOrderState = orderState as OrderStateValid; | ||||
|                         expect(validOrderState.orderHash).to.be.equal(orderHash); | ||||
| @@ -330,7 +329,7 @@ describe('OrderStateWatcher', () => { | ||||
|                     const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals); | ||||
|                     zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                     const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                         const validOrderState = orderState as OrderStateValid; | ||||
|                         const orderRelevantState = validOrderState.orderRelevantState; | ||||
|                         expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal( | ||||
| @@ -360,7 +359,7 @@ describe('OrderStateWatcher', () => { | ||||
|                     const transferAmount = makerBalance.sub(remainingAmount); | ||||
|                     zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                     const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                         expect(orderState.isValid).to.be.true(); | ||||
|                         const validOrderState = orderState as OrderStateValid; | ||||
|                         const orderRelevantState = validOrderState.orderRelevantState; | ||||
| @@ -395,7 +394,7 @@ describe('OrderStateWatcher', () => { | ||||
|                     const transferTokenAmount = makerFee.sub(remainingTokenAmount); | ||||
|                     zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                     const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                         expect(orderState.isValid).to.be.true(); | ||||
|                         const validOrderState = orderState as OrderStateValid; | ||||
|                         const orderRelevantState = validOrderState.orderRelevantState; | ||||
| @@ -429,7 +428,7 @@ describe('OrderStateWatcher', () => { | ||||
|                     const transferTokenAmount = makerFee.sub(remainingTokenAmount); | ||||
|                     zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                     const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                         const validOrderState = orderState as OrderStateValid; | ||||
|                         const orderRelevantState = validOrderState.orderRelevantState; | ||||
|                         expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal( | ||||
| @@ -464,7 +463,7 @@ describe('OrderStateWatcher', () => { | ||||
|  | ||||
|                     zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                     const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                         const validOrderState = orderState as OrderStateValid; | ||||
|                         const orderRelevantState = validOrderState.orderRelevantState; | ||||
|                         expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal( | ||||
| @@ -492,7 +491,7 @@ describe('OrderStateWatcher', () => { | ||||
|                 const orderHash = ZeroEx.getOrderHashHex(signedOrder); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                 const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                 const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     expect(orderState.isValid).to.be.false(); | ||||
|                     const invalidOrderState = orderState as OrderStateInvalid; | ||||
|                     expect(invalidOrderState.orderHash).to.be.equal(orderHash); | ||||
| @@ -516,7 +515,7 @@ describe('OrderStateWatcher', () => { | ||||
|                 const orderHash = ZeroEx.getOrderHashHex(signedOrder); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                 const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                 const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     expect(orderState.isValid).to.be.false(); | ||||
|                     const invalidOrderState = orderState as OrderStateInvalid; | ||||
|                     expect(invalidOrderState.orderHash).to.be.equal(orderHash); | ||||
| @@ -543,7 +542,7 @@ describe('OrderStateWatcher', () => { | ||||
|                 const orderHash = ZeroEx.getOrderHashHex(signedOrder); | ||||
|                 zeroEx.orderStateWatcher.addOrder(signedOrder); | ||||
|  | ||||
|                 const callback = reportNoErrorCallbackErrors(done)((orderState: OrderState) => { | ||||
|                 const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { | ||||
|                     expect(orderState.isValid).to.be.true(); | ||||
|                     const validOrderState = orderState as OrderStateValid; | ||||
|                     expect(validOrderState.orderHash).to.be.equal(orderHash); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import * as Sinon from 'sinon'; | ||||
| @@ -13,11 +13,10 @@ import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { FillScenarios } from './utils/fill_scenarios'; | ||||
| import { TokenUtils } from './utils/token_utils'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| describe('OrderValidation', () => { | ||||
|     let web3: Web3; | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import * as _ from 'lodash'; | ||||
| import 'mocha'; | ||||
| @@ -11,10 +11,9 @@ import { DoneCallback } from '../src/types'; | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { assertNodeCallbackError } from './utils/report_callback_errors'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| describe('SubscriptionTest', () => { | ||||
|     let web3: Web3; | ||||
| @@ -50,7 +49,7 @@ describe('SubscriptionTest', () => { | ||||
|             tokenAddress = token.address; | ||||
|         }); | ||||
|         afterEach(() => { | ||||
|             zeroEx.token.unsubscribeAll(); | ||||
|             zeroEx.token._unsubscribeAll(); | ||||
|             _.each(stubs, s => s.restore()); | ||||
|             stubs = []; | ||||
|         }); | ||||
| @@ -77,7 +76,7 @@ describe('SubscriptionTest', () => { | ||||
|                 const callback = (err: Error | null, logEvent?: DecodedLogEvent<ApprovalContractEventArgs>) => _.noop; | ||||
|                 zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); | ||||
|                 stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error('JSON RPC error'))]; | ||||
|                 zeroEx.token.unsubscribeAll(); | ||||
|                 zeroEx.token._unsubscribeAll(); | ||||
|                 done(); | ||||
|             })().catch(done); | ||||
|         }); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { schemas, SchemaValidator } from '@0xproject/json-schemas'; | ||||
| import * as chai from 'chai'; | ||||
| import * as _ from 'lodash'; | ||||
| @@ -8,11 +8,10 @@ import { Token, ZeroEx } from '../src'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7; | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import { web3Factory } from '@0xproject/dev-utils'; | ||||
| import * as chai from 'chai'; | ||||
|  | ||||
| import { ZeroEx } from '../src'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { BlockchainLifecycle } from '@0xproject/dev-utils'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| @@ -22,11 +22,10 @@ import { chaiSetup } from './utils/chai_setup'; | ||||
| import { constants } from './utils/constants'; | ||||
| import { reportNodeCallbackErrors } from './utils/report_callback_errors'; | ||||
| import { TokenUtils } from './utils/token_utils'; | ||||
| import { web3Factory } from './utils/web3_factory'; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(constants.RPC_URL); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
|  | ||||
| describe('TokenWrapper', () => { | ||||
|     let web3: Web3; | ||||
| @@ -378,7 +377,7 @@ describe('TokenWrapper', () => { | ||||
|             tokenAddress = token.address; | ||||
|         }); | ||||
|         afterEach(() => { | ||||
|             zeroEx.token.unsubscribeAll(); | ||||
|             zeroEx.token._unsubscribeAll(); | ||||
|         }); | ||||
|         // Hack: Mocha does not allow a test to be both async and have a `done` callback | ||||
|         // Since we need to await the receipt of the event in the `subscribe` callback, | ||||
|   | ||||
| @@ -1,11 +1,9 @@ | ||||
| export const constants = { | ||||
|     NULL_ADDRESS: '0x0000000000000000000000000000000000000000', | ||||
|     RPC_URL: 'http://localhost:8545/', | ||||
|     ROPSTEN_NETWORK_ID: 3, | ||||
|     KOVAN_NETWORK_ID: 42, | ||||
|     TESTRPC_NETWORK_ID: 50, | ||||
|     KOVAN_RPC_URL: 'https://kovan.infura.io/', | ||||
|     ROPSTEN_RPC_URL: 'https://ropsten.infura.io/', | ||||
|     ZRX_DECIMALS: 18, | ||||
|     GAS_ESTIMATE: 500000, | ||||
| }; | ||||
|   | ||||
| @@ -3,6 +3,8 @@ import * as _ from 'lodash'; | ||||
|  | ||||
| import { SignedOrder, ZeroEx } from '../../src'; | ||||
|  | ||||
| const SHOULD_ADD_PERSONAL_MESSAGE_PREFIX = false; | ||||
|  | ||||
| export const orderFactory = { | ||||
|     async createSignedOrderAsync( | ||||
|         zeroEx: ZeroEx, | ||||
| @@ -37,7 +39,7 @@ export const orderFactory = { | ||||
|             expirationUnixTimestampSec, | ||||
|         }; | ||||
|         const orderHash = ZeroEx.getOrderHashHex(order); | ||||
|         const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker); | ||||
|         const ecSignature = await zeroEx.signOrderHashAsync(orderHash, maker, SHOULD_ADD_PERSONAL_MESSAGE_PREFIX); | ||||
|         const signedOrder: SignedOrder = _.assign(order, { ecSignature }); | ||||
|         return signedOrder; | ||||
|     }, | ||||
|   | ||||
| @@ -25,7 +25,7 @@ export const reportNoErrorCallbackErrors = (done: DoneCallback, expectToBeCalled | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| export const reportNodeCallbackErrors = (done: DoneCallback) => { | ||||
| export const reportNodeCallbackErrors = (done: DoneCallback, expectToBeCalledOnce = true) => { | ||||
|     return <T>(f?: (value: T) => void) => { | ||||
|         const wrapped = (error: Error | null, value: T | undefined) => { | ||||
|             if (!_.isNull(error)) { | ||||
| @@ -37,7 +37,9 @@ export const reportNodeCallbackErrors = (done: DoneCallback) => { | ||||
|                 } | ||||
|                 try { | ||||
|                     f(value as T); | ||||
|                     done(); | ||||
|                     if (expectToBeCalledOnce) { | ||||
|                         done(); | ||||
|                     } | ||||
|                 } catch (err) { | ||||
|                     done(err); | ||||
|                 } | ||||
|   | ||||
| @@ -7,10 +7,10 @@ const path = require('path'); | ||||
| const production = process.env.NODE_ENV === 'production'; | ||||
|  | ||||
| let entry = { | ||||
|     'index': './src/index.ts', | ||||
|     index: './src/index.ts', | ||||
| }; | ||||
| if (production) { | ||||
|     entry = _.assign({}, entry, {'index.min': './src/index.ts'}); | ||||
|     entry = _.assign({}, entry, { 'index.min': './src/index.ts' }); | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|   | ||||
| @@ -1,5 +1,9 @@ | ||||
| # CHANGELOG | ||||
|  | ||||
| ## v0.2.0 - _???_ | ||||
|  | ||||
| * Added CLI options for explicit specifying location of partials and main template (#346) | ||||
|  | ||||
| ## v0.1.0 - _January 11, 2018_ | ||||
|  | ||||
| * Fixed array typings with union types (#295) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0xproject/abi-gen", | ||||
|     "version": "0.0.4", | ||||
|     "version": "0.1.6", | ||||
|     "description": "Generate contract wrappers from ABI and handlebars templates", | ||||
|     "main": "lib/index.js", | ||||
|     "types": "lib/index.d.ts", | ||||
| @@ -22,7 +22,7 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x.js/packages/abi-gen/README.md", | ||||
|     "dependencies": { | ||||
|         "@0xproject/utils": "^0.1.2", | ||||
|         "@0xproject/utils": "^0.2.4", | ||||
|         "chalk": "^2.3.0", | ||||
|         "glob": "^7.1.2", | ||||
|         "handlebars": "^4.0.11", | ||||
| @@ -33,7 +33,7 @@ | ||||
|         "yargs": "^10.0.3" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0xproject/tslint-config": "^0.4.0", | ||||
|         "@0xproject/tslint-config": "^0.4.6", | ||||
|         "@types/glob": "^5.0.33", | ||||
|         "@types/handlebars": "^4.0.36", | ||||
|         "@types/mkdirp": "^0.5.1", | ||||
| @@ -43,6 +43,6 @@ | ||||
|         "shx": "^0.2.2", | ||||
|         "tslint": "5.8.0", | ||||
|         "typescript": "~2.6.1", | ||||
|         "web3-typescript-typings": "^0.9.0" | ||||
|         "web3-typescript-typings": "^0.9.8" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,12 +3,13 @@ const packageJSON = require('../package.json'); | ||||
|  | ||||
| const subPackageName = packageJSON.name; | ||||
|  | ||||
| postpublish_utils.getLatestTagAndVersionAsync(subPackageName) | ||||
| postpublish_utils | ||||
|     .getLatestTagAndVersionAsync(subPackageName) | ||||
|     .then(function(result) { | ||||
|         const releaseName = postpublish_utils.getReleaseName(subPackageName, result.version); | ||||
|         const assets = []; | ||||
|         return postpublish_utils.publishReleaseNotes(result.tag, releaseName, assets); | ||||
|     }) | ||||
|     .catch (function(err) { | ||||
|     .catch(function(err) { | ||||
|         throw err; | ||||
|     }); | ||||
|   | ||||
| @@ -17,24 +17,45 @@ import { utils } from './utils'; | ||||
| const ABI_TYPE_CONSTRUCTOR = 'constructor'; | ||||
| const ABI_TYPE_METHOD = 'function'; | ||||
| const ABI_TYPE_EVENT = 'event'; | ||||
| const MAIN_TEMPLATE_NAME = 'contract.mustache'; | ||||
|  | ||||
| const args = yargs | ||||
|     .option('abiGlob', { | ||||
|     .option('abis', { | ||||
|         describe: 'Glob pattern to search for ABI JSON files', | ||||
|         type: 'string', | ||||
|         demand: true, | ||||
|     }) | ||||
|     .option('templates', { | ||||
|         describe: 'Folder where to search for templates', | ||||
|         type: 'string', | ||||
|         demand: true, | ||||
|         demandOption: true, | ||||
|     }) | ||||
|     .option('output', { | ||||
|         alias: ['o', 'out'], | ||||
|         describe: 'Folder where to put the output files', | ||||
|         type: 'string', | ||||
|         demand: true, | ||||
|     }).argv; | ||||
|         normalize: true, | ||||
|         demandOption: true, | ||||
|     }) | ||||
|     .option('partials', { | ||||
|         describe: 'Glob pattern for the partial template files', | ||||
|         type: 'string', | ||||
|         implies: 'template', | ||||
|     }) | ||||
|     .option('template', { | ||||
|         describe: 'Path for the main template file that will be used to generate each contract', | ||||
|         type: 'string', | ||||
|         demandOption: true, | ||||
|         normalize: true, | ||||
|     }) | ||||
|     .example( | ||||
|         "$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'", | ||||
|         'Full usage example', | ||||
|     ).argv; | ||||
|  | ||||
| function registerPartials(partialsGlob: string) { | ||||
|     const partialTemplateFileNames = globSync(partialsGlob); | ||||
|     utils.log(`Found ${chalk.green(`${partialTemplateFileNames.length}`)} ${chalk.bold('partial')} templates`); | ||||
|     for (const partialTemplateFileName of partialTemplateFileNames) { | ||||
|         const namedContent = utils.getNamedContent(partialTemplateFileName); | ||||
|         Handlebars.registerPartial(namedContent.name, namedContent.content); | ||||
|     } | ||||
|     return partialsGlob; | ||||
| } | ||||
|  | ||||
| function writeOutputFile(name: string, renderedTsCode: string): void { | ||||
|     const fileName = toSnakeCase(name); | ||||
| @@ -45,15 +66,14 @@ function writeOutputFile(name: string, renderedTsCode: string): void { | ||||
|  | ||||
| Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input)); | ||||
| Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output)); | ||||
| const partialTemplateFileNames = globSync(`${args.templates}/partials/**/*.mustache`); | ||||
| for (const partialTemplateFileName of partialTemplateFileNames) { | ||||
|     const namedContent = utils.getNamedContent(partialTemplateFileName); | ||||
|     Handlebars.registerPartial(namedContent.name, namedContent.content); | ||||
| } | ||||
|  | ||||
| const mainTemplate = utils.getNamedContent(`${args.templates}/${MAIN_TEMPLATE_NAME}`); | ||||
| if (args.partials) { | ||||
|     registerPartials(args.partials); | ||||
| } | ||||
| const mainTemplate = utils.getNamedContent(args.template); | ||||
| const template = Handlebars.compile<ContextData>(mainTemplate.content); | ||||
| const abiFileNames = globSync(args.abiGlob); | ||||
| const abiFileNames = globSync(args.abis); | ||||
|  | ||||
| if (_.isEmpty(abiFileNames)) { | ||||
|     utils.log(`${chalk.red(`No ABI files found.`)}`); | ||||
|     utils.log(`Please make sure you've passed the correct folder name and that the files have | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@0xproject/assert", | ||||
|     "version": "0.0.9", | ||||
|     "version": "0.0.15", | ||||
|     "description": "Provides a standard way of performing type and schema validation across 0x projects", | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
| @@ -23,12 +23,12 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x.js/packages/assert/README.md", | ||||
|     "devDependencies": { | ||||
|         "@0xproject/tslint-config": "^0.4.0", | ||||
|         "@0xproject/tslint-config": "^0.4.6", | ||||
|         "@types/lodash": "^4.14.86", | ||||
|         "@types/mocha": "^2.2.42", | ||||
|         "@types/valid-url": "^1.0.2", | ||||
|         "chai": "^4.0.1", | ||||
|         "chai-typescript-typings": "^0.0.1", | ||||
|         "chai-typescript-typings": "^0.0.2", | ||||
|         "dirty-chai": "^2.0.1", | ||||
|         "mocha": "^4.0.1", | ||||
|         "npm-run-all": "^4.1.2", | ||||
| @@ -37,8 +37,8 @@ | ||||
|         "typescript": "~2.6.1" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "@0xproject/json-schemas": "^0.7.1", | ||||
|         "@0xproject/utils": "^0.1.2", | ||||
|         "@0xproject/json-schemas": "^0.7.7", | ||||
|         "@0xproject/utils": "^0.2.4", | ||||
|         "lodash": "^4.17.4", | ||||
|         "valid-url": "^1.0.9" | ||||
|     } | ||||
|   | ||||
| @@ -3,12 +3,13 @@ const packageJSON = require('../package.json'); | ||||
|  | ||||
| const subPackageName = packageJSON.name; | ||||
|  | ||||
| postpublish_utils.getLatestTagAndVersionAsync(subPackageName) | ||||
| postpublish_utils | ||||
|     .getLatestTagAndVersionAsync(subPackageName) | ||||
|     .then(function(result) { | ||||
|         const releaseName = postpublish_utils.getReleaseName(subPackageName, result.version); | ||||
|         const assets = []; | ||||
|         return postpublish_utils.publishReleaseNotes(result.tag, releaseName, assets); | ||||
|     }) | ||||
|     .catch (function(err) { | ||||
|     .catch(function(err) { | ||||
|         throw err; | ||||
|     }); | ||||
|   | ||||
| @@ -12,6 +12,8 @@ export const assert = { | ||||
|     }, | ||||
|     isValidBaseUnitAmount(variableName: string, value: BigNumber) { | ||||
|         assert.isBigNumber(variableName, value); | ||||
|         const isNegative = value.lessThan(0); | ||||
|         this.assert(!isNegative, `${variableName} cannot be a negative number, found value: ${value.toNumber()}`); | ||||
|         const hasDecimals = value.decimalPlaces() !== 0; | ||||
|         this.assert( | ||||
|             !hasDecimals, | ||||
|   | ||||
| @@ -22,6 +22,20 @@ describe('Assertions', () => { | ||||
|             invalidInputs.forEach(input => expect(assert.isBigNumber.bind(assert, variableName, input)).to.throw()); | ||||
|         }); | ||||
|     }); | ||||
|     describe('#isValidBaseUnitAmount', () => { | ||||
|         it('should not throw for valid input', () => { | ||||
|             const validInputs = [new BigNumber(23), new BigNumber('45000000')]; | ||||
|             validInputs.forEach(input => | ||||
|                 expect(assert.isValidBaseUnitAmount.bind(assert, variableName, input)).to.not.throw(), | ||||
|             ); | ||||
|         }); | ||||
|         it('should throw for invalid input', () => { | ||||
|             const invalidInputs = [0, undefined, new BigNumber(3.145), 3.145, new BigNumber(-400)]; | ||||
|             invalidInputs.forEach(input => | ||||
|                 expect(assert.isValidBaseUnitAmount.bind(assert, variableName, input)).to.throw(), | ||||
|             ); | ||||
|         }); | ||||
|     }); | ||||
|     describe('#isString', () => { | ||||
|         it('should not throw for valid input', () => { | ||||
|             const validInputs = ['hello', 'goodbye']; | ||||
|   | ||||
| @@ -3,5 +3,10 @@ | ||||
|     "compilerOptions": { | ||||
|         "outDir": "lib" | ||||
|     }, | ||||
|     "include": ["./src/**/*", "./test/**/*", "../../node_modules/chai-typescript-typings/index.d.ts"] | ||||
|     "include": [ | ||||
|         "./src/**/*", | ||||
|         "./test/**/*", | ||||
|         "../../node_modules/web3-typescript-typings/index.d.ts", | ||||
|         "../../node_modules/chai-typescript-typings/index.d.ts" | ||||
|     ] | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,3 @@ | ||||
| # CHANGELOG | ||||
|  | ||||
| ## v0.x.x - _TBD, 2018_ | ||||
							
								
								
									
										43
									
								
								packages/chai-as-promised-typescript-typings/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								packages/chai-as-promised-typescript-typings/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| ## chai-as-promised-typescript-typings | ||||
|  | ||||
| Fork of type definitions for chai-as-promised that includes changes made by dirty-chai | ||||
|  | ||||
| ## Installation | ||||
|  | ||||
| ```bash | ||||
| yarn add -D chai-as-promised-typescript-typings | ||||
| ``` | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| Add the following line within an `include` section of your `tsconfig.json` | ||||
|  | ||||
| ```json | ||||
| "./node_modules/chai-as-promised-typescript-typings/index.d.ts" | ||||
| ``` | ||||
|  | ||||
| ## Contributing | ||||
|  | ||||
| We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. | ||||
|  | ||||
| Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. | ||||
|  | ||||
| ### Install Dependencies | ||||
|  | ||||
| If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: | ||||
|  | ||||
| ```bash | ||||
| yarn config set workspaces-experimental true | ||||
| ``` | ||||
|  | ||||
| Then install dependencies | ||||
|  | ||||
| ```bash | ||||
| yarn install | ||||
| ``` | ||||
|  | ||||
| ### Lint | ||||
|  | ||||
| ```bash | ||||
| yarn lint | ||||
| ``` | ||||
							
								
								
									
										268
									
								
								packages/chai-as-promised-typescript-typings/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								packages/chai-as-promised-typescript-typings/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,268 @@ | ||||
| // Type definitions for chai-as-promised | ||||
| // Project: https://github.com/domenic/chai-as-promised/ | ||||
| // Definitions by: jt000 <https://github.com/jt000>, Yuki Kokubun <https://github.com/Kuniwak> | ||||
| // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped | ||||
|  | ||||
| declare module 'chai-as-promised' { | ||||
|     function chaiAsPromised(chai: any, utils: any): void; | ||||
|     namespace chaiAsPromised { | ||||
|  | ||||
|     } | ||||
|     export = chaiAsPromised; | ||||
| } | ||||
|  | ||||
| // tslint:disable:no-namespace ban-types member-ordering | ||||
| declare namespace Chai { | ||||
|     // For BDD API | ||||
|     interface Assertion extends LanguageChains, NumericComparison, TypeComparison { | ||||
|         eventually: PromisedAssertion; | ||||
|         fulfilled: PromisedAssertion; | ||||
|         become(expected: any): PromisedAssertion; | ||||
|         rejected(): PromisedAssertion; | ||||
|         rejectedWith(expected: any, message?: string | RegExp): PromisedAssertion; | ||||
|         notify(fn: Function): PromisedAssertion; | ||||
|     } | ||||
|  | ||||
|     // Eventually does not have .then(), but PromisedAssertion have. | ||||
|     interface Eventually extends PromisedLanguageChains, PromisedNumericComparison, PromisedTypeComparison { | ||||
|         // From chai-as-promised | ||||
|         become(expected: PromiseLike<any>): PromisedAssertion; | ||||
|         fulfilled: PromisedAssertion; | ||||
|         rejected: () => PromisedAssertion; | ||||
|         rejectedWith(expected: any, message?: string | RegExp): PromisedAssertion; | ||||
|         notify(fn: Function): PromisedAssertion; | ||||
|  | ||||
|         // From chai | ||||
|         not: PromisedAssertion; | ||||
|         deep: PromisedDeep; | ||||
|         all: PromisedKeyFilter; | ||||
|         a: PromisedTypeComparison; | ||||
|         an: PromisedTypeComparison; | ||||
|         include: PromisedInclude; | ||||
|         contain: PromisedInclude; | ||||
|         ok: PromisedAssertion; | ||||
|         true: () => PromisedAssertion; | ||||
|         false: () => PromisedAssertion; | ||||
|         null: PromisedAssertion; | ||||
|         undefined: PromisedAssertion; | ||||
|         exist: PromisedAssertion; | ||||
|         empty: PromisedAssertion; | ||||
|         arguments: PromisedAssertion; | ||||
|         Arguments: PromisedAssertion; | ||||
|         equal: PromisedEqual; | ||||
|         equals: PromisedEqual; | ||||
|         eq: PromisedEqual; | ||||
|         eql: PromisedEqual; | ||||
|         eqls: PromisedEqual; | ||||
|         property: PromisedProperty; | ||||
|         ownProperty: PromisedOwnProperty; | ||||
|         haveOwnProperty: PromisedOwnProperty; | ||||
|         length: PromisedLength; | ||||
|         lengthOf: PromisedLength; | ||||
|         match(regexp: RegExp | string, message?: string): PromisedAssertion; | ||||
|         string(string: string, message?: string): PromisedAssertion; | ||||
|         keys: PromisedKeys; | ||||
|         key(string: string): PromisedAssertion; | ||||
|         throw: PromisedThrow; | ||||
|         throws: PromisedThrow; | ||||
|         Throw: PromisedThrow; | ||||
|         respondTo(method: string, message?: string): PromisedAssertion; | ||||
|         itself: PromisedAssertion; | ||||
|         satisfy(matcher: Function, message?: string): PromisedAssertion; | ||||
|         closeTo(expected: number, delta: number, message?: string): PromisedAssertion; | ||||
|         members: PromisedMembers; | ||||
|     } | ||||
|  | ||||
|     interface PromisedAssertion extends Eventually, PromiseLike<any> {} | ||||
|  | ||||
|     interface PromisedLanguageChains { | ||||
|         eventually: Eventually; | ||||
|  | ||||
|         // From chai | ||||
|         to: PromisedAssertion; | ||||
|         be: PromisedAssertion; | ||||
|         been: PromisedAssertion; | ||||
|         is: PromisedAssertion; | ||||
|         that: PromisedAssertion; | ||||
|         which: PromisedAssertion; | ||||
|         and: PromisedAssertion; | ||||
|         has: PromisedAssertion; | ||||
|         have: PromisedAssertion; | ||||
|         with: PromisedAssertion; | ||||
|         at: PromisedAssertion; | ||||
|         of: PromisedAssertion; | ||||
|         same: PromisedAssertion; | ||||
|     } | ||||
|  | ||||
|     interface PromisedNumericComparison { | ||||
|         above: PromisedNumberComparer; | ||||
|         gt: PromisedNumberComparer; | ||||
|         greaterThan: PromisedNumberComparer; | ||||
|         least: PromisedNumberComparer; | ||||
|         gte: PromisedNumberComparer; | ||||
|         below: PromisedNumberComparer; | ||||
|         lt: PromisedNumberComparer; | ||||
|         lessThan: PromisedNumberComparer; | ||||
|         most: PromisedNumberComparer; | ||||
|         lte: PromisedNumberComparer; | ||||
|         within(start: number, finish: number, message?: string): PromisedAssertion; | ||||
|     } | ||||
|  | ||||
|     type PromisedNumberComparer = (value: number, message?: string) => PromisedAssertion; | ||||
|  | ||||
|     interface PromisedTypeComparison { | ||||
|         (type: string, message?: string): PromisedAssertion; | ||||
|         instanceof: PromisedInstanceOf; | ||||
|         instanceOf: PromisedInstanceOf; | ||||
|     } | ||||
|  | ||||
|     type PromisedInstanceOf = (constructor: Object, message?: string) => PromisedAssertion; | ||||
|  | ||||
|     interface PromisedDeep { | ||||
|         equal: PromisedEqual; | ||||
|         include: PromisedInclude; | ||||
|         property: PromisedProperty; | ||||
|     } | ||||
|  | ||||
|     interface PromisedKeyFilter { | ||||
|         keys: PromisedKeys; | ||||
|     } | ||||
|  | ||||
|     type PromisedEqual = (value: any, message?: string) => PromisedAssertion; | ||||
|  | ||||
|     type PromisedProperty = (name: string, value?: any, message?: string) => PromisedAssertion; | ||||
|  | ||||
|     type PromisedOwnProperty = (name: string, message?: string) => PromisedAssertion; | ||||
|  | ||||
|     interface PromisedLength extends PromisedLanguageChains, PromisedNumericComparison { | ||||
|         (length: number, message?: string): PromisedAssertion; | ||||
|     } | ||||
|  | ||||
|     interface PromisedInclude { | ||||
|         (value: Object | string | number, message?: string): PromisedAssertion; | ||||
|         keys: PromisedKeys; | ||||
|         members: PromisedMembers; | ||||
|         all: PromisedKeyFilter; | ||||
|     } | ||||
|  | ||||
|     interface PromisedKeys { | ||||
|         (...keys: string[]): PromisedAssertion; | ||||
|         (keys: any[]): PromisedAssertion; | ||||
|     } | ||||
|  | ||||
|     interface PromisedThrow { | ||||
|         (): PromisedAssertion; | ||||
|         (expected: string | RegExp, message?: string): PromisedAssertion; | ||||
|         (constructor: Error | Function, expected?: string | RegExp, message?: string): PromisedAssertion; | ||||
|     } | ||||
|  | ||||
|     type PromisedMembers = (set: any[], message?: string) => PromisedAssertion; | ||||
|  | ||||
|     // For Assert API | ||||
|     interface Assert { | ||||
|         eventually: PromisedAssert; | ||||
|         isFulfilled(promise: PromiseLike<any>, message?: string): PromiseLike<void>; | ||||
|         becomes(promise: PromiseLike<any>, expected: any, message?: string): PromiseLike<void>; | ||||
|         doesNotBecome(promise: PromiseLike<any>, expected: any, message?: string): PromiseLike<void>; | ||||
|         isRejected(promise: PromiseLike<any>, message?: string): PromiseLike<void>; | ||||
|         isRejected(promise: PromiseLike<any>, expected: any | RegExp, message?: string): PromiseLike<void>; | ||||
|         notify(fn: Function): PromiseLike<void>; | ||||
|     } | ||||
|  | ||||
|     export interface PromisedAssert { | ||||
|         fail(actual?: any, expected?: any, msg?: string, operator?: string): PromiseLike<void>; | ||||
|  | ||||
|         ok(val: any, msg?: string): PromiseLike<void>; | ||||
|         notOk(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         equal(act: any, exp: any, msg?: string): PromiseLike<void>; | ||||
|         notEqual(act: any, exp: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         strictEqual(act: any, exp: any, msg?: string): PromiseLike<void>; | ||||
|         notStrictEqual(act: any, exp: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         deepEqual(act: any, exp: any, msg?: string): PromiseLike<void>; | ||||
|         notDeepEqual(act: any, exp: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isTrue(val: any, msg?: string): PromiseLike<void>; | ||||
|         isFalse(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isNull(val: any, msg?: string): PromiseLike<void>; | ||||
|         isNotNull(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isUndefined(val: any, msg?: string): PromiseLike<void>; | ||||
|         isDefined(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isFunction(val: any, msg?: string): PromiseLike<void>; | ||||
|         isNotFunction(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isObject(val: any, msg?: string): PromiseLike<void>; | ||||
|         isNotObject(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isArray(val: any, msg?: string): PromiseLike<void>; | ||||
|         isNotArray(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isString(val: any, msg?: string): PromiseLike<void>; | ||||
|         isNotString(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isNumber(val: any, msg?: string): PromiseLike<void>; | ||||
|         isNotNumber(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         isBoolean(val: any, msg?: string): PromiseLike<void>; | ||||
|         isNotBoolean(val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         typeOf(val: any, type: string, msg?: string): PromiseLike<void>; | ||||
|         notTypeOf(val: any, type: string, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         instanceOf(val: any, type: Function, msg?: string): PromiseLike<void>; | ||||
|         notInstanceOf(val: any, type: Function, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         include(exp: string | any[], inc: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         notInclude(exp: string | any[], inc: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         match(exp: any, re: RegExp, msg?: string): PromiseLike<void>; | ||||
|         notMatch(exp: any, re: RegExp, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         property(obj: Object, prop: string, msg?: string): PromiseLike<void>; | ||||
|         notProperty(obj: Object, prop: string, msg?: string): PromiseLike<void>; | ||||
|         deepProperty(obj: Object, prop: string, msg?: string): PromiseLike<void>; | ||||
|         notDeepProperty(obj: Object, prop: string, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         propertyVal(obj: Object, prop: string, val: any, msg?: string): PromiseLike<void>; | ||||
|         propertyNotVal(obj: Object, prop: string, val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         deepPropertyVal(obj: Object, prop: string, val: any, msg?: string): PromiseLike<void>; | ||||
|         deepPropertyNotVal(obj: Object, prop: string, val: any, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         lengthOf(exp: any, len: number, msg?: string): PromiseLike<void>; | ||||
|         // alias frenzy | ||||
|         throw(fn: Function, msg?: string): PromiseLike<void>; | ||||
|         throw(fn: Function, regExp: RegExp): PromiseLike<void>; | ||||
|         throw(fn: Function, errType: Function, msg?: string): PromiseLike<void>; | ||||
|         throw(fn: Function, errType: Function, regExp: RegExp): PromiseLike<void>; | ||||
|  | ||||
|         throws(fn: Function, msg?: string): PromiseLike<void>; | ||||
|         throws(fn: Function, regExp: RegExp): PromiseLike<void>; | ||||
|         throws(fn: Function, errType: Function, msg?: string): PromiseLike<void>; | ||||
|         throws(fn: Function, errType: Function, regExp: RegExp): PromiseLike<void>; | ||||
|  | ||||
|         Throw(fn: Function, msg?: string): PromiseLike<void>; | ||||
|         Throw(fn: Function, regExp: RegExp): PromiseLike<void>; | ||||
|         Throw(fn: Function, errType: Function, msg?: string): PromiseLike<void>; | ||||
|         Throw(fn: Function, errType: Function, regExp: RegExp): PromiseLike<void>; | ||||
|  | ||||
|         doesNotThrow(fn: Function, msg?: string): PromiseLike<void>; | ||||
|         doesNotThrow(fn: Function, regExp: RegExp): PromiseLike<void>; | ||||
|         doesNotThrow(fn: Function, errType: Function, msg?: string): PromiseLike<void>; | ||||
|         doesNotThrow(fn: Function, errType: Function, regExp: RegExp): PromiseLike<void>; | ||||
|  | ||||
|         operator(val: any, operator: string, val2: any, msg?: string): PromiseLike<void>; | ||||
|         closeTo(act: number, exp: number, delta: number, msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         sameMembers(set1: any[], set2: any[], msg?: string): PromiseLike<void>; | ||||
|         includeMembers(set1: any[], set2: any[], msg?: string): PromiseLike<void>; | ||||
|  | ||||
|         ifError(val: any, msg?: string): PromiseLike<void>; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								packages/chai-as-promised-typescript-typings/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								packages/chai-as-promised-typescript-typings/package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| { | ||||
|     "name": "chai-as-promised-typescript-typings", | ||||
|     "version": "0.0.8", | ||||
|     "description": "Typescript type definitions for chai-as-promised", | ||||
|     "main": "index.d.ts", | ||||
|     "types": "index.d.ts", | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
|         "url": "git+https://github.com/0xProject/0x.js.git" | ||||
|     }, | ||||
|     "author": "Fabio Berger", | ||||
|     "contributors": [ | ||||
|         "Leonid Logvinov <logvinov.leon@gmail.com>" | ||||
|     ], | ||||
|     "license": "Apache-2.0", | ||||
|     "bugs": { | ||||
|         "url": "https://github.com/0xProject/0x.js/issues" | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x.js/packages/chai-as-promised-typescript-typings#readme", | ||||
|     "dependencies": { | ||||
|         "chai-typescript-typings": "^0.0.2" | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| const postpublish_utils = require('../../../scripts/postpublish_utils'); | ||||
| const packageJSON = require('../package.json'); | ||||
|  | ||||
| const subPackageName = packageJSON.name; | ||||
|  | ||||
| postpublish_utils | ||||
|     .getLatestTagAndVersionAsync(subPackageName) | ||||
|     .then(function(result) { | ||||
|         const releaseName = postpublish_utils.getReleaseName(subPackageName, result.version); | ||||
|         const assets = []; | ||||
|         return postpublish_utils.publishReleaseNotes(result.tag, releaseName, assets); | ||||
|     }) | ||||
|     .catch(function(err) { | ||||
|         throw err; | ||||
|     }); | ||||
							
								
								
									
										3
									
								
								packages/chai-as-promised-typescript-typings/tslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/chai-as-promised-typescript-typings/tslint.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| { | ||||
|     "extends": ["tslint-config-0xproject"] | ||||
| } | ||||
							
								
								
									
										3
									
								
								packages/chai-typescript-typings/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/chai-typescript-typings/CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # CHANGELOG | ||||
|  | ||||
| ## v0.x.x - _TBD, 2018_ | ||||
							
								
								
									
										43
									
								
								packages/chai-typescript-typings/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								packages/chai-typescript-typings/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| ## chai-typescript-typings | ||||
|  | ||||
| Fork of type definitions for chai that includes changes made by dirty-chai | ||||
|  | ||||
| ## Installation | ||||
|  | ||||
| ```bash | ||||
| yarn add -D chai-typescript-typings | ||||
| ``` | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| Add the following line within an `include` section of your `tsconfig.json` | ||||
|  | ||||
| ```json | ||||
| "./node_modules/chai-typescript-typings/index.d.ts" | ||||
| ``` | ||||
|  | ||||
| ## Contributing | ||||
|  | ||||
| We strongly encourage that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. | ||||
|  | ||||
| Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. | ||||
|  | ||||
| ### Install Dependencies | ||||
|  | ||||
| If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: | ||||
|  | ||||
| ```bash | ||||
| yarn config set workspaces-experimental true | ||||
| ``` | ||||
|  | ||||
| Then install dependencies | ||||
|  | ||||
| ```bash | ||||
| yarn install | ||||
| ``` | ||||
|  | ||||
| ### Lint | ||||
|  | ||||
| ```bash | ||||
| yarn lint | ||||
| ``` | ||||
							
								
								
									
										1254
									
								
								packages/chai-typescript-typings/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1254
									
								
								packages/chai-typescript-typings/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										16
									
								
								packages/chai-typescript-typings/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								packages/chai-typescript-typings/package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| { | ||||
|     "name": "chai-typescript-typings", | ||||
|     "version": "0.0.2", | ||||
|     "description": "Typescript type definitions for chai", | ||||
|     "main": "index.d.ts", | ||||
|     "types": "index.d.ts", | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
|         "url": "git+https://github.com/0xProject/0x.js.git" | ||||
|     }, | ||||
|     "license": "Apache-2.0", | ||||
|     "bugs": { | ||||
|         "url": "https://github.com/0xProject/0x.js/issues" | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x.js/packages/chai-typescript-typings#readme" | ||||
| } | ||||
							
								
								
									
										15
									
								
								packages/chai-typescript-typings/scripts/postpublish.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								packages/chai-typescript-typings/scripts/postpublish.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| const postpublish_utils = require('../../../scripts/postpublish_utils'); | ||||
| const packageJSON = require('../package.json'); | ||||
|  | ||||
| const subPackageName = packageJSON.name; | ||||
|  | ||||
| postpublish_utils | ||||
|     .getLatestTagAndVersionAsync(subPackageName) | ||||
|     .then(function(result) { | ||||
|         const releaseName = postpublish_utils.getReleaseName(subPackageName, result.version); | ||||
|         const assets = []; | ||||
|         return postpublish_utils.publishReleaseNotes(result.tag, releaseName, assets); | ||||
|     }) | ||||
|     .catch(function(err) { | ||||
|         throw err; | ||||
|     }); | ||||
							
								
								
									
										3
									
								
								packages/chai-typescript-typings/tslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								packages/chai-typescript-typings/tslint.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| { | ||||
|     "extends": ["tslint-config-0xproject"] | ||||
| } | ||||
| @@ -1,6 +1,12 @@ | ||||
| # CHANGELOG | ||||
|  | ||||
| ## vx.x.x | ||||
| ## v0.5.0 - _January 17, 2018_ | ||||
|  | ||||
|     * Sanitize api endpoint url and remove trailing slashes (#318) | ||||
|     * Improve error message text in HttpClient (#318) | ||||
|     * Stop appending '/v0' to api endpoint url in HttpClient (#318) | ||||
|  | ||||
| ## v0.4.0 - _January 11, 2018_ | ||||
|  | ||||
|     * Prevent getFeesAsync method on HttpClient from mutating input (#296) | ||||
|  | ||||
|   | ||||
| @@ -1,16 +1,21 @@ | ||||
| { | ||||
|     "name": "@0xproject/connect", | ||||
|     "version": "0.3.2", | ||||
|     "version": "0.5.4", | ||||
|     "description": "A javascript library for interacting with the standard relayer api", | ||||
|     "keywords": ["connect", "0xproject", "ethereum", "tokens", "exchange"], | ||||
|     "keywords": [ | ||||
|         "connect", | ||||
|         "0xproject", | ||||
|         "ethereum", | ||||
|         "tokens", | ||||
|         "exchange" | ||||
|     ], | ||||
|     "main": "lib/src/index.js", | ||||
|     "types": "lib/src/index.d.ts", | ||||
|     "scripts": { | ||||
|         "build": "tsc", | ||||
|         "clean": "shx rm -rf _bundles lib test_temp", | ||||
|         "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_DIR", | ||||
|         "upload_docs_json": | ||||
|             "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json", | ||||
|         "upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json", | ||||
|         "copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures", | ||||
|         "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", | ||||
|         "run_mocha": "mocha lib/test/**/*_test.js", | ||||
| @@ -31,16 +36,16 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x.js/packages/connect/README.md", | ||||
|     "dependencies": { | ||||
|         "@0xproject/assert": "^0.0.9", | ||||
|         "@0xproject/json-schemas": "^0.7.1", | ||||
|         "@0xproject/utils": "^0.1.2", | ||||
|         "@0xproject/assert": "^0.0.15", | ||||
|         "@0xproject/json-schemas": "^0.7.7", | ||||
|         "@0xproject/utils": "^0.2.4", | ||||
|         "isomorphic-fetch": "^2.2.1", | ||||
|         "lodash": "^4.17.4", | ||||
|         "query-string": "^5.0.1", | ||||
|         "websocket": "^1.0.25" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "@0xproject/tslint-config": "^0.4.0", | ||||
|         "@0xproject/tslint-config": "^0.4.6", | ||||
|         "@types/fetch-mock": "^5.12.1", | ||||
|         "@types/lodash": "^4.14.86", | ||||
|         "@types/mocha": "^2.2.42", | ||||
| @@ -48,8 +53,8 @@ | ||||
|         "@types/websocket": "^0.0.34", | ||||
|         "chai": "^4.0.1", | ||||
|         "chai-as-promised": "^7.1.0", | ||||
|         "chai-as-promised-typescript-typings": "^0.0.3", | ||||
|         "chai-typescript-typings": "^0.0.1", | ||||
|         "chai-as-promised-typescript-typings": "^0.0.8", | ||||
|         "chai-typescript-typings": "^0.0.2", | ||||
|         "copyfiles": "^1.2.0", | ||||
|         "dirty-chai": "^2.0.1", | ||||
|         "fetch-mock": "^5.13.1", | ||||
| @@ -59,6 +64,6 @@ | ||||
|         "tslint": "5.8.0", | ||||
|         "typedoc": "~0.8.0", | ||||
|         "typescript": "~2.6.1", | ||||
|         "web3-typescript-typings": "^0.9.0" | ||||
|         "web3-typescript-typings": "^0.9.8" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,22 +8,20 @@ const S3BucketPath = 's3://connect-docs-jsons/'; | ||||
|  | ||||
| let tag; | ||||
| let version; | ||||
| postpublish_utils.getLatestTagAndVersionAsync(subPackageName) | ||||
| postpublish_utils | ||||
|     .getLatestTagAndVersionAsync(subPackageName) | ||||
|     .then(function(result) { | ||||
|         tag = result.tag; | ||||
|         version = result.version; | ||||
|          const releaseName = postpublish_utils.getReleaseName(subPackageName, version); | ||||
|          return postpublish_utils.publishReleaseNotes(tag, releaseName); | ||||
|         const releaseName = postpublish_utils.getReleaseName(subPackageName, version); | ||||
|         return postpublish_utils.publishReleaseNotes(tag, releaseName); | ||||
|     }) | ||||
|     .then(function(release) { | ||||
|         console.log('POSTPUBLISH: Release successful, generating docs...'); | ||||
|         const jsonFilePath = __dirname + '/../' + postpublish_utils.generatedDocsDirectoryName + '/index.json'; | ||||
|         return execAsync( | ||||
|             'JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_DIR=' + __dirname + '/.. yarn docs:json', | ||||
|             { | ||||
|                 cwd, | ||||
|             } | ||||
|         ); | ||||
|         return execAsync('JSON_FILE_PATH=' + jsonFilePath + ' PROJECT_DIR=' + __dirname + '/.. yarn docs:json', { | ||||
|             cwd, | ||||
|         }); | ||||
|     }) | ||||
|     .then(function(result) { | ||||
|         if (result.stderr !== '') { | ||||
| @@ -35,6 +33,7 @@ postpublish_utils.getLatestTagAndVersionAsync(subPackageName) | ||||
|         return execAsync('S3_URL=' + s3Url + ' yarn upload_docs_json', { | ||||
|             cwd, | ||||
|         }); | ||||
|     }).catch (function(err) { | ||||
|     }) | ||||
|     .catch(function(err) { | ||||
|         throw err; | ||||
|     }); | ||||
|   | ||||
| @@ -20,6 +20,7 @@ import { | ||||
| } from './types'; | ||||
| import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers'; | ||||
|  | ||||
| const TRAILING_SLASHES_REGEX = /\/+$/; | ||||
| /** | ||||
|  * This class includes all the functionality related to interacting with a set of HTTP endpoints | ||||
|  * that implement the standard relayer API v0 | ||||
| @@ -33,7 +34,7 @@ export class HttpClient implements Client { | ||||
|      */ | ||||
|     constructor(url: string) { | ||||
|         assert.isHttpUrl('url', url); | ||||
|         this._apiEndpointUrl = url; | ||||
|         this._apiEndpointUrl = url.replace(TRAILING_SLASHES_REGEX, ''); // remove trailing slashes | ||||
|     } | ||||
|     /** | ||||
|      * Retrieve token pair info from the API | ||||
| @@ -130,20 +131,22 @@ export class HttpClient implements Client { | ||||
|             const stringifiedParams = queryString.stringify(params); | ||||
|             query = `?${stringifiedParams}`; | ||||
|         } | ||||
|         const url = `${this._apiEndpointUrl}/v0${path}${query}`; | ||||
|         const url = `${this._apiEndpointUrl}${path}${query}`; | ||||
|         const headers = new Headers({ | ||||
|             'content-type': 'application/json', | ||||
|         }); | ||||
|  | ||||
|         const response = await fetch(url, { | ||||
|             method: requestType, | ||||
|             body: JSON.stringify(payload), | ||||
|             headers, | ||||
|         }); | ||||
|         if (!response.ok) { | ||||
|             throw Error(response.statusText); | ||||
|         } | ||||
|         const json = await response.json(); | ||||
|         if (!response.ok) { | ||||
|             const errorString = `${response.status} - ${response.statusText}\n${requestType} ${url}\n${JSON.stringify( | ||||
|                 json, | ||||
|             )}`; | ||||
|             throw Error(errorString); | ||||
|         } | ||||
|         return json; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -29,14 +29,23 @@ describe('HttpClient', () => { | ||||
|     afterEach(() => { | ||||
|         fetchMock.restore(); | ||||
|     }); | ||||
|     describe('#constructor', () => { | ||||
|         it('should remove trailing slashes from api url', async () => { | ||||
|             const urlWithTrailingSlash = 'https://slash.com/'; | ||||
|             const urlWithoutTrailingSlash = 'https://slash.com'; | ||||
|             const client = new HttpClient(urlWithTrailingSlash); | ||||
|             const sanitizedUrl = (client as any)._apiEndpointUrl; | ||||
|             expect(sanitizedUrl).to.be.deep.equal(urlWithoutTrailingSlash); | ||||
|         }); | ||||
|     }); | ||||
|     describe('#getTokenPairsAsync', () => { | ||||
|         const url = `${relayUrl}/v0/token_pairs`; | ||||
|         const url = `${relayUrl}/token_pairs`; | ||||
|         it('gets token pairs', async () => { | ||||
|             fetchMock.get(url, tokenPairsResponseJSON); | ||||
|             const tokenPairs = await relayerClient.getTokenPairsAsync(); | ||||
|             expect(tokenPairs).to.be.deep.equal(tokenPairsResponse); | ||||
|         }); | ||||
|         it('gets specfic token pairs for request', async () => { | ||||
|         it('gets specific token pairs for request', async () => { | ||||
|             const tokenAddress = '0x323b5d4c32345ced77393b3530b1eed0f346429d'; | ||||
|             const tokenPairsRequest = { | ||||
|                 tokenA: tokenAddress, | ||||
| @@ -52,7 +61,7 @@ describe('HttpClient', () => { | ||||
|         }); | ||||
|     }); | ||||
|     describe('#getOrdersAsync', () => { | ||||
|         const url = `${relayUrl}/v0/orders`; | ||||
|         const url = `${relayUrl}/orders`; | ||||
|         it('gets orders', async () => { | ||||
|             fetchMock.get(url, ordersResponseJSON); | ||||
|             const orders = await relayerClient.getOrdersAsync(); | ||||
| @@ -75,7 +84,7 @@ describe('HttpClient', () => { | ||||
|     }); | ||||
|     describe('#getOrderAsync', () => { | ||||
|         const orderHash = '0xabc67323774bdbd24d94f977fa9ac94a50f016026fd13f42990861238897721f'; | ||||
|         const url = `${relayUrl}/v0/order/${orderHash}`; | ||||
|         const url = `${relayUrl}/order/${orderHash}`; | ||||
|         it('gets order', async () => { | ||||
|             fetchMock.get(url, orderResponseJSON); | ||||
|             const order = await relayerClient.getOrderAsync(orderHash); | ||||
| @@ -91,7 +100,7 @@ describe('HttpClient', () => { | ||||
|             baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d', | ||||
|             quoteTokenAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32', | ||||
|         }; | ||||
|         const url = `${relayUrl}/v0/orderbook?baseTokenAddress=${request.baseTokenAddress}"eTokenAddress=${ | ||||
|         const url = `${relayUrl}/orderbook?baseTokenAddress=${request.baseTokenAddress}"eTokenAddress=${ | ||||
|             request.quoteTokenAddress | ||||
|         }`; | ||||
|         it('gets order book', async () => { | ||||
| @@ -116,7 +125,7 @@ describe('HttpClient', () => { | ||||
|             salt: new BigNumber('256'), | ||||
|             expirationUnixTimestampSec: new BigNumber('42'), | ||||
|         }; | ||||
|         const url = `${relayUrl}/v0/fees`; | ||||
|         const url = `${relayUrl}/fees`; | ||||
|         it('gets fees', async () => { | ||||
|             fetchMock.post(url, feesResponseJSON); | ||||
|             const fees = await relayerClient.getFeesAsync(request); | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
|     "include": [ | ||||
|         "./src/**/*", | ||||
|         "./test/**/*", | ||||
|         "../../node_modules/web3-typescript-typings/index.d.ts", | ||||
|         "../../node_modules/chai-as-promised-typescript-typings/index.d.ts", | ||||
|         "../../node_modules/chai-typescript-typings/index.d.ts" | ||||
|     ] | ||||
|   | ||||
| @@ -600,4 +600,3 @@ contract Exchange is SafeMath { | ||||
|         return Token(token).allowance.gas(EXTERNAL_QUERY_GAS_LIMIT)(owner, TOKEN_TRANSFER_PROXY_CONTRACT); // Limit gas to prevent reentrancy | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										4
									
								
								packages/contracts/globals.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								packages/contracts/globals.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -32,7 +32,3 @@ declare module 'ethereumjs-abi' { | ||||
|     const soliditySHA3: (argTypes: string[], args: any[]) => Buffer; | ||||
|     const methodID: (name: string, types: string[]) => Buffer; | ||||
| } | ||||
|  | ||||
| // Truffle injects the following into the global scope | ||||
| declare var artifacts: any; | ||||
| declare var contract: any; | ||||
|   | ||||
| @@ -1,6 +0,0 @@ | ||||
| import { Artifacts } from '../util/artifacts'; | ||||
| const { Migrations } = new Artifacts(artifacts); | ||||
|  | ||||
| module.exports = (deployer: any) => { | ||||
|     deployer.deploy(Migrations); | ||||
| }; | ||||
| @@ -1,41 +0,0 @@ | ||||
| import { Artifacts } from '../util/artifacts'; | ||||
| import { MultiSigConfigByNetwork } from '../util/types'; | ||||
| const { MultiSigWalletWithTimeLock, TokenTransferProxy, EtherToken, TokenRegistry } = new Artifacts(artifacts); | ||||
|  | ||||
| let multiSigConfigByNetwork: MultiSigConfigByNetwork; | ||||
| try { | ||||
|     /* tslint:disable */ | ||||
|     const multiSigConfig = require('./config/multisig'); | ||||
|     multiSigConfigByNetwork = multiSigConfig.multiSig; | ||||
|     /* tslint:enable */ | ||||
| } catch (e) { | ||||
|     multiSigConfigByNetwork = {}; | ||||
| } | ||||
|  | ||||
| module.exports = (deployer: any, network: string, accounts: string[]) => { | ||||
|     const defaultConfig = { | ||||
|         owners: [accounts[0], accounts[1]], | ||||
|         confirmationsRequired: 2, | ||||
|         secondsRequired: 0, | ||||
|     }; | ||||
|     const config = multiSigConfigByNetwork[network] || defaultConfig; | ||||
|     if (network !== 'live') { | ||||
|         deployer | ||||
|             .deploy(MultiSigWalletWithTimeLock, config.owners, config.confirmationsRequired, config.secondsRequired) | ||||
|             .then(() => { | ||||
|                 return deployer.deploy(TokenTransferProxy); | ||||
|             }) | ||||
|             .then(() => { | ||||
|                 return deployer.deploy(TokenRegistry); | ||||
|             }) | ||||
|             .then(() => { | ||||
|                 return deployer.deploy(EtherToken); | ||||
|             }); | ||||
|     } else { | ||||
|         deployer.deploy([ | ||||
|             [MultiSigWalletWithTimeLock, config.owners, config.confirmationsRequired, config.secondsRequired], | ||||
|             TokenTransferProxy, | ||||
|             TokenRegistry, | ||||
|         ]); | ||||
|     } | ||||
| }; | ||||
| @@ -1,95 +0,0 @@ | ||||
| import * as Bluebird from 'bluebird'; | ||||
| import * as _ from 'lodash'; | ||||
|  | ||||
| import { Artifacts } from '../util/artifacts'; | ||||
| import { constants } from '../util/constants'; | ||||
| import { ContractInstance, Token } from '../util/types'; | ||||
|  | ||||
| import { tokenInfo } from './config/token_info'; | ||||
| const { DummyToken, EtherToken, ZRXToken, TokenRegistry } = new Artifacts(artifacts); | ||||
|  | ||||
| module.exports = (deployer: any, network: string) => { | ||||
|     const tokens = network === 'live' ? tokenInfo.live : tokenInfo.development; | ||||
|     deployer | ||||
|         .then(() => { | ||||
|             return TokenRegistry.deployed(); | ||||
|         }) | ||||
|         .then((tokenRegistry: ContractInstance) => { | ||||
|             if (network !== 'live') { | ||||
|                 const totalSupply = Math.pow(10, 18) * 1000000000; | ||||
|                 return Bluebird.each( | ||||
|                     tokens.map((token: Token) => DummyToken.new(token.name, token.symbol, token.decimals, totalSupply)), | ||||
|                     _.noop, | ||||
|                 ).then((dummyTokens: ContractInstance[]) => { | ||||
|                     const weth = { | ||||
|                         address: EtherToken.address, | ||||
|                         name: 'Ether Token', | ||||
|                         symbol: 'WETH', | ||||
|                         url: '', | ||||
|                         decimals: 18, | ||||
|                         ipfsHash: constants.NULL_BYTES, | ||||
|                         swarmHash: constants.NULL_BYTES, | ||||
|                     }; | ||||
|                     return Bluebird.each( | ||||
|                         dummyTokens | ||||
|                             .map((tokenContract: ContractInstance, i: number) => { | ||||
|                                 const token = tokens[i]; | ||||
|                                 return tokenRegistry.addToken( | ||||
|                                     tokenContract.address, | ||||
|                                     token.name, | ||||
|                                     token.symbol, | ||||
|                                     token.decimals, | ||||
|                                     token.ipfsHash, | ||||
|                                     token.swarmHash, | ||||
|                                 ); | ||||
|                             }) | ||||
|                             .concat( | ||||
|                                 tokenRegistry.addToken( | ||||
|                                     weth.address, | ||||
|                                     weth.name, | ||||
|                                     weth.symbol, | ||||
|                                     weth.decimals, | ||||
|                                     weth.ipfsHash, | ||||
|                                     weth.swarmHash, | ||||
|                                 ), | ||||
|                             ), | ||||
|                         _.noop, | ||||
|                     ); | ||||
|                 }); | ||||
|             } else { | ||||
|                 const zrx = { | ||||
|                     address: ZRXToken.address, | ||||
|                     name: '0x Protocol Token', | ||||
|                     symbol: 'ZRX', | ||||
|                     url: 'https://www.0xproject.com/', | ||||
|                     decimals: 18, | ||||
|                     ipfsHash: constants.NULL_BYTES, | ||||
|                     swarmHash: constants.NULL_BYTES, | ||||
|                 }; | ||||
|                 return Bluebird.each( | ||||
|                     tokens | ||||
|                         .map((token: Token) => { | ||||
|                             return tokenRegistry.addToken( | ||||
|                                 token.address, | ||||
|                                 token.name, | ||||
|                                 token.symbol, | ||||
|                                 token.decimals, | ||||
|                                 token.ipfsHash, | ||||
|                                 token.swarmHash, | ||||
|                             ); | ||||
|                         }) | ||||
|                         .concat( | ||||
|                             tokenRegistry.addToken( | ||||
|                                 zrx.address, | ||||
|                                 zrx.name, | ||||
|                                 zrx.symbol, | ||||
|                                 zrx.decimals, | ||||
|                                 zrx.ipfsHash, | ||||
|                                 zrx.swarmHash, | ||||
|                             ), | ||||
|                         ), | ||||
|                     _.noop, | ||||
|                 ); | ||||
|             } | ||||
|         }); | ||||
| }; | ||||
| @@ -1,22 +0,0 @@ | ||||
| import { Artifacts } from '../util/artifacts'; | ||||
| import { ContractInstance } from '../util/types'; | ||||
| const { TokenTransferProxy, Exchange, TokenRegistry } = new Artifacts(artifacts); | ||||
|  | ||||
| let tokenTransferProxy: ContractInstance; | ||||
| module.exports = (deployer: any) => { | ||||
|     deployer | ||||
|         .then(async () => { | ||||
|             return Promise.all([TokenTransferProxy.deployed(), TokenRegistry.deployed()]); | ||||
|         }) | ||||
|         .then((instances: ContractInstance[]) => { | ||||
|             let tokenRegistry: ContractInstance; | ||||
|             [tokenTransferProxy, tokenRegistry] = instances; | ||||
|             return tokenRegistry.getTokenAddressBySymbol('ZRX'); | ||||
|         }) | ||||
|         .then((ptAddress: string) => { | ||||
|             return deployer.deploy(Exchange, ptAddress, tokenTransferProxy.address); | ||||
|         }) | ||||
|         .then(() => { | ||||
|             return tokenTransferProxy.addAuthorizedAddress(Exchange.address); | ||||
|         }); | ||||
| }; | ||||
| @@ -1,20 +0,0 @@ | ||||
| import { Artifacts } from '../util/artifacts'; | ||||
| import { ContractInstance } from '../util/types'; | ||||
| const { TokenTransferProxy, MultiSigWalletWithTimeLock, TokenRegistry } = new Artifacts(artifacts); | ||||
|  | ||||
| let tokenRegistry: ContractInstance; | ||||
| module.exports = (deployer: any, network: string) => { | ||||
|     if (network !== 'development') { | ||||
|         deployer.then(async () => { | ||||
|             return Promise.all([TokenTransferProxy.deployed(), TokenRegistry.deployed()]) | ||||
|                 .then((instances: ContractInstance[]) => { | ||||
|                     let tokenTransferProxy: ContractInstance; | ||||
|                     [tokenTransferProxy, tokenRegistry] = instances; | ||||
|                     return tokenTransferProxy.transferOwnership(MultiSigWalletWithTimeLock.address); | ||||
|                 }) | ||||
|                 .then(() => { | ||||
|                     return tokenRegistry.transferOwnership(MultiSigWalletWithTimeLock.address); | ||||
|                 }); | ||||
|         }); | ||||
|     } | ||||
| }; | ||||
| @@ -1,99 +0,0 @@ | ||||
| import { constants } from '../../util/constants'; | ||||
| import { TokenInfoByNetwork } from '../../util/types'; | ||||
|  | ||||
| export const tokenInfo: TokenInfoByNetwork = { | ||||
|     development: [ | ||||
|         { | ||||
|             name: '0x Protocol Token', | ||||
|             symbol: 'ZRX', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             name: 'Augur Reputation Token', | ||||
|             symbol: 'REP', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             name: 'Digix DAO Token', | ||||
|             symbol: 'DGD', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             name: 'Golem Network Token', | ||||
|             symbol: 'GNT', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             name: 'MakerDAO', | ||||
|             symbol: 'MKR', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             name: 'Melon Token', | ||||
|             symbol: 'MLN', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|     ], | ||||
|     live: [ | ||||
|         { | ||||
|             address: '0xecf8f87f810ecf450940c9f60066b4a7a501d6a7', | ||||
|             name: 'ETH Wrapper Token', | ||||
|             symbol: 'WETH', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             address: '0x48c80f1f4d53d5951e5d5438b54cba84f29f32a5', | ||||
|             name: 'Augur Reputation Token', | ||||
|             symbol: 'REP', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             address: '0xe0b7927c4af23765cb51314a0e0521a9645f0e2a', | ||||
|             name: 'Digix DAO Token', | ||||
|             symbol: 'DGD', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             address: '0xa74476443119a942de498590fe1f2454d7d4ac0d', | ||||
|             name: 'Golem Network Token', | ||||
|             symbol: 'GNT', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             address: '0xc66ea802717bfb9833400264dd12c2bceaa34a6d', | ||||
|             name: 'MakerDAO', | ||||
|             symbol: 'MKR', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|         { | ||||
|             address: '0xbeb9ef514a379b997e0798fdcc901ee474b6d9a1', | ||||
|             name: 'Melon Token', | ||||
|             symbol: 'MLN', | ||||
|             decimals: 18, | ||||
|             ipfsHash: constants.NULL_BYTES, | ||||
|             swarmHash: constants.NULL_BYTES, | ||||
|         }, | ||||
|     ], | ||||
| }; | ||||
| @@ -1,23 +1,24 @@ | ||||
| { | ||||
|     "private": true, | ||||
|     "name": "contracts", | ||||
|     "version": "2.1.1", | ||||
|     "version": "2.1.8", | ||||
|     "description": "Smart contract components of 0x protocol", | ||||
|     "main": "index.js", | ||||
|     "directories": { | ||||
|         "test": "test" | ||||
|     }, | ||||
|     "scripts": { | ||||
|         "build": | ||||
|             "rm -rf ./lib; copyfiles ./build/**/* ./deploy/solc/solc_bin/* ./deploy/test/fixtures/contracts/**/* ./deploy/test/fixtures/contracts/* ./lib; tsc;", | ||||
|         "test": "npm run build; truffle test", | ||||
|         "compile": "npm run build; node lib/deploy/cli.js compile", | ||||
|         "prebuild": "run-s clean copy_artifacts", | ||||
|         "copy_artifacts": "copyfiles './build/**/*' './deploy/solc/solc_bin/*' './deploy/test/fixtures/contracts/**/*' './deploy/test/fixtures/contracts/*' ./lib", | ||||
|         "build": "tsc", | ||||
|         "test": "run-s compile build run_mocha", | ||||
|         "run_mocha": "mocha 'lib/test/**/*.js' --timeout 10000 --bail --exit", | ||||
|         "compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846", | ||||
|         "compile": "node ../deployer/lib/src/cli.js compile", | ||||
|         "clean": "rm -rf ./lib", | ||||
|         "migrate:truffle": "npm run build; truffle migrate", | ||||
|         "migrate": "npm run build; node lib/deploy/cli.js migrate", | ||||
|         "migrate": "node ../deployer/lib/src/cli.js migrate", | ||||
|         "lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'", | ||||
|         "test:circleci": "yarn test; yarn test:deployer", | ||||
|         "test:deployer": "npm run build; mocha lib/deploy/test/*_test.js" | ||||
|         "test:circleci": "yarn test" | ||||
|     }, | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
| @@ -30,9 +31,9 @@ | ||||
|     }, | ||||
|     "homepage": "https://github.com/0xProject/0x.js/packages/contracts/README.md", | ||||
|     "devDependencies": { | ||||
|         "@0xproject/dev-utils": "^0.0.3", | ||||
|         "@0xproject/tslint-config": "^0.4.0", | ||||
|         "@0xproject/types": "^0.1.2", | ||||
|         "@0xproject/dev-utils": "^0.0.9", | ||||
|         "@0xproject/tslint-config": "^0.4.6", | ||||
|         "@0xproject/types": "^0.1.8", | ||||
|         "@types/bluebird": "^3.5.3", | ||||
|         "@types/lodash": "^4.14.86", | ||||
|         "@types/node": "^8.0.53", | ||||
| @@ -40,26 +41,27 @@ | ||||
|         "@types/yargs": "^10.0.0", | ||||
|         "chai": "^4.0.1", | ||||
|         "chai-as-promised": "^7.1.0", | ||||
|         "chai-as-promised-typescript-typings": "^0.0.3", | ||||
|         "chai-as-promised-typescript-typings": "^0.0.8", | ||||
|         "chai-bignumber": "^2.0.1", | ||||
|         "chai-typescript-typings": "^0.0.1", | ||||
|         "chai-typescript-typings": "^0.0.2", | ||||
|         "copyfiles": "^1.2.0", | ||||
|         "dirty-chai": "^2.0.1", | ||||
|         "mocha": "^4.0.1", | ||||
|         "npm-run-all": "^4.1.2", | ||||
|         "solc": "^0.4.18", | ||||
|         "truffle": "^4.0.1", | ||||
|         "tslint": "5.8.0", | ||||
|         "types-bn": "^0.0.1", | ||||
|         "types-ethereumjs-util": "0xProject/types-ethereumjs-util", | ||||
|         "types-ethereumjs-util": "0xproject/types-ethereumjs-util", | ||||
|         "typescript": "~2.6.1", | ||||
|         "web3-typescript-typings": "^0.9.0", | ||||
|         "web3-typescript-typings": "^0.9.8", | ||||
|         "yargs": "^10.0.3" | ||||
|     }, | ||||
|     "dependencies": { | ||||
|         "0x.js": "^0.29.0", | ||||
|         "@0xproject/json-schemas": "^0.7.1", | ||||
|         "@0xproject/utils": "^0.1.2", | ||||
|         "@0xproject/web3-wrapper": "^0.1.2", | ||||
|         "0x.js": "^0.31.1", | ||||
|         "@0xproject/deployer": "^0.0.5", | ||||
|         "@0xproject/json-schemas": "^0.7.7", | ||||
|         "@0xproject/utils": "^0.2.4", | ||||
|         "@0xproject/web3-wrapper": "^0.1.9", | ||||
|         "bluebird": "^3.5.0", | ||||
|         "bn.js": "^4.11.8", | ||||
|         "ethereumjs-abi": "^0.6.4", | ||||
|   | ||||
| @@ -1,46 +1,46 @@ | ||||
| import { ZeroEx, ZeroExError } from '0x.js'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber, promisify } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import Web3 = require('web3'); | ||||
| 
 | ||||
| import { Artifacts } from '../../util/artifacts'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { constants } from '../util/constants'; | ||||
| import { ContractName } from '../util/types'; | ||||
| 
 | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| 
 | ||||
| const { EtherToken } = new Artifacts(artifacts); | ||||
| import { deployer } from './utils/deployer'; | ||||
| 
 | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| 
 | ||||
| // In order to benefit from type-safety, we re-assign the global web3 instance injected by Truffle
 | ||||
| // with type `any` to a variable of type `Web3`.
 | ||||
| const web3: Web3 = (global as any).web3; | ||||
| 
 | ||||
| contract('EtherToken', (accounts: string[]) => { | ||||
|     const account = accounts[0]; | ||||
| describe('EtherToken', () => { | ||||
|     let account: string; | ||||
|     const gasPrice = ZeroEx.toBaseUnitAmount(new BigNumber(20), 9); | ||||
|     let zeroEx: ZeroEx; | ||||
|     let etherTokenAddress: string; | ||||
| 
 | ||||
|     before(async () => { | ||||
|         etherTokenAddress = EtherToken.address; | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         account = accounts[0]; | ||||
| 
 | ||||
|         const etherToken = await deployer.deployAsync(ContractName.EtherToken); | ||||
|         etherTokenAddress = etherToken.address; | ||||
|         zeroEx = new ZeroEx(web3.currentProvider, { | ||||
|             gasPrice, | ||||
|             networkId: constants.TESTRPC_NETWORK_ID, | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     const sendTransactionAsync = promisify<string>(web3.eth.sendTransaction); | ||||
|     const getEthBalanceAsync = async (owner: string) => { | ||||
|         const balanceStr = await promisify<string>(web3.eth.getBalance)(owner); | ||||
|         const balance = new BigNumber(balanceStr); | ||||
|         return balance; | ||||
|     }; | ||||
| 
 | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|     describe('deposit', () => { | ||||
|         it('should throw if caller attempts to deposit more Ether than caller balance', async () => { | ||||
|             const initEthBalance = await getEthBalanceAsync(account); | ||||
|             const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); | ||||
|             const ethToDeposit = initEthBalance.plus(1); | ||||
| 
 | ||||
|             return expect(zeroEx.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account)).to.be.rejectedWith( | ||||
| @@ -49,7 +49,7 @@ contract('EtherToken', (accounts: string[]) => { | ||||
|         }); | ||||
| 
 | ||||
|         it('should convert deposited Ether to wrapped Ether tokens', async () => { | ||||
|             const initEthBalance = await getEthBalanceAsync(account); | ||||
|             const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); | ||||
|             const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); | ||||
| 
 | ||||
|             const ethToDeposit = new BigNumber(web3.toWei(1, 'ether')); | ||||
| @@ -58,7 +58,7 @@ contract('EtherToken', (accounts: string[]) => { | ||||
|             const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
| 
 | ||||
|             const ethSpentOnGas = gasPrice.times(receipt.gasUsed); | ||||
|             const finalEthBalance = await getEthBalanceAsync(account); | ||||
|             const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); | ||||
|             const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); | ||||
| 
 | ||||
|             expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas))); | ||||
| @@ -77,8 +77,10 @@ contract('EtherToken', (accounts: string[]) => { | ||||
|         }); | ||||
| 
 | ||||
|         it('should convert ether tokens to ether with sufficient balance', async () => { | ||||
|             const ethToDeposit = new BigNumber(web3.toWei(1, 'ether')); | ||||
|             await zeroEx.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account); | ||||
|             const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); | ||||
|             const initEthBalance = await getEthBalanceAsync(account); | ||||
|             const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); | ||||
|             const ethTokensToWithdraw = initEthTokenBalance; | ||||
|             expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0); | ||||
|             const txHash = await zeroEx.etherToken.withdrawAsync(etherTokenAddress, ethTokensToWithdraw, account, { | ||||
| @@ -87,7 +89,7 @@ contract('EtherToken', (accounts: string[]) => { | ||||
|             const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
| 
 | ||||
|             const ethSpentOnGas = gasPrice.times(receipt.gasUsed); | ||||
|             const finalEthBalance = await getEthBalanceAsync(account); | ||||
|             const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); | ||||
|             const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); | ||||
| 
 | ||||
|             expect(finalEthBalance).to.be.bignumber.equal( | ||||
| @@ -99,12 +101,12 @@ contract('EtherToken', (accounts: string[]) => { | ||||
| 
 | ||||
|     describe('fallback', () => { | ||||
|         it('should convert sent ether to ether tokens', async () => { | ||||
|             const initEthBalance = await getEthBalanceAsync(account); | ||||
|             const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); | ||||
|             const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); | ||||
| 
 | ||||
|             const ethToDeposit = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18); | ||||
| 
 | ||||
|             const txHash = await sendTransactionAsync({ | ||||
|             const txHash = await web3Wrapper.sendTransactionAsync({ | ||||
|                 from: account, | ||||
|                 to: etherTokenAddress, | ||||
|                 value: ethToDeposit, | ||||
| @@ -114,7 +116,7 @@ contract('EtherToken', (accounts: string[]) => { | ||||
|             const receipt = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
| 
 | ||||
|             const ethSpentOnGas = gasPrice.times(receipt.gasUsed); | ||||
|             const finalEthBalance = await getEthBalanceAsync(account); | ||||
|             const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); | ||||
|             const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account); | ||||
| 
 | ||||
|             expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas))); | ||||
| @@ -1,41 +1,47 @@ | ||||
| import { ZeroEx } from '0x.js'; | ||||
| import { | ||||
|     LogCancelContractEventArgs, | ||||
|     LogErrorContractEventArgs, | ||||
|     LogFillContractEventArgs, | ||||
|     LogWithDecodedArgs, | ||||
|     TransactionReceiptWithDecodedLogs, | ||||
|     ZeroEx, | ||||
| } from '0x.js'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import ethUtil = require('ethereumjs-util'); | ||||
| import * as Web3 from 'web3'; | ||||
| 
 | ||||
| import { Artifacts } from '../../../util/artifacts'; | ||||
| import { Balances } from '../../../util/balances'; | ||||
| import { constants } from '../../../util/constants'; | ||||
| import { crypto } from '../../../util/crypto'; | ||||
| import { ExchangeWrapper } from '../../../util/exchange_wrapper'; | ||||
| import { Order } from '../../../util/order'; | ||||
| import { OrderFactory } from '../../../util/order_factory'; | ||||
| import { BalancesByOwner, ContractInstance, ExchangeContractErrs } from '../../../util/types'; | ||||
| import { Balances } from '../../util/balances'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { crypto } from '../../util/crypto'; | ||||
| import { ExchangeWrapper } from '../../util/exchange_wrapper'; | ||||
| import { Order } from '../../util/order'; | ||||
| import { OrderFactory } from '../../util/order_factory'; | ||||
| import { BalancesByOwner, ContractName, ExchangeContractErrs } from '../../util/types'; | ||||
| import { chaiSetup } from '../utils/chai_setup'; | ||||
| import { deployer } from '../utils/deployer'; | ||||
| 
 | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const { Exchange, TokenTransferProxy, DummyToken, TokenRegistry, MaliciousToken } = new Artifacts(artifacts); | ||||
| 
 | ||||
| // In order to benefit from type-safety, we re-assign the global web3 instance injected by Truffle
 | ||||
| // with type `any` to a variable of type `Web3`.
 | ||||
| const web3: Web3 = (global as any).web3; | ||||
| 
 | ||||
| contract('Exchange', (accounts: string[]) => { | ||||
|     const maker = accounts[0]; | ||||
|     const tokenOwner = accounts[0]; | ||||
|     const taker = accounts[1] || accounts[accounts.length - 1]; | ||||
|     const feeRecipient = accounts[2] || accounts[accounts.length - 1]; | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| 
 | ||||
| describe('Exchange', () => { | ||||
|     let maker: string; | ||||
|     let tokenOwner: string; | ||||
|     let taker: string; | ||||
|     let feeRecipient: string; | ||||
|     const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); | ||||
|     const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); | ||||
| 
 | ||||
|     let rep: ContractInstance; | ||||
|     let dgd: ContractInstance; | ||||
|     let zrx: ContractInstance; | ||||
|     let exchange: ContractInstance; | ||||
|     let tokenRegistry: ContractInstance; | ||||
|     let rep: Web3.ContractInstance; | ||||
|     let dgd: Web3.ContractInstance; | ||||
|     let zrx: Web3.ContractInstance; | ||||
|     let exchange: Web3.ContractInstance; | ||||
|     let tokenTransferProxy: Web3.ContractInstance; | ||||
| 
 | ||||
|     let order: Order; | ||||
|     let balances: BalancesByOwner; | ||||
| @@ -46,66 +52,69 @@ contract('Exchange', (accounts: string[]) => { | ||||
|     let zeroEx: ZeroEx; | ||||
| 
 | ||||
|     before(async () => { | ||||
|         [tokenRegistry, exchange] = await Promise.all([TokenRegistry.deployed(), Exchange.deployed()]); | ||||
|         exWrapper = new ExchangeWrapper(exchange); | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         maker = accounts[0]; | ||||
|         [tokenOwner, taker, feeRecipient] = accounts; | ||||
|         [rep, dgd, zrx] = await Promise.all([ | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|         ]); | ||||
|         tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); | ||||
|         exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]); | ||||
|         await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] }); | ||||
|         zeroEx = new ZeroEx(web3.currentProvider, { | ||||
|             exchangeContractAddress: exchange.address, | ||||
|             networkId: constants.TESTRPC_NETWORK_ID, | ||||
|         }); | ||||
| 
 | ||||
|         const [repAddress, dgdAddress, zrxAddress] = await Promise.all([ | ||||
|             tokenRegistry.getTokenAddressBySymbol('REP'), | ||||
|             tokenRegistry.getTokenAddressBySymbol('DGD'), | ||||
|             tokenRegistry.getTokenAddressBySymbol('ZRX'), | ||||
|         ]); | ||||
|         exWrapper = new ExchangeWrapper(exchange, zeroEx); | ||||
| 
 | ||||
|         const defaultOrderParams = { | ||||
|             exchangeContractAddress: Exchange.address, | ||||
|             exchangeContractAddress: exchange.address, | ||||
|             maker, | ||||
|             feeRecipient, | ||||
|             makerToken: repAddress, | ||||
|             takerToken: dgdAddress, | ||||
|             makerToken: rep.address, | ||||
|             takerToken: dgd.address, | ||||
|             makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), | ||||
|             takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), | ||||
|             makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), | ||||
|             takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), | ||||
|         }; | ||||
|         orderFactory = new OrderFactory(defaultOrderParams); | ||||
| 
 | ||||
|         [rep, dgd, zrx] = await Promise.all([ | ||||
|             DummyToken.at(repAddress), | ||||
|             DummyToken.at(dgdAddress), | ||||
|             DummyToken.at(zrxAddress), | ||||
|         ]); | ||||
|         orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams); | ||||
|         dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]); | ||||
|         await Promise.all([ | ||||
|             rep.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: maker, | ||||
|             }), | ||||
|             rep.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: taker, | ||||
|             }), | ||||
|             rep.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }), | ||||
|             rep.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }), | ||||
|             dgd.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: maker, | ||||
|             }), | ||||
|             dgd.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: taker, | ||||
|             }), | ||||
|             dgd.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }), | ||||
|             dgd.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }), | ||||
|             zrx.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: maker, | ||||
|             }), | ||||
|             zrx.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: taker, | ||||
|             }), | ||||
|             zrx.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }), | ||||
|             zrx.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }), | ||||
|         ]); | ||||
|     }); | ||||
| 
 | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|     describe('internal functions', () => { | ||||
|         it('should include transferViaTokenTransferProxy', () => { | ||||
|             expect(exchange.transferViaTokenTransferProxy).to.be.undefined(); | ||||
| @@ -136,9 +145,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
|                 takerTokenAmount: new BigNumber(3), | ||||
|             }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0); | ||||
| 
 | ||||
|             const fillTakerTokenAmount1 = new BigNumber(2); | ||||
| @@ -146,9 +154,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
|                 fillTakerTokenAmount: fillTakerTokenAmount1, | ||||
|             }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountAfter1 = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountAfter1 = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountAfter1).to.be.bignumber.equal(fillTakerTokenAmount1); | ||||
| 
 | ||||
|             const fillTakerTokenAmount2 = new BigNumber(1); | ||||
| @@ -156,9 +163,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
|                 fillTakerTokenAmount: fillTakerTokenAmount2, | ||||
|             }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountAfter2 = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountAfter2 = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountAfter2).to.be.bignumber.equal(filledTakerTokenAmountAfter1); | ||||
|         }); | ||||
| 
 | ||||
| @@ -168,17 +174,15 @@ contract('Exchange', (accounts: string[]) => { | ||||
|                 takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), | ||||
|             }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0); | ||||
| 
 | ||||
|             const fillTakerTokenAmount = order.params.takerTokenAmount.div(2); | ||||
|             await exWrapper.fillOrderAsync(order, taker, { fillTakerTokenAmount }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountAfter = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountAfter = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountAfter).to.be.bignumber.equal(fillTakerTokenAmount); | ||||
| 
 | ||||
|             const newBalances = await dmyBalances.getAsync(); | ||||
| @@ -221,17 +225,15 @@ contract('Exchange', (accounts: string[]) => { | ||||
|                 takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), | ||||
|             }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0); | ||||
| 
 | ||||
|             const fillTakerTokenAmount = order.params.takerTokenAmount.div(2); | ||||
|             await exWrapper.fillOrderAsync(order, taker, { fillTakerTokenAmount }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountAfter = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountAfter = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountAfter).to.be.bignumber.equal(fillTakerTokenAmount); | ||||
| 
 | ||||
|             const newBalances = await dmyBalances.getAsync(); | ||||
| @@ -274,17 +276,15 @@ contract('Exchange', (accounts: string[]) => { | ||||
|                 takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), | ||||
|             }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0); | ||||
| 
 | ||||
|             const fillTakerTokenAmount = order.params.takerTokenAmount.div(2); | ||||
|             await exWrapper.fillOrderAsync(order, taker, { fillTakerTokenAmount }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountAfter = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountAfter = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountAfter).to.be.bignumber.equal(fillTakerTokenAmount); | ||||
| 
 | ||||
|             const newBalances = await dmyBalances.getAsync(); | ||||
| @@ -328,17 +328,15 @@ contract('Exchange', (accounts: string[]) => { | ||||
|                 takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), | ||||
|             }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountBefore = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             expect(filledTakerTokenAmountBefore).to.be.bignumber.equal(0); | ||||
| 
 | ||||
|             const fillTakerTokenAmount = order.params.takerTokenAmount.div(2); | ||||
|             await exWrapper.fillOrderAsync(order, taker, { fillTakerTokenAmount }); | ||||
| 
 | ||||
|             const filledTakerTokenAmountAfter = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                 order.params.orderHashHex, | ||||
|             ); | ||||
|             const filledTakerTokenAmountAfter = await zeroEx.exchange.getFilledTakerAmountAsync(order.params | ||||
|                 .orderHashHex as string); | ||||
|             const expectedFillAmountTAfter = fillTakerTokenAmount.add(filledTakerTokenAmountBefore); | ||||
|             expect(filledTakerTokenAmountAfter).to.be.bignumber.equal(expectedFillAmountTAfter); | ||||
| 
 | ||||
| @@ -383,8 +381,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
|             const res = await exWrapper.fillOrderAsync(order, taker, { | ||||
|                 fillTakerTokenAmount: order.params.takerTokenAmount, | ||||
|             }); | ||||
| 
 | ||||
|             expect(res.logs[0].args.filledTakerTokenAmount).to.be.bignumber.equal( | ||||
|             const log = res.logs[0] as LogWithDecodedArgs<LogFillContractEventArgs>; | ||||
|             expect(log.args.filledTakerTokenAmount).to.be.bignumber.equal( | ||||
|                 order.params.takerTokenAmount.minus(fillTakerTokenAmount), | ||||
|             ); | ||||
|             const newBalances = await dmyBalances.getAsync(); | ||||
| @@ -419,7 +417,7 @@ contract('Exchange', (accounts: string[]) => { | ||||
|             }); | ||||
|             expect(res.logs).to.have.length(1); | ||||
| 
 | ||||
|             const logArgs = res.logs[0].args; | ||||
|             const logArgs = (res.logs[0] as LogWithDecodedArgs<LogFillContractEventArgs>).args; | ||||
|             const expectedFilledMakerTokenAmount = order.params.makerTokenAmount.div(divisor); | ||||
|             const expectedFilledTakerTokenAmount = order.params.takerTokenAmount.div(divisor); | ||||
|             const expectedFeeMPaid = order.params.makerFee.div(divisor); | ||||
| @@ -450,7 +448,7 @@ contract('Exchange', (accounts: string[]) => { | ||||
|             }); | ||||
|             expect(res.logs).to.have.length(1); | ||||
| 
 | ||||
|             const logArgs = res.logs[0].args; | ||||
|             const logArgs = (res.logs[0] as LogWithDecodedArgs<LogFillContractEventArgs>).args; | ||||
|             const expectedFilledMakerTokenAmount = order.params.makerTokenAmount.div(divisor); | ||||
|             const expectedFilledTakerTokenAmount = order.params.takerTokenAmount.div(divisor); | ||||
|             const expectedFeeMPaid = new BigNumber(0); | ||||
| @@ -567,9 +565,9 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|         it('should not change balances if maker allowances are too low to fill order and \ | ||||
|                 shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { | ||||
|             await rep.approve(TokenTransferProxy.address, 0, { from: maker }); | ||||
|             await rep.approve(tokenTransferProxy.address, 0, { from: maker }); | ||||
|             await exWrapper.fillOrderAsync(order, taker); | ||||
|             await rep.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             await rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: maker, | ||||
|             }); | ||||
| 
 | ||||
| @@ -579,22 +577,22 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|         it('should throw if maker allowances are too low to fill order and \ | ||||
|                 shouldThrowOnInsufficientBalanceOrAllowance = true', async () => { | ||||
|             await rep.approve(TokenTransferProxy.address, 0, { from: maker }); | ||||
|             await rep.approve(tokenTransferProxy.address, 0, { from: maker }); | ||||
|             expect( | ||||
|                 exWrapper.fillOrderAsync(order, taker, { | ||||
|                     shouldThrowOnInsufficientBalanceOrAllowance: true, | ||||
|                 }), | ||||
|             ).to.be.rejectedWith(constants.REVERT); | ||||
|             await rep.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             await rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: maker, | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         it('should not change balances if taker allowances are too low to fill order and \ | ||||
|                 shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { | ||||
|             await dgd.approve(TokenTransferProxy.address, 0, { from: taker }); | ||||
|             await dgd.approve(tokenTransferProxy.address, 0, { from: taker }); | ||||
|             await exWrapper.fillOrderAsync(order, taker); | ||||
|             await dgd.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             await dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: taker, | ||||
|             }); | ||||
| 
 | ||||
| @@ -604,13 +602,13 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|         it('should throw if taker allowances are too low to fill order and \ | ||||
|                 shouldThrowOnInsufficientBalanceOrAllowance = true', async () => { | ||||
|             await dgd.approve(TokenTransferProxy.address, 0, { from: taker }); | ||||
|             await dgd.approve(tokenTransferProxy.address, 0, { from: taker }); | ||||
|             expect( | ||||
|                 exWrapper.fillOrderAsync(order, taker, { | ||||
|                     shouldThrowOnInsufficientBalanceOrAllowance: true, | ||||
|                 }), | ||||
|             ).to.be.rejectedWith(constants.REVERT); | ||||
|             await dgd.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|             await dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { | ||||
|                 from: taker, | ||||
|             }); | ||||
|         }); | ||||
| @@ -630,7 +628,7 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|         it('should not change balances if makerToken is ZRX, makerTokenAmount + makerFee > maker allowance, \ | ||||
|                 and shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { | ||||
|             const makerZRXAllowance = await zrx.allowance(maker, TokenTransferProxy.address); | ||||
|             const makerZRXAllowance = await zrx.allowance(maker, tokenTransferProxy.address); | ||||
|             order = await orderFactory.newSignedOrderAsync({ | ||||
|                 makerToken: zrx.address, | ||||
|                 makerTokenAmount: new BigNumber(makerZRXAllowance), | ||||
| @@ -656,7 +654,7 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|         it('should not change balances if takerToken is ZRX, takerTokenAmount + takerFee > taker allowance, \ | ||||
|                 and shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { | ||||
|             const takerZRXAllowance = await zrx.allowance(taker, TokenTransferProxy.address); | ||||
|             const takerZRXAllowance = await zrx.allowance(taker, tokenTransferProxy.address); | ||||
|             order = await orderFactory.newSignedOrderAsync({ | ||||
|                 takerToken: zrx.address, | ||||
|                 takerTokenAmount: new BigNumber(takerZRXAllowance), | ||||
| @@ -669,8 +667,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|         it('should throw if getBalance or getAllowance attempts to change state and \ | ||||
|                 shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { | ||||
|             const maliciousToken = await MaliciousToken.new(); | ||||
|             await maliciousToken.approve(TokenTransferProxy.address, INITIAL_ALLOWANCE, { from: taker }); | ||||
|             const maliciousToken = await deployer.deployAsync(ContractName.MaliciousToken); | ||||
|             await maliciousToken.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: taker }); | ||||
| 
 | ||||
|             order = await orderFactory.newSignedOrderAsync({ | ||||
|                 takerToken: maliciousToken.address, | ||||
| @@ -680,7 +678,7 @@ contract('Exchange', (accounts: string[]) => { | ||||
|                 exWrapper.fillOrderAsync(order, taker, { | ||||
|                     shouldThrowOnInsufficientBalanceOrAllowance: false, | ||||
|                 }), | ||||
|             ).to.be.rejectedWith(constants.REVERT); | ||||
|             ).to.be.rejectedWith(constants.INVALID_OPCODE); | ||||
|         }); | ||||
| 
 | ||||
|         it('should not change balances if an order is expired', async () => { | ||||
| @@ -700,16 +698,19 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|             const res = await exWrapper.fillOrderAsync(order, taker); | ||||
|             expect(res.logs).to.have.length(1); | ||||
|             const errCode = res.logs[0].args.errorId.toNumber(); | ||||
|             const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>; | ||||
|             const errCode = log.args.errorId.toNumber(); | ||||
|             expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_EXPIRED); | ||||
|         }); | ||||
| 
 | ||||
|         it('should log an error event if no value is filled', async () => { | ||||
|             order = await orderFactory.newSignedOrderAsync({}); | ||||
|             await exWrapper.fillOrderAsync(order, taker); | ||||
| 
 | ||||
|             const res = await exWrapper.fillOrderAsync(order, taker); | ||||
|             expect(res.logs).to.have.length(1); | ||||
|             const errCode = res.logs[0].args.errorId.toNumber(); | ||||
|             const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>; | ||||
|             const errCode = log.args.errorId.toNumber(); | ||||
|             expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_FULLY_FILLED_OR_CANCELLED); | ||||
|         }); | ||||
|     }); | ||||
| @@ -769,7 +770,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
|             const res = await exWrapper.fillOrderAsync(order, taker, { | ||||
|                 fillTakerTokenAmount: order.params.takerTokenAmount, | ||||
|             }); | ||||
|             expect(res.logs[0].args.filledTakerTokenAmount).to.be.bignumber.equal( | ||||
|             const log = res.logs[0] as LogWithDecodedArgs<LogFillContractEventArgs>; | ||||
|             expect(log.args.filledTakerTokenAmount).to.be.bignumber.equal( | ||||
|                 order.params.takerTokenAmount.minus(cancelTakerTokenAmount), | ||||
|             ); | ||||
| 
 | ||||
| @@ -813,7 +815,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
|             }); | ||||
|             expect(res.logs).to.have.length(1); | ||||
| 
 | ||||
|             const logArgs = res.logs[0].args; | ||||
|             const log = res.logs[0] as LogWithDecodedArgs<LogCancelContractEventArgs>; | ||||
|             const logArgs = log.args; | ||||
|             const expectedCancelledMakerTokenAmount = order.params.makerTokenAmount.div(divisor); | ||||
|             const expectedCancelledTakerTokenAmount = order.params.takerTokenAmount.div(divisor); | ||||
|             const tokensHashBuff = crypto.solSHA3([order.params.makerToken, order.params.takerToken]); | ||||
| @@ -834,7 +837,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|             const res = await exWrapper.cancelOrderAsync(order, maker); | ||||
|             expect(res.logs).to.have.length(1); | ||||
|             const errCode = res.logs[0].args.errorId.toNumber(); | ||||
|             const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>; | ||||
|             const errCode = log.args.errorId.toNumber(); | ||||
|             expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_FULLY_FILLED_OR_CANCELLED); | ||||
|         }); | ||||
| 
 | ||||
| @@ -845,7 +849,8 @@ contract('Exchange', (accounts: string[]) => { | ||||
| 
 | ||||
|             const res = await exWrapper.cancelOrderAsync(order, maker); | ||||
|             expect(res.logs).to.have.length(1); | ||||
|             const errCode = res.logs[0].args.errorId.toNumber(); | ||||
|             const log = res.logs[0] as LogWithDecodedArgs<LogErrorContractEventArgs>; | ||||
|             const errCode = log.args.errorId.toNumber(); | ||||
|             expect(errCode).to.be.equal(ExchangeContractErrs.ERROR_ORDER_EXPIRED); | ||||
|         }); | ||||
|     }); | ||||
| @@ -1,52 +1,68 @@ | ||||
| import { ZeroEx } from '0x.js'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import ethUtil = require('ethereumjs-util'); | ||||
| 
 | ||||
| import { Artifacts } from '../../../util/artifacts'; | ||||
| import { ExchangeWrapper } from '../../../util/exchange_wrapper'; | ||||
| import { Order } from '../../../util/order'; | ||||
| import { OrderFactory } from '../../../util/order_factory'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { ExchangeWrapper } from '../../util/exchange_wrapper'; | ||||
| import { Order } from '../../util/order'; | ||||
| import { OrderFactory } from '../../util/order_factory'; | ||||
| import { ContractName } from '../../util/types'; | ||||
| import { chaiSetup } from '../utils/chai_setup'; | ||||
| import { deployer } from '../utils/deployer'; | ||||
| 
 | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| 
 | ||||
| const { Exchange, TokenRegistry } = new Artifacts(artifacts); | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| 
 | ||||
| contract('Exchange', (accounts: string[]) => { | ||||
|     const maker = accounts[0]; | ||||
|     const feeRecipient = accounts[1] || accounts[accounts.length - 1]; | ||||
| describe('Exchange', () => { | ||||
|     let maker: string; | ||||
|     let feeRecipient: string; | ||||
| 
 | ||||
|     let order: Order; | ||||
|     let exchangeWrapper: ExchangeWrapper; | ||||
|     let orderFactory: OrderFactory; | ||||
| 
 | ||||
|     before(async () => { | ||||
|         const [tokenRegistry, exchange] = await Promise.all([TokenRegistry.deployed(), Exchange.deployed()]); | ||||
|         exchangeWrapper = new ExchangeWrapper(exchange); | ||||
|         const [repAddress, dgdAddress] = await Promise.all([ | ||||
|             tokenRegistry.getTokenAddressBySymbol('REP'), | ||||
|             tokenRegistry.getTokenAddressBySymbol('DGD'), | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         [maker, feeRecipient] = accounts; | ||||
|         const tokenRegistry = await deployer.deployAsync(ContractName.TokenRegistry); | ||||
|         const tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); | ||||
|         const [rep, dgd, zrx] = await Promise.all([ | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|         ]); | ||||
|         const exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]); | ||||
|         await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] }); | ||||
|         const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID }); | ||||
|         exchangeWrapper = new ExchangeWrapper(exchange, zeroEx); | ||||
|         const defaultOrderParams = { | ||||
|             exchangeContractAddress: Exchange.address, | ||||
|             exchangeContractAddress: exchange.address, | ||||
|             maker, | ||||
|             feeRecipient, | ||||
|             makerToken: repAddress, | ||||
|             takerToken: dgdAddress, | ||||
|             makerToken: rep.address, | ||||
|             takerToken: dgd.address, | ||||
|             makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), | ||||
|             takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), | ||||
|             makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), | ||||
|             takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), | ||||
|         }; | ||||
|         orderFactory = new OrderFactory(defaultOrderParams); | ||||
|     }); | ||||
| 
 | ||||
|     beforeEach(async () => { | ||||
|         orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams); | ||||
|         order = await orderFactory.newSignedOrderAsync(); | ||||
|     }); | ||||
| 
 | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|     describe('getOrderHash', () => { | ||||
|         it('should output the correct orderHash', async () => { | ||||
|             const orderHashHex = await exchangeWrapper.getOrderHashAsync(order); | ||||
| @@ -1,35 +1,41 @@ | ||||
| import { ZeroEx } from '0x.js'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import * as _ from 'lodash'; | ||||
| import * as Web3 from 'web3'; | ||||
| 
 | ||||
| import { Artifacts } from '../../../util/artifacts'; | ||||
| import { Balances } from '../../../util/balances'; | ||||
| import { constants } from '../../../util/constants'; | ||||
| import { ExchangeWrapper } from '../../../util/exchange_wrapper'; | ||||
| import { Order } from '../../../util/order'; | ||||
| import { OrderFactory } from '../../../util/order_factory'; | ||||
| import { BalancesByOwner, ContractInstance } from '../../../util/types'; | ||||
| import { Balances } from '../../util/balances'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { ExchangeWrapper } from '../../util/exchange_wrapper'; | ||||
| import { Order } from '../../util/order'; | ||||
| import { OrderFactory } from '../../util/order_factory'; | ||||
| import { BalancesByOwner, ContractName } from '../../util/types'; | ||||
| import { chaiSetup } from '../utils/chai_setup'; | ||||
| import { deployer } from '../utils/deployer'; | ||||
| 
 | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const { Exchange, TokenTransferProxy, DummyToken, TokenRegistry } = new Artifacts(artifacts); | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| 
 | ||||
| contract('Exchange', (accounts: string[]) => { | ||||
|     const maker = accounts[0]; | ||||
|     const tokenOwner = accounts[0]; | ||||
|     const taker = accounts[1] || accounts[accounts.length - 1]; | ||||
|     const feeRecipient = accounts[2] || accounts[accounts.length - 1]; | ||||
| describe('Exchange', () => { | ||||
|     let maker: string; | ||||
|     let tokenOwner: string; | ||||
|     let taker: string; | ||||
|     let feeRecipient: string; | ||||
| 
 | ||||
|     const INIT_BAL = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); | ||||
|     const INIT_ALLOW = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); | ||||
| 
 | ||||
|     let rep: ContractInstance; | ||||
|     let dgd: ContractInstance; | ||||
|     let zrx: ContractInstance; | ||||
|     let exchange: ContractInstance; | ||||
|     let tokenRegistry: ContractInstance; | ||||
|     let rep: Web3.ContractInstance; | ||||
|     let dgd: Web3.ContractInstance; | ||||
|     let zrx: Web3.ContractInstance; | ||||
|     let exchange: Web3.ContractInstance; | ||||
|     let tokenRegistry: Web3.ContractInstance; | ||||
|     let tokenTransferProxy: Web3.ContractInstance; | ||||
| 
 | ||||
|     let balances: BalancesByOwner; | ||||
| 
 | ||||
| @@ -38,49 +44,56 @@ contract('Exchange', (accounts: string[]) => { | ||||
|     let orderFactory: OrderFactory; | ||||
| 
 | ||||
|     before(async () => { | ||||
|         [tokenRegistry, exchange] = await Promise.all([TokenRegistry.deployed(), Exchange.deployed()]); | ||||
|         exWrapper = new ExchangeWrapper(exchange); | ||||
|         const [repAddress, dgdAddress, zrxAddress] = await Promise.all([ | ||||
|             tokenRegistry.getTokenAddressBySymbol('REP'), | ||||
|             tokenRegistry.getTokenAddressBySymbol('DGD'), | ||||
|             tokenRegistry.getTokenAddressBySymbol('ZRX'), | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         tokenOwner = accounts[0]; | ||||
|         [maker, taker, feeRecipient] = accounts; | ||||
|         [rep, dgd, zrx] = await Promise.all([ | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|             deployer.deployAsync(ContractName.DummyToken), | ||||
|         ]); | ||||
|         tokenRegistry = await deployer.deployAsync(ContractName.TokenRegistry); | ||||
|         tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); | ||||
|         exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]); | ||||
|         await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] }); | ||||
|         const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID }); | ||||
|         exWrapper = new ExchangeWrapper(exchange, zeroEx); | ||||
| 
 | ||||
|         const defaultOrderParams = { | ||||
|             exchangeContractAddress: Exchange.address, | ||||
|             exchangeContractAddress: exchange.address, | ||||
|             maker, | ||||
|             feeRecipient, | ||||
|             makerToken: repAddress, | ||||
|             takerToken: dgdAddress, | ||||
|             makerToken: rep.address, | ||||
|             takerToken: dgd.address, | ||||
|             makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18), | ||||
|             takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18), | ||||
|             makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), | ||||
|             takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18), | ||||
|         }; | ||||
|         orderFactory = new OrderFactory(defaultOrderParams); | ||||
| 
 | ||||
|         [rep, dgd, zrx] = await Promise.all([ | ||||
|             DummyToken.at(repAddress), | ||||
|             DummyToken.at(dgdAddress), | ||||
|             DummyToken.at(zrxAddress), | ||||
|         ]); | ||||
|         orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams); | ||||
|         dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]); | ||||
|         await Promise.all([ | ||||
|             rep.approve(TokenTransferProxy.address, INIT_ALLOW, { from: maker }), | ||||
|             rep.approve(TokenTransferProxy.address, INIT_ALLOW, { from: taker }), | ||||
|             rep.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }), | ||||
|             rep.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }), | ||||
|             rep.setBalance(maker, INIT_BAL, { from: tokenOwner }), | ||||
|             rep.setBalance(taker, INIT_BAL, { from: tokenOwner }), | ||||
|             dgd.approve(TokenTransferProxy.address, INIT_ALLOW, { from: maker }), | ||||
|             dgd.approve(TokenTransferProxy.address, INIT_ALLOW, { from: taker }), | ||||
|             dgd.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }), | ||||
|             dgd.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }), | ||||
|             dgd.setBalance(maker, INIT_BAL, { from: tokenOwner }), | ||||
|             dgd.setBalance(taker, INIT_BAL, { from: tokenOwner }), | ||||
|             zrx.approve(TokenTransferProxy.address, INIT_ALLOW, { from: maker }), | ||||
|             zrx.approve(TokenTransferProxy.address, INIT_ALLOW, { from: taker }), | ||||
|             zrx.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }), | ||||
|             zrx.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }), | ||||
|             zrx.setBalance(maker, INIT_BAL, { from: tokenOwner }), | ||||
|             zrx.setBalance(taker, INIT_BAL, { from: tokenOwner }), | ||||
|         ]); | ||||
|     }); | ||||
| 
 | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|     describe('fillOrKillOrder', () => { | ||||
|         beforeEach(async () => { | ||||
|             balances = await dmyBalances.getAsync(); | ||||
							
								
								
									
										191
									
								
								packages/contracts/test/multi_sig_with_time_lock.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								packages/contracts/test/multi_sig_with_time_lock.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| import { LogWithDecodedArgs, ZeroEx } from '0x.js'; | ||||
| import { BlockchainLifecycle, RPC, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { AbiDecoder, BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import * as Web3 from 'web3'; | ||||
|  | ||||
| import * as multiSigWalletJSON from '../../build/contracts/MultiSigWalletWithTimeLock.json'; | ||||
| import { artifacts } from '../util/artifacts'; | ||||
| import { constants } from '../util/constants'; | ||||
| import { MultiSigWrapper } from '../util/multi_sig_wrapper'; | ||||
| import { ContractName, SubmissionContractEventArgs } from '../util/types'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { deployer } from './utils/deployer'; | ||||
|  | ||||
| const MULTI_SIG_ABI = artifacts.MultiSigWalletWithTimeLockArtifact.networks[constants.TESTRPC_NETWORK_ID].abi; | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
|  | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID }); | ||||
| const abiDecoder = new AbiDecoder([MULTI_SIG_ABI]); | ||||
|  | ||||
| describe('MultiSigWalletWithTimeLock', () => { | ||||
|     let owners: string[]; | ||||
|     before(async () => { | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         owners = [accounts[0], accounts[1]]; | ||||
|     }); | ||||
|     const SIGNATURES_REQUIRED = 2; | ||||
|     const SECONDS_TIME_LOCKED = 10000; | ||||
|  | ||||
|     let multiSig: Web3.ContractInstance; | ||||
|     let multiSigWrapper: MultiSigWrapper; | ||||
|     let txId: number; | ||||
|     let initialSecondsTimeLocked: number; | ||||
|     let rpc: RPC; | ||||
|  | ||||
|     before(async () => { | ||||
|         rpc = new RPC(); | ||||
|     }); | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|  | ||||
|     describe('changeTimeLock', () => { | ||||
|         describe('initially non-time-locked', async () => { | ||||
|             before('deploy a walet', async () => { | ||||
|                 multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [ | ||||
|                     owners, | ||||
|                     SIGNATURES_REQUIRED, | ||||
|                     0, | ||||
|                 ]); | ||||
|                 multiSigWrapper = new MultiSigWrapper(multiSig); | ||||
|  | ||||
|                 const secondsTimeLocked = await multiSig.secondsTimeLocked(); | ||||
|                 initialSecondsTimeLocked = secondsTimeLocked.toNumber(); | ||||
|             }); | ||||
|             it('should throw when not called by wallet', async () => { | ||||
|                 return expect(multiSig.changeTimeLock(SECONDS_TIME_LOCKED, { from: owners[0] })).to.be.rejectedWith( | ||||
|                     constants.REVERT, | ||||
|                 ); | ||||
|             }); | ||||
|  | ||||
|             it('should throw without enough confirmations', async () => { | ||||
|                 const destination = multiSig.address; | ||||
|                 const from = owners[0]; | ||||
|                 const dataParams = { | ||||
|                     name: 'changeTimeLock', | ||||
|                     abi: MULTI_SIG_ABI, | ||||
|                     args: [SECONDS_TIME_LOCKED], | ||||
|                 }; | ||||
|                 const txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); | ||||
|                 const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|                 const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< | ||||
|                     SubmissionContractEventArgs | ||||
|                 >; | ||||
|  | ||||
|                 txId = log.args.transactionId.toNumber(); | ||||
|                 return expect(multiSig.executeTransaction(txId, { from: owners[0] })).to.be.rejectedWith( | ||||
|                     constants.REVERT, | ||||
|                 ); | ||||
|             }); | ||||
|  | ||||
|             it('should set confirmation time with enough confirmations', async () => { | ||||
|                 const destination = multiSig.address; | ||||
|                 const from = owners[0]; | ||||
|                 const dataParams = { | ||||
|                     name: 'changeTimeLock', | ||||
|                     abi: MULTI_SIG_ABI, | ||||
|                     args: [SECONDS_TIME_LOCKED], | ||||
|                 }; | ||||
|                 let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); | ||||
|                 const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|                 const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< | ||||
|                     SubmissionContractEventArgs | ||||
|                 >; | ||||
|  | ||||
|                 txId = log.args.transactionId.toNumber(); | ||||
|                 txHash = await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|                 const res = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|                 expect(res.logs).to.have.length(2); | ||||
|  | ||||
|                 const blockNum = await web3Wrapper.getBlockNumberAsync(); | ||||
|                 const blockInfo = await web3Wrapper.getBlockAsync(blockNum); | ||||
|                 const timestamp = new BigNumber(blockInfo.timestamp); | ||||
|                 const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.call(txId)); | ||||
|  | ||||
|                 expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum); | ||||
|             }); | ||||
|  | ||||
|             it('should be executable with enough confirmations and secondsTimeLocked of 0', async () => { | ||||
|                 const destination = multiSig.address; | ||||
|                 const from = owners[0]; | ||||
|                 const dataParams = { | ||||
|                     name: 'changeTimeLock', | ||||
|                     abi: MULTI_SIG_ABI, | ||||
|                     args: [SECONDS_TIME_LOCKED], | ||||
|                 }; | ||||
|                 let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); | ||||
|                 const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|                 const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< | ||||
|                     SubmissionContractEventArgs | ||||
|                 >; | ||||
|  | ||||
|                 txId = log.args.transactionId.toNumber(); | ||||
|                 txHash = await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|  | ||||
|                 expect(initialSecondsTimeLocked).to.be.equal(0); | ||||
|  | ||||
|                 txHash = await multiSig.executeTransaction(txId, { from: owners[0] }); | ||||
|                 const res = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|                 expect(res.logs).to.have.length(2); | ||||
|  | ||||
|                 const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call()); | ||||
|                 expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED); | ||||
|             }); | ||||
|         }); | ||||
|         describe('initially time-locked', async () => { | ||||
|             before('deploy a walet', async () => { | ||||
|                 multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [ | ||||
|                     owners, | ||||
|                     SIGNATURES_REQUIRED, | ||||
|                     SECONDS_TIME_LOCKED, | ||||
|                 ]); | ||||
|                 multiSigWrapper = new MultiSigWrapper(multiSig); | ||||
|  | ||||
|                 const secondsTimeLocked = await multiSig.secondsTimeLocked(); | ||||
|                 initialSecondsTimeLocked = secondsTimeLocked.toNumber(); | ||||
|                 const destination = multiSig.address; | ||||
|                 const from = owners[0]; | ||||
|                 const dataParams = { | ||||
|                     name: 'changeTimeLock', | ||||
|                     abi: MULTI_SIG_ABI, | ||||
|                     args: [newSecondsTimeLocked], | ||||
|                 }; | ||||
|                 let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); | ||||
|                 const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|                 const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< | ||||
|                     SubmissionContractEventArgs | ||||
|                 >; | ||||
|                 txId = log.args.transactionId.toNumber(); | ||||
|                 txHash = await multiSig.confirmTransaction(txId, { | ||||
|                     from: owners[1], | ||||
|                 }); | ||||
|                 const confRes = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|                 expect(confRes.logs).to.have.length(2); | ||||
|             }); | ||||
|             const newSecondsTimeLocked = 0; | ||||
|             it('should throw if it has enough confirmations but is not past the time lock', async () => { | ||||
|                 return expect(multiSig.executeTransaction(txId, { from: owners[0] })).to.be.rejectedWith( | ||||
|                     constants.REVERT, | ||||
|                 ); | ||||
|             }); | ||||
|  | ||||
|             it('should execute if it has enough confirmations and is past the time lock', async () => { | ||||
|                 await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED); | ||||
|                 await multiSig.executeTransaction(txId, { from: owners[0] }); | ||||
|  | ||||
|                 const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call()); | ||||
|                 expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked); | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -0,0 +1,181 @@ | ||||
| import { LogWithDecodedArgs, ZeroEx } from '0x.js'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { AbiDecoder } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import * as Web3 from 'web3'; | ||||
|  | ||||
| import { artifacts } from '../util/artifacts'; | ||||
| import { constants } from '../util/constants'; | ||||
| import { crypto } from '../util/crypto'; | ||||
| import { MultiSigWrapper } from '../util/multi_sig_wrapper'; | ||||
| import { ContractName, SubmissionContractEventArgs, TransactionDataParams } from '../util/types'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { deployer } from './utils/deployer'; | ||||
| const PROXY_ABI = artifacts.TokenTransferProxyArtifact.networks[constants.TESTRPC_NETWORK_ID].abi; | ||||
| const MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_AUTHORIZED_ADDRESS_ABI = | ||||
|     artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact.networks[constants.TESTRPC_NETWORK_ID] | ||||
|         .abi; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| const abiDecoder = new AbiDecoder([MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_AUTHORIZED_ADDRESS_ABI]); | ||||
|  | ||||
| describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => { | ||||
|     const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID }); | ||||
|     let owners: string[]; | ||||
|     const requiredApprovals = 2; | ||||
|     const SECONDS_TIME_LOCKED = 1000000; | ||||
|  | ||||
|     // initialize fake addresses | ||||
|     let authorizedAddress: string; | ||||
|     let unauthorizedAddress: string; | ||||
|  | ||||
|     let tokenTransferProxy: Web3.ContractInstance; | ||||
|     let multiSig: Web3.ContractInstance; | ||||
|     let multiSigWrapper: MultiSigWrapper; | ||||
|  | ||||
|     let validDestination: string; | ||||
|     before(async () => { | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         owners = [accounts[0], accounts[1]]; | ||||
|         [authorizedAddress, unauthorizedAddress] = accounts; | ||||
|         const initialOwner = accounts[0]; | ||||
|         tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); | ||||
|         await tokenTransferProxy.addAuthorizedAddress(authorizedAddress, { | ||||
|             from: initialOwner, | ||||
|         }); | ||||
|         multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress, [ | ||||
|             owners, | ||||
|             requiredApprovals, | ||||
|             SECONDS_TIME_LOCKED, | ||||
|             tokenTransferProxy.address, | ||||
|         ]); | ||||
|         await tokenTransferProxy.transferOwnership(multiSig.address, { | ||||
|             from: initialOwner, | ||||
|         }); | ||||
|         multiSigWrapper = new MultiSigWrapper(multiSig); | ||||
|         validDestination = tokenTransferProxy.address; | ||||
|     }); | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|  | ||||
|     describe('isFunctionRemoveAuthorizedAddress', () => { | ||||
|         it('should throw if data is not for removeAuthorizedAddress', async () => { | ||||
|             const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]); | ||||
|             return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data)).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
|  | ||||
|         it('should return true if data is for removeAuthorizedAddress', async () => { | ||||
|             const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]); | ||||
|             const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.call(data); | ||||
|             expect(isFunctionRemoveAuthorizedAddress).to.be.true(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('executeRemoveAuthorizedAddress', () => { | ||||
|         it('should throw without the required confirmations', async () => { | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'removeAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [authorizedAddress], | ||||
|             }; | ||||
|             const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); | ||||
|             const res = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|             const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; | ||||
|             const txId = log.args.transactionId.toString(); | ||||
|  | ||||
|             return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith( | ||||
|                 constants.REVERT, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should throw if tx destination is not the tokenTransferProxy', async () => { | ||||
|             const invalidTokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); | ||||
|             const invalidDestination = invalidTokenTransferProxy.address; | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'removeAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [authorizedAddress], | ||||
|             }; | ||||
|             const txHash = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams); | ||||
|             const res = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|             const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; | ||||
|             const txId = log.args.transactionId.toString(); | ||||
|             await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             const isConfirmed = await multiSig.isConfirmed.call(txId); | ||||
|             expect(isConfirmed).to.be.true(); | ||||
|  | ||||
|             return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith( | ||||
|                 constants.REVERT, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should throw if tx data is not for removeAuthorizedAddress', async () => { | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'addAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [unauthorizedAddress], | ||||
|             }; | ||||
|             const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); | ||||
|             const res = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|             const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; | ||||
|             const txId = log.args.transactionId.toString(); | ||||
|             await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             const isConfirmed = await multiSig.isConfirmed.call(txId); | ||||
|             expect(isConfirmed).to.be.true(); | ||||
|  | ||||
|             return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith( | ||||
|                 constants.REVERT, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => { | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'removeAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [authorizedAddress], | ||||
|             }; | ||||
|             const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); | ||||
|             const res = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|             const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; | ||||
|             const txId = log.args.transactionId.toString(); | ||||
|             await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             const isConfirmed = await multiSig.isConfirmed.call(txId); | ||||
|             expect(isConfirmed).to.be.true(); | ||||
|             await multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] }); | ||||
|             const isAuthorized = await tokenTransferProxy.authorized.call(authorizedAddress); | ||||
|             expect(isAuthorized).to.be.false(); | ||||
|         }); | ||||
|  | ||||
|         it('should throw if already executed', async () => { | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'removeAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [authorizedAddress], | ||||
|             }; | ||||
|             const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); | ||||
|             const res = await zeroEx.awaitTransactionMinedAsync(txHash); | ||||
|             const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; | ||||
|             const txId = log.args.transactionId.toString(); | ||||
|             await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             const isConfirmed = await multiSig.isConfirmed(txId); | ||||
|             expect(isConfirmed).to.be.true(); | ||||
|             await multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] }); | ||||
|             const tx = await multiSig.transactions(txId); | ||||
|             const isExecuted = tx[3]; | ||||
|             expect(isExecuted).to.be.true(); | ||||
|             return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith( | ||||
|                 constants.REVERT, | ||||
|             ); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,22 +1,42 @@ | ||||
| import { ZeroEx } from '0x.js'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import ethUtil = require('ethereumjs-util'); | ||||
| import * as _ from 'lodash'; | ||||
| import * as Web3 from 'web3'; | ||||
| 
 | ||||
| import { Artifacts } from '../../util/artifacts'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { TokenRegWrapper } from '../../util/token_registry_wrapper'; | ||||
| import { ContractInstance } from '../../util/types'; | ||||
| import { constants } from '../util/constants'; | ||||
| import { TokenRegWrapper } from '../util/token_registry_wrapper'; | ||||
| import { ContractName } from '../util/types'; | ||||
| 
 | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { deployer } from './utils/deployer'; | ||||
| 
 | ||||
| const { TokenRegistry } = new Artifacts(artifacts); | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| 
 | ||||
| contract('TokenRegistry', (accounts: string[]) => { | ||||
|     const owner = accounts[0]; | ||||
|     const notOwner = accounts[1]; | ||||
| describe('TokenRegistry', () => { | ||||
|     let owner: string; | ||||
|     let notOwner: string; | ||||
|     let tokenReg: Web3.ContractInstance; | ||||
|     let tokenRegWrapper: TokenRegWrapper; | ||||
|     before(async () => { | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         owner = accounts[0]; | ||||
|         notOwner = accounts[1]; | ||||
|         tokenReg = await deployer.deployAsync(ContractName.TokenRegistry); | ||||
|         tokenRegWrapper = new TokenRegWrapper(tokenReg); | ||||
|     }); | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
| 
 | ||||
|     const tokenAddress1 = `0x${ethUtil.setLength(ethUtil.toBuffer('0x1'), 20, false).toString('hex')}`; | ||||
|     const tokenAddress2 = `0x${ethUtil.setLength(ethUtil.toBuffer('0x2'), 20, false).toString('hex')}`; | ||||
| @@ -48,14 +68,6 @@ contract('TokenRegistry', (accounts: string[]) => { | ||||
|         swarmHash: constants.NULL_BYTES, | ||||
|     }; | ||||
| 
 | ||||
|     let tokenReg: ContractInstance; | ||||
|     let tokenRegWrapper: TokenRegWrapper; | ||||
| 
 | ||||
|     beforeEach(async () => { | ||||
|         tokenReg = await TokenRegistry.new(); | ||||
|         tokenRegWrapper = new TokenRegWrapper(tokenReg); | ||||
|     }); | ||||
| 
 | ||||
|     describe('addToken', () => { | ||||
|         it('should throw when not called by owner', async () => { | ||||
|             return expect(tokenRegWrapper.addTokenAsync(token1, notOwner)).to.be.rejectedWith(constants.REVERT); | ||||
| @@ -125,10 +137,9 @@ contract('TokenRegistry', (accounts: string[]) => { | ||||
|             }); | ||||
| 
 | ||||
|             it('should change the token name when called by owner', async () => { | ||||
|                 const res = await tokenReg.setTokenName(token1.address, token2.name, { | ||||
|                 await tokenReg.setTokenName(token1.address, token2.name, { | ||||
|                     from: owner, | ||||
|                 }); | ||||
|                 expect(res.logs).to.have.length(1); | ||||
|                 const [newData, oldData] = await Promise.all([ | ||||
|                     tokenRegWrapper.getTokenByNameAsync(token2.name), | ||||
|                     tokenRegWrapper.getTokenByNameAsync(token1.name), | ||||
| @@ -165,8 +176,7 @@ contract('TokenRegistry', (accounts: string[]) => { | ||||
|             }); | ||||
| 
 | ||||
|             it('should change the token symbol when called by owner', async () => { | ||||
|                 const res = await tokenReg.setTokenSymbol(token1.address, token2.symbol, { from: owner }); | ||||
|                 expect(res.logs).to.have.length(1); | ||||
|                 await tokenReg.setTokenSymbol(token1.address, token2.symbol, { from: owner }); | ||||
|                 const [newData, oldData] = await Promise.all([ | ||||
|                     tokenRegWrapper.getTokenBySymbolAsync(token2.symbol), | ||||
|                     tokenRegWrapper.getTokenBySymbolAsync(token1.symbol), | ||||
| @@ -207,10 +217,9 @@ contract('TokenRegistry', (accounts: string[]) => { | ||||
| 
 | ||||
|             it('should remove token metadata when called by owner', async () => { | ||||
|                 const index = 0; | ||||
|                 const res = await tokenReg.removeToken(token1.address, index, { | ||||
|                 await tokenReg.removeToken(token1.address, index, { | ||||
|                     from: owner, | ||||
|                 }); | ||||
|                 expect(res.logs).to.have.length(1); | ||||
|                 const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address); | ||||
|                 expect(tokenData).to.be.deep.equal(nullToken); | ||||
|             }); | ||||
| @@ -1,44 +1,50 @@ | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import * as Web3 from 'web3'; | ||||
| 
 | ||||
| import { constants } from '../../../util/constants'; | ||||
| import { ContractInstance } from '../../../util/types'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { ContractName } from '../../util/types'; | ||||
| import { chaiSetup } from '../utils/chai_setup'; | ||||
| import { deployer } from '../utils/deployer'; | ||||
| 
 | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const TokenTransferProxy = artifacts.require('./db/TokenTransferProxy.sol'); | ||||
| 
 | ||||
| contract('TokenTransferProxy', (accounts: string[]) => { | ||||
|     const owner = accounts[0]; | ||||
|     const notOwner = accounts[1]; | ||||
| 
 | ||||
|     let tokenTransferProxy: ContractInstance; | ||||
|     let authorized: string; | ||||
|     let notAuthorized = owner; | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| 
 | ||||
| describe('TokenTransferProxy', () => { | ||||
|     let owner: string; | ||||
|     let notOwner: string; | ||||
|     let address: string; | ||||
|     let tokenTransferProxy: Web3.ContractInstance; | ||||
|     before(async () => { | ||||
|         tokenTransferProxy = await TokenTransferProxy.deployed(); | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         owner = address = accounts[0]; | ||||
|         notOwner = accounts[1]; | ||||
|         tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); | ||||
|     }); | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
| 
 | ||||
|     describe('addAuthorizedAddress', () => { | ||||
|         it('should throw if not called by owner', async () => { | ||||
|             return expect(tokenTransferProxy.addAuthorizedAddress(notOwner, { from: notOwner })).to.be.rejectedWith( | ||||
|                 constants.REVERT, | ||||
|             ); | ||||
|         }); | ||||
| 
 | ||||
|         it('should allow owner to add an authorized address', async () => { | ||||
|             await tokenTransferProxy.addAuthorizedAddress(notAuthorized, { | ||||
|                 from: owner, | ||||
|             }); | ||||
|             authorized = notAuthorized; | ||||
|             notAuthorized = null; | ||||
|             const isAuthorized = await tokenTransferProxy.authorized.call(authorized); | ||||
|             await tokenTransferProxy.addAuthorizedAddress(address, { from: owner }); | ||||
|             const isAuthorized = await tokenTransferProxy.authorized(address); | ||||
|             expect(isAuthorized).to.be.true(); | ||||
|         }); | ||||
| 
 | ||||
|         it('should throw if owner attempts to authorize a duplicate address', async () => { | ||||
|             return expect(tokenTransferProxy.addAuthorizedAddress(authorized, { from: owner })).to.be.rejectedWith( | ||||
|             await tokenTransferProxy.addAuthorizedAddress(address, { from: owner }); | ||||
|             return expect(tokenTransferProxy.addAuthorizedAddress(address, { from: owner })).to.be.rejectedWith( | ||||
|                 constants.REVERT, | ||||
|             ); | ||||
|         }); | ||||
| @@ -46,27 +52,26 @@ contract('TokenTransferProxy', (accounts: string[]) => { | ||||
| 
 | ||||
|     describe('removeAuthorizedAddress', () => { | ||||
|         it('should throw if not called by owner', async () => { | ||||
|             await tokenTransferProxy.addAuthorizedAddress(address, { from: owner }); | ||||
|             return expect( | ||||
|                 tokenTransferProxy.removeAuthorizedAddress(authorized, { | ||||
|                 tokenTransferProxy.removeAuthorizedAddress(address, { | ||||
|                     from: notOwner, | ||||
|                 }), | ||||
|             ).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
| 
 | ||||
|         it('should allow owner to remove an authorized address', async () => { | ||||
|             await tokenTransferProxy.removeAuthorizedAddress(authorized, { | ||||
|             await tokenTransferProxy.addAuthorizedAddress(address, { from: owner }); | ||||
|             await tokenTransferProxy.removeAuthorizedAddress(address, { | ||||
|                 from: owner, | ||||
|             }); | ||||
|             notAuthorized = authorized; | ||||
|             authorized = null; | ||||
| 
 | ||||
|             const isAuthorized = await tokenTransferProxy.authorized.call(notAuthorized); | ||||
|             const isAuthorized = await tokenTransferProxy.authorized(address); | ||||
|             expect(isAuthorized).to.be.false(); | ||||
|         }); | ||||
| 
 | ||||
|         it('should throw if owner attempts to remove an address that is not authorized', async () => { | ||||
|             return expect( | ||||
|                 tokenTransferProxy.removeAuthorizedAddress(notAuthorized, { | ||||
|                 tokenTransferProxy.removeAuthorizedAddress(address, { | ||||
|                     from: owner, | ||||
|                 }), | ||||
|             ).to.be.rejectedWith(constants.REVERT); | ||||
| @@ -76,24 +81,19 @@ contract('TokenTransferProxy', (accounts: string[]) => { | ||||
|     describe('getAuthorizedAddresses', () => { | ||||
|         it('should return all authorized addresses', async () => { | ||||
|             const initial = await tokenTransferProxy.getAuthorizedAddresses(); | ||||
|             expect(initial).to.have.length(1); | ||||
|             await tokenTransferProxy.addAuthorizedAddress(notAuthorized, { | ||||
|             expect(initial).to.have.length(0); | ||||
|             await tokenTransferProxy.addAuthorizedAddress(address, { | ||||
|                 from: owner, | ||||
|             }); | ||||
| 
 | ||||
|             authorized = notAuthorized; | ||||
|             notAuthorized = null; | ||||
|             const afterAdd = await tokenTransferProxy.getAuthorizedAddresses(); | ||||
|             expect(afterAdd).to.have.length(2); | ||||
|             expect(afterAdd).to.include(authorized); | ||||
|             expect(afterAdd).to.have.length(1); | ||||
|             expect(afterAdd).to.include(address); | ||||
| 
 | ||||
|             await tokenTransferProxy.removeAuthorizedAddress(authorized, { | ||||
|             await tokenTransferProxy.removeAuthorizedAddress(address, { | ||||
|                 from: owner, | ||||
|             }); | ||||
|             notAuthorized = authorized; | ||||
|             authorized = null; | ||||
|             const afterRemove = await tokenTransferProxy.getAuthorizedAddresses(); | ||||
|             expect(afterRemove).to.have.length(1); | ||||
|             expect(afterRemove).to.have.length(0); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,47 +1,55 @@ | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import * as Web3 from 'web3'; | ||||
| 
 | ||||
| import { Artifacts } from '../../../util/artifacts'; | ||||
| import { Balances } from '../../../util/balances'; | ||||
| import { constants } from '../../../util/constants'; | ||||
| import { ContractInstance } from '../../../util/types'; | ||||
| import { Balances } from '../../util/balances'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { ContractName } from '../../util/types'; | ||||
| import { chaiSetup } from '../utils/chai_setup'; | ||||
| import { deployer } from '../utils/deployer'; | ||||
| 
 | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const { TokenTransferProxy, DummyToken, TokenRegistry } = new Artifacts(artifacts); | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| 
 | ||||
| contract('TokenTransferProxy', (accounts: string[]) => { | ||||
| describe('TokenTransferProxy', () => { | ||||
|     let accounts: string[]; | ||||
|     let owner: string; | ||||
|     let notAuthorized: string; | ||||
|     const INIT_BAL = 100000000; | ||||
|     const INIT_ALLOW = 100000000; | ||||
| 
 | ||||
|     const owner = accounts[0]; | ||||
|     const notAuthorized = owner; | ||||
| 
 | ||||
|     let tokenTransferProxy: ContractInstance; | ||||
|     let tokenRegistry: ContractInstance; | ||||
|     let rep: ContractInstance; | ||||
|     let tokenTransferProxy: Web3.ContractInstance; | ||||
|     let rep: Web3.ContractInstance; | ||||
|     let dmyBalances: Balances; | ||||
| 
 | ||||
|     before(async () => { | ||||
|         [tokenTransferProxy, tokenRegistry] = await Promise.all([ | ||||
|             TokenTransferProxy.deployed(), | ||||
|             TokenRegistry.deployed(), | ||||
|         ]); | ||||
|         const repAddress = await tokenRegistry.getTokenAddressBySymbol('REP'); | ||||
|         rep = DummyToken.at(repAddress); | ||||
|         accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         owner = notAuthorized = accounts[0]; | ||||
|         tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); | ||||
|         rep = await deployer.deployAsync(ContractName.DummyToken); | ||||
| 
 | ||||
|         dmyBalances = new Balances([rep], [accounts[0], accounts[1]]); | ||||
|         await Promise.all([ | ||||
|             rep.approve(TokenTransferProxy.address, INIT_ALLOW, { | ||||
|             rep.approve(tokenTransferProxy.address, INIT_ALLOW, { | ||||
|                 from: accounts[0], | ||||
|             }), | ||||
|             rep.setBalance(accounts[0], INIT_BAL, { from: owner }), | ||||
|             rep.approve(TokenTransferProxy.address, INIT_ALLOW, { | ||||
|             rep.approve(tokenTransferProxy.address, INIT_ALLOW, { | ||||
|                 from: accounts[1], | ||||
|             }), | ||||
|             rep.setBalance(accounts[1], INIT_BAL, { from: owner }), | ||||
|         ]); | ||||
|     }); | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
| 
 | ||||
|     describe('transferFrom', () => { | ||||
|         it('should throw when called by an unauthorized address', async () => { | ||||
| @@ -1,115 +0,0 @@ | ||||
| import { RPC } from '@0xproject/dev-utils'; | ||||
| import { BigNumber, promisify } from '@0xproject/utils'; | ||||
| import * as chai from 'chai'; | ||||
| import Web3 = require('web3'); | ||||
|  | ||||
| import * as multiSigWalletJSON from '../../build/contracts/MultiSigWalletWithTimeLock.json'; | ||||
| import * as truffleConf from '../../truffle.js'; | ||||
| import { Artifacts } from '../../util/artifacts'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { MultiSigWrapper } from '../../util/multi_sig_wrapper'; | ||||
| import { ContractInstance } from '../../util/types'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
|  | ||||
| const { MultiSigWalletWithTimeLock } = new Artifacts(artifacts); | ||||
|  | ||||
| const MULTI_SIG_ABI = (multiSigWalletJSON as any).abi; | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
|  | ||||
| // In order to benefit from type-safety, we re-assign the global web3 instance injected by Truffle | ||||
| // with type `any` to a variable of type `Web3`. | ||||
| const web3: Web3 = (global as any).web3; | ||||
|  | ||||
| contract('MultiSigWalletWithTimeLock', (accounts: string[]) => { | ||||
|     const owners = [accounts[0], accounts[1]]; | ||||
|     const SECONDS_TIME_LOCKED = 10000; | ||||
|  | ||||
|     let multiSig: ContractInstance; | ||||
|     let multiSigWrapper: MultiSigWrapper; | ||||
|     let txId: number; | ||||
|     let initialSecondsTimeLocked: number; | ||||
|     let rpc: RPC; | ||||
|  | ||||
|     before(async () => { | ||||
|         multiSig = await MultiSigWalletWithTimeLock.deployed(); | ||||
|         multiSigWrapper = new MultiSigWrapper(multiSig); | ||||
|  | ||||
|         const secondsTimeLocked = await multiSig.secondsTimeLocked.call(); | ||||
|         initialSecondsTimeLocked = secondsTimeLocked.toNumber(); | ||||
|         const rpcUrl = `http://${truffleConf.networks.development.host}:${truffleConf.networks.development.port}`; | ||||
|         rpc = new RPC(rpcUrl); | ||||
|     }); | ||||
|  | ||||
|     describe('changeTimeLock', () => { | ||||
|         it('should throw when not called by wallet', async () => { | ||||
|             return expect(multiSig.changeTimeLock(SECONDS_TIME_LOCKED, { from: owners[0] })).to.be.rejectedWith( | ||||
|                 constants.REVERT, | ||||
|             ); | ||||
|         }); | ||||
|  | ||||
|         it('should throw without enough confirmations', async () => { | ||||
|             const destination = multiSig.address; | ||||
|             const from = owners[0]; | ||||
|             const dataParams = { | ||||
|                 name: 'changeTimeLock', | ||||
|                 abi: MULTI_SIG_ABI, | ||||
|                 args: [SECONDS_TIME_LOCKED], | ||||
|             }; | ||||
|             const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); | ||||
|  | ||||
|             txId = subRes.logs[0].args.transactionId.toNumber(); | ||||
|             return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
|  | ||||
|         it('should set confirmation time with enough confirmations', async () => { | ||||
|             const res = await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             expect(res.logs).to.have.length(2); | ||||
|             const blockNum = await promisify<number>(web3.eth.getBlockNumber)(); | ||||
|             const blockInfo = await promisify<Web3.BlockWithoutTransactionData>(web3.eth.getBlock)(blockNum); | ||||
|             const timestamp = new BigNumber(blockInfo.timestamp); | ||||
|             const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.call(txId)); | ||||
|  | ||||
|             expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum); | ||||
|         }); | ||||
|  | ||||
|         it('should be executable with enough confirmations and secondsTimeLocked of 0', async () => { | ||||
|             expect(initialSecondsTimeLocked).to.be.equal(0); | ||||
|  | ||||
|             const res = await multiSig.executeTransaction(txId); | ||||
|             expect(res.logs).to.have.length(2); | ||||
|  | ||||
|             const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call()); | ||||
|             expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED); | ||||
|         }); | ||||
|  | ||||
|         const newSecondsTimeLocked = 0; | ||||
|         it('should throw if it has enough confirmations but is not past the time lock', async () => { | ||||
|             const destination = multiSig.address; | ||||
|             const from = owners[0]; | ||||
|             const dataParams = { | ||||
|                 name: 'changeTimeLock', | ||||
|                 abi: MULTI_SIG_ABI, | ||||
|                 args: [newSecondsTimeLocked], | ||||
|             }; | ||||
|             const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); | ||||
|  | ||||
|             txId = subRes.logs[0].args.transactionId.toNumber(); | ||||
|             const confRes = await multiSig.confirmTransaction(txId, { | ||||
|                 from: owners[1], | ||||
|             }); | ||||
|             expect(confRes.logs).to.have.length(2); | ||||
|  | ||||
|             return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
|  | ||||
|         it('should execute if it has enough confirmations and is past the time lock', async () => { | ||||
|             await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED); | ||||
|             await multiSig.executeTransaction(txId); | ||||
|  | ||||
|             const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call()); | ||||
|             expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,150 +0,0 @@ | ||||
| import * as chai from 'chai'; | ||||
|  | ||||
| import * as tokenTransferProxyJSON from '../../build/contracts/TokenTransferProxy.json'; | ||||
| import { Artifacts } from '../../util/artifacts'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { crypto } from '../../util/crypto'; | ||||
| import { MultiSigWrapper } from '../../util/multi_sig_wrapper'; | ||||
| import { ContractInstance, TransactionDataParams } from '../../util/types'; | ||||
|  | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| const { TokenTransferProxy, MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress } = new Artifacts(artifacts); | ||||
| const PROXY_ABI = (tokenTransferProxyJSON as any).abi; | ||||
|  | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
|  | ||||
| contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: string[]) => { | ||||
|     const owners = [accounts[0], accounts[1]]; | ||||
|     const requiredApprovals = 2; | ||||
|     const SECONDS_TIME_LOCKED = 1000000; | ||||
|  | ||||
|     // initialize fake addresses | ||||
|     const authorizedAddress = `0x${crypto | ||||
|         .solSHA3([accounts[0]]) | ||||
|         .slice(0, 20) | ||||
|         .toString('hex')}`; | ||||
|     const unauthorizedAddress = `0x${crypto | ||||
|         .solSHA3([accounts[1]]) | ||||
|         .slice(0, 20) | ||||
|         .toString('hex')}`; | ||||
|  | ||||
|     let tokenTransferProxy: ContractInstance; | ||||
|     let multiSig: ContractInstance; | ||||
|     let multiSigWrapper: MultiSigWrapper; | ||||
|  | ||||
|     let validDestination: string; | ||||
|  | ||||
|     beforeEach(async () => { | ||||
|         const initialOwner = accounts[0]; | ||||
|         tokenTransferProxy = await TokenTransferProxy.new({ from: initialOwner }); | ||||
|         await tokenTransferProxy.addAuthorizedAddress(authorizedAddress, { | ||||
|             from: initialOwner, | ||||
|         }); | ||||
|         multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.new( | ||||
|             owners, | ||||
|             requiredApprovals, | ||||
|             SECONDS_TIME_LOCKED, | ||||
|             tokenTransferProxy.address, | ||||
|         ); | ||||
|         await tokenTransferProxy.transferOwnership(multiSig.address, { | ||||
|             from: initialOwner, | ||||
|         }); | ||||
|         multiSigWrapper = new MultiSigWrapper(multiSig); | ||||
|         validDestination = tokenTransferProxy.address; | ||||
|     }); | ||||
|  | ||||
|     describe('isFunctionRemoveAuthorizedAddress', () => { | ||||
|         it('should throw if data is not for removeAuthorizedAddress', async () => { | ||||
|             const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]); | ||||
|             return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data)).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
|  | ||||
|         it('should return true if data is for removeAuthorizedAddress', async () => { | ||||
|             const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]); | ||||
|             const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.call(data); | ||||
|             expect(isFunctionRemoveAuthorizedAddress).to.be.true(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe('executeRemoveAuthorizedAddress', () => { | ||||
|         it('should throw without the required confirmations', async () => { | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'removeAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [authorizedAddress], | ||||
|             }; | ||||
|             const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); | ||||
|             const txId = res.logs[0].args.transactionId.toString(); | ||||
|  | ||||
|             return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
|  | ||||
|         it('should throw if tx destination is not the tokenTransferProxy', async () => { | ||||
|             const invalidTokenTransferProxy = await TokenTransferProxy.new(); | ||||
|             const invalidDestination = invalidTokenTransferProxy.address; | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'removeAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [authorizedAddress], | ||||
|             }; | ||||
|             const res = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams); | ||||
|             const txId = res.logs[0].args.transactionId.toString(); | ||||
|             await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             const isConfirmed = await multiSig.isConfirmed.call(txId); | ||||
|             expect(isConfirmed).to.be.true(); | ||||
|  | ||||
|             return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
|  | ||||
|         it('should throw if tx data is not for removeAuthorizedAddress', async () => { | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'addAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [unauthorizedAddress], | ||||
|             }; | ||||
|             const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); | ||||
|             const txId = res.logs[0].args.transactionId.toString(); | ||||
|             await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             const isConfirmed = await multiSig.isConfirmed.call(txId); | ||||
|             expect(isConfirmed).to.be.true(); | ||||
|  | ||||
|             return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
|  | ||||
|         it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => { | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'removeAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [authorizedAddress], | ||||
|             }; | ||||
|             const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); | ||||
|             const txId = res.logs[0].args.transactionId.toString(); | ||||
|             await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             const isConfirmed = await multiSig.isConfirmed.call(txId); | ||||
|             expect(isConfirmed).to.be.true(); | ||||
|             await multiSig.executeRemoveAuthorizedAddress(txId); | ||||
|  | ||||
|             const isAuthorized = await tokenTransferProxy.authorized.call(authorizedAddress); | ||||
|             expect(isAuthorized).to.be.false(); | ||||
|         }); | ||||
|  | ||||
|         it('should throw if already executed', async () => { | ||||
|             const dataParams: TransactionDataParams = { | ||||
|                 name: 'removeAuthorizedAddress', | ||||
|                 abi: PROXY_ABI, | ||||
|                 args: [authorizedAddress], | ||||
|             }; | ||||
|             const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); | ||||
|             const txId = res.logs[0].args.transactionId.toString(); | ||||
|             await multiSig.confirmTransaction(txId, { from: owners[1] }); | ||||
|             const isConfirmed = await multiSig.isConfirmed.call(txId); | ||||
|             expect(isConfirmed).to.be.true(); | ||||
|             await multiSig.executeRemoveAuthorizedAddress(txId); | ||||
|             const tx = await multiSig.transactions.call(txId); | ||||
|             const isExecuted = tx[3]; | ||||
|             expect(isExecuted).to.be.true(); | ||||
|             return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| @@ -1,37 +1,48 @@ | ||||
| import { ZeroEx } from '0x.js'; | ||||
| import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; | ||||
| import { BigNumber } from '@0xproject/utils'; | ||||
| import { Web3Wrapper } from '@0xproject/web3-wrapper'; | ||||
| import * as chai from 'chai'; | ||||
| import * as Web3 from 'web3'; | ||||
| 
 | ||||
| import { Artifacts } from '../../util/artifacts'; | ||||
| import { constants } from '../../util/constants'; | ||||
| import { ContractInstance } from '../../util/types'; | ||||
| import { constants } from '../util/constants'; | ||||
| import { ContractName } from '../util/types'; | ||||
| 
 | ||||
| import { chaiSetup } from './utils/chai_setup'; | ||||
| import { deployer } from './utils/deployer'; | ||||
| 
 | ||||
| const { DummyToken } = new Artifacts(artifacts); | ||||
| const web3: Web3 = (global as any).web3; | ||||
| const web3 = web3Factory.create(); | ||||
| const web3Wrapper = new Web3Wrapper(web3.currentProvider); | ||||
| chaiSetup.configure(); | ||||
| const expect = chai.expect; | ||||
| const blockchainLifecycle = new BlockchainLifecycle(); | ||||
| 
 | ||||
| contract('UnlimitedAllowanceToken', (accounts: string[]) => { | ||||
| describe('UnlimitedAllowanceToken', () => { | ||||
|     let owner: string; | ||||
|     let spender: string; | ||||
|     const config = { | ||||
|         networkId: constants.TESTRPC_NETWORK_ID, | ||||
|     }; | ||||
|     const zeroEx = new ZeroEx(web3.currentProvider, config); | ||||
|     const owner = accounts[0]; | ||||
|     const spender = accounts[1]; | ||||
| 
 | ||||
|     const MAX_MINT_VALUE = new BigNumber(100000000000000000000); | ||||
|     let tokenAddress: string; | ||||
|     let token: ContractInstance; | ||||
|     let token: Web3.ContractInstance; | ||||
| 
 | ||||
|     beforeEach(async () => { | ||||
|         token = await DummyToken.new({ from: owner }); | ||||
|     before(async () => { | ||||
|         const accounts = await web3Wrapper.getAvailableAddressesAsync(); | ||||
|         owner = accounts[0]; | ||||
|         spender = accounts[1]; | ||||
|         token = await deployer.deployAsync(ContractName.DummyToken); | ||||
|         await token.mint(MAX_MINT_VALUE, { from: owner }); | ||||
|         tokenAddress = token.address; | ||||
|     }); | ||||
| 
 | ||||
|     beforeEach(async () => { | ||||
|         await blockchainLifecycle.startAsync(); | ||||
|     }); | ||||
|     afterEach(async () => { | ||||
|         await blockchainLifecycle.revertAsync(); | ||||
|     }); | ||||
|     describe('transfer', () => { | ||||
|         it('should transfer balance from sender to receiver', async () => { | ||||
|             const receiver = spender; | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user