Compare commits

..

792 Commits

Author SHA1 Message Date
Fabio Berger
a9b320e636 Add back timestamp 2018-07-09 15:49:24 +02:00
Leonid Logvinov
ecdc0636d8 Merge pull request #841 from 0xProject/feature/v2-contract-wrappers-validation
Feature/v2 contract wrappers validation
2018-07-09 12:21:32 +02:00
Leonid Logvinov
ea12e34809 Ignore coverage of generated files 2018-07-09 12:07:42 +02:00
Leonid Logvinov
9fb7865292 Dedupe AssetProxyId types 2018-07-09 11:43:00 +02:00
Leonid Logvinov
12f30c78ff Fix a typo 2018-07-09 11:29:42 +02:00
Leonid Logvinov
e3bed5cc71 Default shouldValidate to true 2018-07-09 11:29:09 +02:00
Leonid Logvinov
0f8f5ca5ff Add basic validation for exchange contract wrapper 2018-07-09 11:13:21 +02:00
Leonid Logvinov
0fe0433b9a Add type for AssetProxyId 2018-07-09 11:13:21 +02:00
Leonid Logvinov
ab1e38701d Add revert reason parsing to error handling decorator 2018-07-09 11:13:21 +02:00
Leonid Logvinov
258fe8ea50 Render callAsync in templates even if it returns nothing 2018-07-09 11:13:21 +02:00
Leonid Logvinov
813824868e Return AssetProxyId instead of string from proxy.getProxyIdAsync() 2018-07-09 11:13:21 +02:00
Fabio Berger
028184947f Merge pull request #833 from feuGeneA/issue-823
document how to check test coverage on a fork
2018-07-09 10:10:31 +02:00
Amir Bandeali
14c96e0b97 Merge pull request #839 from 0xProject/refactor/contracts/forwarder-interfaces
Refactor forwarder file structure
2018-07-08 20:29:31 -07:00
Brandon Millman
ef03d1ae13 Give environment enums string values 2018-07-08 01:37:22 -07:00
Amir Bandeali
f1613d36ac Move functions out of Forwarder.sol 2018-07-07 23:23:22 -07:00
Amir Bandeali
8314bbbbac Add interfaces and mixins 2018-07-07 22:57:09 -07:00
Amir Bandeali
462f1f00d8 Combine mixins 2018-07-07 22:11:36 -07:00
Amir Bandeali
1c80bba4dd Use interfaces instead of full contracts 2018-07-07 22:11:36 -07:00
fragosti
d22cff0976 Shim shouldShowPortalV2 to always return true 2018-07-06 16:08:35 -07:00
Francesco Agosti
269b56b907 Merge pull request #838 from 0xProject/feature/website/portal-final-touches
Some final polish touches for portal!
2018-07-06 15:38:51 -07:00
fragosti
60ebfcf36d Fix lint errors 2018-07-06 15:21:50 -07:00
fragosti
824c331ea0 Make unlock metamask step look more like mock 2018-07-06 15:17:23 -07:00
fragosti
b9e51d2fad Add updated asset for unlock metamask portal onboarding step 2018-07-06 14:23:00 -07:00
fragosti
9669a4d121 Create Balance component and make token symbols smaller than token amounts 2018-07-06 14:21:30 -07:00
Amir Bandeali
e929fb4337 Merge pull request #826 from 0xProject/refactor/contracts/todos
Address TODOs and small fixes
2018-07-06 13:41:06 -07:00
Brandon Millman
80da9cd31f Merge pull request #835 from 0xProject/feature/website/token-updates
Update token registry icons and asset picker flows
2018-07-06 13:24:55 -07:00
Amir Bandeali
5ed7a1baba Add lint-contracts to default lint command 2018-07-06 13:23:09 -07:00
Amir Bandeali
07c111d1f5 Remove TODOs that won't be addressed 2018-07-06 13:23:09 -07:00
Amir Bandeali
a2024da955 Remove AbiV2 where unused 2018-07-06 13:23:05 -07:00
fragosti
7418926ebb Give Wallet a min height 2018-07-06 13:17:28 -07:00
Brandon Millman
4cc33d270e Merge pull request #828 from 0xProject/feature/website/portal-improvements
Fix some portal bugs, and poll for best gas price
2018-07-06 13:05:27 -07:00
Brandon Millman
f767f5c12c Hard code exchange abi 2018-07-06 13:03:35 -07:00
Amir Bandeali
0ea3b10efd Only reset currentContextAddress if it was previously updated 2018-07-06 11:53:59 -07:00
Amir Bandeali
d634775d40 Change uint => uint256 2018-07-06 11:53:59 -07:00
Francesco Agosti
c4ab5bc653 Merge pull request #829 from 0xProject/bug/web3-wrapper/fix-invalid-transaction-format
Fix invalid transaction format errors when going through `SingerSubprovider`
2018-07-06 11:46:03 -07:00
Amir Bandeali
1d3bdfc374 Merge pull request #834 from 0xProject/fix/contracts/linter
Apply linter to nested contracts
2018-07-06 11:45:06 -07:00
fragosti
72fb1ee36f Fix linting issues 2018-07-06 11:30:01 -07:00
fragosti
afbc4989d5 address CR feedback 2018-07-06 11:23:41 -07:00
Amir Bandeali
d2e422cd5e Apply new linter rules 2018-07-06 10:58:28 -07:00
Brandon Millman
49c7365d93 Update token registry icons and asset picker flows 2018-07-06 10:51:46 -07:00
fragosti
c753e24f0a Export marshaller and use it to unmarshal tx dataa 2018-07-06 10:35:13 -07:00
fragosti
acfbba5476 Revert moving formatUtils into utils 2018-07-06 10:23:24 -07:00
Amir Bandeali
e796734659 Update linter config 2018-07-06 09:51:09 -07:00
F. Eugene Aumson
f172908bde document how to check test coverage on a fork 2018-07-06 10:26:24 -04:00
Leonid Logvinov
16dc4e9f66 Instantiate BlockAndLogStreamer with generic type parameters 2018-07-06 13:36:23 +02:00
Fabio Berger
8eefc89d55 Merge pull request #831 from 0xProject/fix-readme-intros
Update Package Descriptions
2018-07-06 13:10:00 +02:00
Fabio Berger
20d349cea7 Merge pull request #825 from 0xProject/fix-order-watcher
OrderWatcher Fixes
2018-07-06 13:06:12 +02:00
Fabio Berger
22f408f713 Update readme and doc intros 2018-07-06 13:05:13 +02:00
Fabio Berger
1e0fa776c1 Add isVerbose flag and log blockstream recoverable errors rather then bubbling them up 2018-07-06 12:34:03 +02:00
Leonid Logvinov
faf5c84082 Fix imports 2018-07-06 11:21:49 +02:00
Leonid Logvinov
b21f6e4d86 Merge pull request #822 from 0xProject/v2-contract-wrappers-WIP
V2 contract wrappers
2018-07-06 12:10:55 +03:00
Jacob Evans
bc52303402 Types: Move Forwarder Revert Reason into types package 2018-07-06 18:26:59 +10:00
Jacob Evans
2da705e81c Forwarder specify the revert reasons 2018-07-06 18:09:56 +10:00
Jacob Evans
a0601cd052 Forwarder fix linter error 2018-07-06 17:44:17 +10:00
Jacob Evans
ed2c06508b Update to new assertions 2018-07-06 17:43:15 +10:00
Jacob Evans
03b3d74748 Merge pull request #522 from 0xProject/feature/contracts/forwarder
Forwarding contract
2018-07-06 16:29:56 +10:00
Jacob Evans
0557d6a9bf Forwarding contract (squashed commits) 2018-07-06 15:30:07 +10:00
Brandon Millman
d975c0cef3 Merge pull request #827 from 0xProject/feature/website/landing-page-cta
Landing page CTA for portal
2018-07-05 22:03:13 -07:00
fragosti
188bf000b7 Add formatUtils 2018-07-05 18:59:01 -07:00
fragosti
608442b2e8 Add to changelog, rename to formatUtils and lint 2018-07-05 18:56:58 -07:00
fragosti
aefc122caf Add conversion utility file 2018-07-05 18:38:25 -07:00
fragosti
a72eae7ea8 Unmarshall txn data in SignerSubprovider before calling web3wrapper sendTransactionAsync 2018-07-05 18:32:28 -07:00
fragosti
30e3afc0fb Add unmarshallTxData to marshaller 2018-07-05 17:48:02 -07:00
fragosti
97809a03eb Make wallet height responsive 2018-07-05 17:11:50 -07:00
fragosti
f894ffc0cc Poll for gas prices and use fast instead of average for better UX 2018-07-05 15:37:35 -07:00
fragosti
127fbc6e94 Just disable closing onboarding by clicking outside for firefox 2018-07-05 15:16:46 -07:00
Brandon Millman
9f870b3d4e Change call to action link to /portal 2018-07-05 15:12:22 -07:00
Amir Bandeali
51b86742d1 Merge pull request #824 from protofire/v2-prototype-solhint
Add and apply solidity linter (V2, updated)
2018-07-05 15:09:41 -07:00
Brandon Millman
3a85b3212b Unify large and small padding in Portal 2018-07-05 14:42:22 -07:00
Brandon Millman
fd6445439e Implement landing page change in preperation for portal 2018-07-05 14:34:34 -07:00
Brandon Millman
51fa8d3e24 Merge pull request #820 from 0xProject/bug/website/top-bar-layout
Various mobile portal fixes and top bar layout refactor
2018-07-05 14:33:22 -07:00
Brandon Millman
7b8db1156d Various fixes for portal on mobile and top bar layout 2018-07-05 14:31:05 -07:00
Fabio Berger
32ad34d224 properly stop blockstream and pass stateLayer into blockstream 2018-07-05 23:18:55 +02:00
Fabio Berger
cfbb1c440e Add pr number 2018-07-05 22:33:11 +02:00
Fabio Berger
ade2f96ca3 Add changelog notes 2018-07-05 22:32:25 +02:00
Fabio Berger
abb38e1bc0 Don't unsubscribe on Blockstream errors 2018-07-05 22:25:47 +02:00
Fabio Berger
0df36471b7 Pass actual networkId 2018-07-05 22:24:21 +02:00
fragosti
97312c2656 Use default networkId of 1 for ledger dropdown 2018-07-05 11:45:54 -07:00
fragosti
e9e4df4891 Fix onboarding closing on unlock metamask step on click outside 2018-07-05 11:28:34 -07:00
Francesco Agosti
e0f80c5e6a Merge pull request #816 from 0xProject/feature/website/portal-mobile-improvements
Make onboarding and wallet copy dynamic based on OS
2018-07-05 11:09:25 -07:00
Alex Shafranovich
f21b042ed1 Contracts 2.0.0 were linted with solhint 2018-07-05 21:01:14 +03:00
Alex Shafranovich
d8c7c9803c Added Solhint package and 'lint-contracts' npm script 2018-07-05 20:58:52 +03:00
fragosti
302b9deef3 Rename getBestDownloadLink to getBestWalletDownloadLinkAndIsMobile 2018-07-05 10:54:13 -07:00
Leonid Logvinov
0c8264801a Fix tests 2018-07-05 19:11:41 +02:00
Leonid Logvinov
54d1a0359f Fix prettier 2018-07-05 17:09:14 +02:00
Leonid Logvinov
b87e48c113 Fix merge conflicts 2018-07-05 16:51:37 +02:00
Fabio Berger
a874cd2424 Remove legacy logic 2018-07-05 16:42:01 +02:00
Fabio Berger
d9e308e53a Refactor order-watcher to use Blockstream under-the-hood 2018-07-05 16:39:53 +02:00
Leonid Logvinov
efc3536283 Add CHANGELOG entries 2018-07-05 16:30:36 +02:00
Leonid Logvinov
4b7e669d29 Upgrade artifacts 2018-07-05 16:02:26 +02:00
Leonid Logvinov
01c6efeaf1 Merge branch 'v2-prototype' into v2-contract-wrappers-WIP 2018-07-05 17:00:50 +03:00
Leonid Logvinov
22cf7bee5b Merge pull request #814 from 0xProject/feature/fill-scenarios-v2
@0xproject/contract-wrappers V2 refactor. Part 2
2018-07-05 16:59:12 +03:00
Leonid Logvinov
ef890aeac4 Adjust comments 2018-07-05 15:58:42 +02:00
Leonid Logvinov
91e8c00076 Fix comments 2018-07-05 15:58:42 +02:00
Leonid Logvinov
20bf4d8ef9 Improve the comment 2018-07-05 15:58:42 +02:00
Leonid Logvinov
795da130a2 Rename Proxie to Proxy 2018-07-05 15:58:41 +02:00
Leonid Logvinov
51a625d4af Rename compact_artifacts to artifacts 2018-07-05 15:58:41 +02:00
Leonid Logvinov
ab8544b0ff Rearrange assertions t match parameter order 2018-07-05 15:58:41 +02:00
Leonid Logvinov
b68d16820f Fix match orders test and add a validation TODO 2018-07-05 15:58:41 +02:00
Leonid Logvinov
61d9cdced0 Add tests for exchange contract wrapper 2018-07-05 15:58:41 +02:00
Leonid Logvinov
714f9ed207 Add Exchange contract wrapper 2018-07-05 15:56:32 +02:00
Leonid Logvinov
ccccaf8e12 Pass through blockPollingInterval down to contract wrapper 2018-07-05 15:56:31 +02:00
Leonid Logvinov
c3ce9d6104 Export orderStatus and OrderInfo 2018-07-05 15:56:31 +02:00
Leonid Logvinov
d3f602f063 Add blockPollingInterval config to contractWrappers config type 2018-07-05 15:56:31 +02:00
Leonid Logvinov
6b379a8a0f Add contractWrappers.erc721Proxy.getproxyIdAsync 2018-07-05 15:56:31 +02:00
Leonid Logvinov
d1d636f1ca Add contractWrappers.erc20Proxy.getproxyIdAsync 2018-07-05 15:56:31 +02:00
Leonid Logvinov
ba9d3cbdb8 Make it possible to configure block polling interval in base contract wrapper 2018-07-05 15:56:31 +02:00
Leonid Logvinov
bcf8d51806 Add blockPollingIntervalMs as an optional field to contract-wrappers config schemas 2018-07-05 15:05:58 +02:00
Leonid Logvinov
66c0d6724a Add even more entries to postinstall hack 2018-07-05 15:05:58 +02:00
Leonid Logvinov
0f477607f9 Update dummy tokens addresses in token_utils 2018-07-05 15:05:58 +02:00
Leonid Logvinov
c1635f2656 Remove only from tests 2018-07-05 15:05:57 +02:00
Leonid Logvinov
029d91bd7a Add OrderInfo and OrderStatus to types 2018-07-05 15:05:57 +02:00
Leonid Logvinov
03dbad6813 Add OrderTxOptsSchema 2018-07-05 15:05:57 +02:00
Leonid Logvinov
c65b2573c4 Refactor fill-scenarios for V2 2018-07-05 15:05:57 +02:00
Leonid Logvinov
7fbee77875 Export ecSignatureParameterSchema from json-schemas 2018-07-05 15:05:57 +02:00
Leonid Logvinov
3cc1a952ca Add ordersSchema to json-schemas 2018-07-05 15:05:57 +02:00
Leonid Logvinov
9c8de3e933 Fix VRS signature generation in order-utils 2018-07-05 15:05:57 +02:00
Leonid Logvinov
cbdce6b67e Update ABI in compact_artifacts 2018-07-05 15:05:57 +02:00
Leonid Logvinov
a6746ae5cd Upgrade artifacts 2018-07-05 15:05:57 +02:00
Leonid Logvinov
7111f3ffc6 Dump assert version and make the order-watcher depend on the old assert version 2018-07-05 15:05:57 +02:00
Fabio Berger
87a7a4ad2d Merge pull request #821 from 0xProject/remove-web3-from-wrapper
Remove Web3.js From 0x-monorepo 🍾
2018-07-05 15:04:58 +02:00
Leonid Logvinov
1ee2d6ed54 Merge branch 'v2-prototype' into v2-contract-wrappers-WIP 2018-07-05 15:04:01 +02:00
Leonid Logvinov
1eba78e20a Revert all changes to the contracts 2018-07-05 14:49:05 +02:00
Fabio Berger
a1fb438a8c Prettier fixes 2018-07-05 13:03:33 +02:00
Fabio Berger
40d1b0a23c Update json-schema version used by web3-wrapper 2018-07-05 12:35:38 +02:00
Fabio Berger
1c9a657693 Add schema assertion checks for callData and txData 2018-07-05 12:35:16 +02:00
Fabio Berger
11747c6cf4 Make sure from is included in txData 2018-07-05 12:34:15 +02:00
Fabio Berger
2a7b3aecc3 Add CallData schema to json-schemas 2018-07-05 12:33:48 +02:00
Fabio Berger
75babed693 Update assert changelog 2018-07-05 12:07:17 +02:00
Fabio Berger
0a32ae6cb5 Add defaultBlock param to getBalanceInWeiAsync 2018-07-05 12:04:08 +02:00
Fabio Berger
3d67f122a5 Move 'from' check to sendTransaction 2018-07-05 12:03:34 +02:00
Fabio Berger
b0daec8384 Remove bn.js unused dep 2018-07-05 01:56:40 +02:00
Fabio Berger
f5b1fe0e6b Fix linter issues 2018-07-05 01:45:56 +02:00
Fabio Berger
139d289b01 remove stray console.log 2018-07-05 01:39:46 +02:00
Fabio Berger
fd242a9cba Remove web3Utils dep and write necessary utility methods 2018-07-05 01:38:14 +02:00
Fabio Berger
7efa17ef7d Add new param javadoc comment 2018-07-05 00:40:43 +02:00
Fabio Berger
a0b9c7777b merge v2-prototype 2018-07-05 00:38:15 +02:00
Fabio Berger
5204e4c08d Pass 'from' param to estimateGas since it is required 2018-07-05 00:36:30 +02:00
Fabio Berger
1050ecdf3c Refactor Web3Wrapper to no longer use Web3.js & add more test coverage 2018-07-05 00:36:01 +02:00
Fabio Berger
5176d929fa Merge pull request #817 from 0xProject/remove-web3
Remove Web3 Dependencies (exept for in web3-wrapper)
2018-07-04 18:51:17 +02:00
Fabio Berger
d712dc47d9 Removee getContractFromAbi method since we no longer use it and do not recommend others use it 2018-07-04 18:11:50 +02:00
Fabio Berger
8adc6f0faa merge v2-prototype 2018-07-04 16:35:49 +02:00
Fabio Berger
4e783fba57 Add missing undefined check 2018-07-04 16:34:03 +02:00
Jacob Evans
ade620f4f7 Merge pull request #775 from RadarRelay/eth-lightwallet-subprovider-final
Eth lightwallet subprovider (replaces #660)
2018-07-04 20:49:25 +10:00
Jacob Evans
5915f8430c Merge branch 'v2-prototype' into eth-lightwallet-subprovider-final 2018-07-04 20:29:54 +10:00
Jacob Evans
9e0f06d060 Specify the lint rule to disable 2018-07-04 20:06:10 +10:00
Fabio Berger
ce86ae0191 Add assert dep 2018-07-04 08:56:12 +02:00
Fabio Berger
2bec5cb7fd Fix bug in string enum assertion so that we check enum values not keys 2018-07-04 08:55:16 +02:00
Fabio Berger
cd766ea2a1 Add more assertions to Web3Wrapper public methods 2018-07-04 08:54:43 +02:00
Fabio Berger
aeea3817a4 Merge pull request #818 from 0xProject/fix-intermittent-test-failure
Fix intermittent test failure in Subproviders package
2018-07-04 07:48:37 +02:00
fragosti
0f11ae1875 No longer elevate relayer grid tile on long press 2018-07-03 18:22:19 -07:00
fragosti
6e87e3e1ac Fix issue where onboarding doesn't scroll to wallet when starting from relayers page 2018-07-03 18:05:00 -07:00
Fabio Berger
4ba108d12f Use stub in test to avoid difference in setup, how network requests take place 2018-07-04 00:59:18 +02:00
Fabio Berger
8ff17ff960 improve comment 2018-07-04 00:41:19 +02:00
Fabio Berger
0d56daf7ab remove console.log 2018-07-04 00:37:39 +02:00
Fabio Berger
9db0bc262b Fix conditional 2018-07-04 00:36:57 +02:00
Fabio Berger
f410903465 Rename to InjectedProvider and make publicConfigStore optional 2018-07-04 00:29:29 +02:00
Fabio Berger
5f2c303bd8 Remove hack since latest web3-provider-engine fixed underlying issue 2018-07-04 00:23:40 +02:00
Fabio Berger
6aa4984fed Fix instance variable name 2018-07-04 00:22:21 +02:00
Fabio Berger
f5cd1ac82e Fix linter 2018-07-04 00:18:09 +02:00
Fabio Berger
54c0b7b261 Fix type 2018-07-04 00:13:36 +02:00
Fabio Berger
a7902eca1f Fix package.json 2018-07-03 23:57:33 +02:00
Fabio Berger
2b4bb579d4 Rename subprovider in blockchain.ts 2018-07-03 23:57:19 +02:00
fragosti
52c956222e Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/portal-mobile-improvements 2018-07-03 14:43:23 -07:00
Francesco Agosti
0900e0c85e Merge pull request #811 from 0xProject/feature/website/onboarding-polish-2
Add Hotjar, and other small improvements
2018-07-03 14:43:02 -07:00
Fabio Berger
a5653337c1 Remove unused imported Web3.js 2018-07-03 23:36:14 +02:00
Fabio Berger
d097113639 Remove dep on Web3 in Website. Introduced InjectedWeb3 type. 2018-07-03 23:34:51 +02:00
fragosti
9389d64392 Add toshi logo asset 2018-07-03 14:32:11 -07:00
fragosti
931e7e7d71 Prompt user to download Toshi or MetaMask in install wallet onboarding step 2018-07-03 14:28:49 -07:00
Fabio Berger
cce2fb40a1 Fix import 2018-07-03 23:11:59 +02:00
Fabio Berger
547cf4bef3 Refactor testnet-faucet to use web3Wrapper instead of web3 directly 2018-07-03 23:11:49 +02:00
Fabio Berger
d528ce757c Replace use of web3 w/ web3wrapper in subproviders and rename injectedWeb3 to signer subprovider for clarity 2018-07-03 22:58:17 +02:00
fragosti
3b78188fec Show different download links and icons when on mobile 2018-07-03 13:51:58 -07:00
Alex Browne
d91b30faef Merge pull request #812 from 0xProject/fix/revert-assertions-improvements
Improve robustness of revert reason assertions
2018-07-03 13:42:30 -07:00
Alex Browne
dc956020ef Move NodeType caching out of web3-wrapper and into our internal code 2018-07-03 12:57:11 -07:00
fragosti
a52eb81380 Rename isMobile utility fn to be more specific and add isMobileOperatingSystem 2018-07-03 12:48:19 -07:00
fragosti
ab0055d5c6 Add OperatingSystemType and get OS util 2018-07-03 12:45:28 -07:00
fragosti
32c25a2034 Persist whether onboarding is open or close across refreshes 2018-07-03 11:48:34 -07:00
fragosti
c30b42434a Fix linting 2018-07-03 11:31:40 -07:00
fragosti
3c797a6e11 Merge branch 'fixed-position-onboarding' into feature/website/onboarding-polish-2 2018-07-03 11:26:26 -07:00
Brandon Millman
9b864517e2 Merge pull request #799 from 0xProject/feature/website/wallet-menu
Add menu for at the top of wallet and top right component
2018-07-03 11:19:52 -07:00
Fabio Berger
a858e2870b Merge pull request #815 from 0xProject/update-dependencies
Update Blockstream & ProviderEngine
2018-07-03 20:19:08 +02:00
Alex Browne
ce1542da4f Update CHANGELOG.json for ethereum-types and web3-wrapper 2018-07-03 10:59:45 -07:00
Alex Browne
d2ebf4a777 Add TransactionReceiptStatus type to ethereum-types 2018-07-03 10:49:35 -07:00
Alex Browne
c5fcea1dbd Actually cache node type in web3-wrapper 2018-07-03 10:40:54 -07:00
Fabio Berger
5e8ef070e2 Fix alignment 2018-07-03 18:26:12 +02:00
Brandon Millman
2d30c290e9 Remove InstallPrompt 2018-07-03 09:22:52 -07:00
Fabio Berger
688b34710e Update blockstream to latest version, propogate errors to top-level callers 2018-07-03 18:15:20 +02:00
Brandon Millman
afbfc8ba1c Implement clickaway for wallet menu on mobile 2018-07-03 09:06:29 -07:00
Fabio Berger
671f29774b Update web3-provider-engine version w/o caret 2018-07-03 16:56:49 +02:00
Fabio Berger
4c99ac0ca2 Update web3-provider-engine 2018-07-03 15:59:30 +02:00
Leonid Logvinov
0e690608d3 Merge pull request #782 from 0xProject/feature/contract-wrappers-v2
@0xproject/contract-wrappers V2 refactor. Part 1
2018-07-03 15:32:38 +03:00
Fabio Berger
92f6391df5 Merge pull request #801 from feuGeneA/patch-3
in subproviders/package.json, cite typescript-typings only once
2018-07-03 11:53:23 +02:00
Brandon Millman
f2af6e4b3a Add optional onClick to Link simple menu item 2018-07-03 01:51:59 -07:00
Jacob Evans
27c03cffe2 Fix unused imports 2018-07-03 17:01:08 +10:00
Jacob Evans
499915042e Merge branch 'v2-prototype' into eth-lightwallet-subprovider-final 2018-07-03 16:58:08 +10:00
Jacob Evans
1a901554cc compiler and ts lint are confused about ContractEventArgs 2018-07-03 15:39:15 +10:00
Alex Browne
5b64b3ea93 Improve robustness of revert reason assertions 2018-07-02 18:57:33 -07:00
fragosti
6fc5c0cd46 Remove unused import 2018-07-02 18:36:41 -07:00
Brandon Millman
328da21420 Merge pull request #806 from 0xProject/feature/website/mobile-readable-web3-names
Add detection logic for Toshi and Cipher
2018-07-02 18:26:16 -07:00
Brandon Millman
81062d20eb Merge pull request #808 from 0xProject/feature/website/better-balance-formatting
Add better balance formatting rules for balances and usd values
2018-07-02 18:25:58 -07:00
Brandon Millman
835d06dcdc Merge pull request #810 from 0xProject/feature/wesbite/remove-add-balance
Remove increase balance link from balance_bounded_input component
2018-07-02 18:25:43 -07:00
fragosti
8929543b55 Add end comment to hotjar tracking code 2018-07-02 18:15:41 -07:00
fragosti
f62044c1e3 Add media file and remove stray comment 2018-07-02 18:14:21 -07:00
fragosti
a31f7a5112 Implement fixed position onboarding option 2018-07-02 18:12:08 -07:00
Brandon Millman
fe68114f39 Use new lock svg 2018-07-02 17:56:37 -07:00
fragosti
a5231df6d9 Add media query abstraction around ScreenWidths and stop relayer grid hover effect on mobile 2018-07-02 17:26:48 -07:00
Brandon Millman
fd545ec00f Remove increase balance link from balance_bounded_input component 2018-07-02 17:14:46 -07:00
Brandon Millman
73d8a2adf7 Always show the wrap ether row in between ETH and WETH 2018-07-02 17:02:11 -07:00
Brandon Millman
04d11d6fac Add human readable names for Toshi and Cipher 2018-07-02 16:37:22 -07:00
Brandon Millman
2eede4a09e Update start onboarding copy and relayer grid empty color 2018-07-02 16:30:13 -07:00
Brandon Millman
bc7e8ff471 Add better balance formatting rules for balances and usd values 2018-07-02 16:08:02 -07:00
fragosti
73e81c62fb Remove max-width from onboarding card to support iPad 2018-07-02 15:58:53 -07:00
fragosti
8c5dc7cecd Only auto-start onboarding if blockchain is loaded 2018-07-02 15:52:59 -07:00
Francesco Agosti
300c9f09b9 Merge pull request #805 from 0xProject/feature/website/add-alex-to-about
Add Alex Browne to about page
2018-07-02 14:09:31 -07:00
fragosti
06f4427939 Add Alex Browne to about page 2018-07-02 13:15:40 -07:00
Amir Bandeali
b1dc20bbb3 Add developer mailing list link to README 2018-07-02 09:51:51 -07:00
F. Eugene Aumson
4887d1d42f in subproviders, cite typescript-typings only once
`yarn build` was giving the following warning:

warning package.json: "dependencies" has dependency "@0xproject/typescript-typings" with range "^0.4.1" that collides with a dependency in "devDependencies" of the same name with version "^0.4.2"
2018-07-02 11:23:33 -04:00
Fabio Berger
d247d72e3e Merge pull request #803 from 0xProject/fix/publishing/remote-tag-removal
Small publish fixes
2018-07-02 16:20:34 +02:00
Fabio Berger
50957e1d29 Update incorrect versions of deps 2018-07-02 16:04:48 +02:00
Fabio Berger
6aad12a52f Add new changelog entry 2018-07-02 14:26:52 +02:00
Fabio Berger
db0944acde fix prettier 2018-07-02 14:21:49 +02:00
Fabio Berger
e553ef83de Git command outputs logs to stdErr so only way to check for errors if with try/catch 2018-07-02 14:20:42 +02:00
Fabio Berger
a619949a56 Remove remote tag before local one 2018-07-02 14:19:30 +02:00
Fabio Berger
1346fa792a Add logs for when tags get removed 2018-07-02 13:53:44 +02:00
Fabio Berger
b763cdbd4c combine changelog entries since we haven't published yet 2018-07-02 13:53:24 +02:00
Fabio Berger
e4eac14dc9 version outdated 2018-07-02 13:53:05 +02:00
Fabio Berger
bdda1f2992 Throw if changelog version is below package.json version 2018-07-02 13:32:22 +02:00
Fabio Berger
9c7289d7a3 Update outdated changelogs 2018-07-02 13:31:34 +02:00
Fabio Berger
d861caca23 Fix bug where 18 decimal tokens instead of 5 decimal tokens created 2018-07-02 12:31:02 +02:00
Fabio Berger
590033bcb2 Merge pull request #802 from 0xProject/fix/five_decimal_scenario
FillOrder Combinatorial Testing Fixes
2018-07-02 12:24:57 +02:00
Fabio Berger
af1e4574a8 Disable custom-no-magic-number for block 2018-07-02 11:39:07 +02:00
Fabio Berger
7b806fe84d Remove unused variable 2018-07-02 11:18:48 +02:00
Fabio Berger
e54e2ac67b Add .vscode from .gitignore 2018-07-02 11:13:31 +02:00
Fabio Berger
de9f0732a0 Merge branch 'v2-prototype' into fix/five_decimal_scenario
* v2-prototype: (75 commits)
  Update relayer grid tiles to use Text
  Fix build
  Update file structure
  Update 2.0.0 artifacts
  Move ledgerhq module declarations to typescript-typings
  Export LedgerEthereumClient type in subproviders
  Update artifacts
  Add logging and updated artifacts
  Fix migrations
  Run prettier
  Add Kovan artifacts
  Use ledger subprovider
  Add Kovan migrations
  Remove state variable from Link component in Portal
  Make registerAssetProxy append only
  Update staging api link
  Change getTransactionReceipt to awaitTransactionMined
  Move /docs route to the end
  Remove extra call to scrollIntoView for wallet in onboarding
  Update expectRevertReasonOrAlwaysFailingTransactionAsync to check status codes
  ...
2018-07-02 11:12:01 +02:00
Fabio Berger
20acdbf6c3 Add commented out scenarios not run by default 2018-07-02 11:01:15 +02:00
Fabio Berger
6a6d2f73a8 Fix comment 2018-07-02 11:00:32 +02:00
Fabio Berger
f5a8f00af8 Fix validation logic by checking for 0 maker/taker amount before 0 fillTakerAssetAmount since one causes the other during combinatorial testing 2018-07-02 10:52:49 +02:00
Fabio Berger
018a437d62 Print out entire orderFill scenario 2018-07-02 10:51:28 +02:00
Fabio Berger
32d75b6483 Transfer ERC721 token instead of burning, so we can still set an allowance to it in tests 2018-07-02 10:50:48 +02:00
Fabio Berger
cb6cace910 Fix bug where using nullAddress for order instead of actual taker address 2018-07-02 10:49:41 +02:00
Fabio Berger
0326ddd79d Add maker and taker balance/allowance scenarios to generateFillOrderCombination 2018-07-02 10:48:59 +02:00
Jacob Evans
d6f40a9281 Remove duplicated typescript-typings in package.json 2018-07-02 18:14:19 +10:00
Jacob Evans
687802394a Remove duplicate type definitions.
Clear private key earlier
Fix changelog in typescript-typings from bad merge
2018-07-02 18:09:05 +10:00
Jacob Evans
ad570b8ae1 Merge branch 'v2-prototype' into eth-lightwallet-subprovider-final 2018-07-02 11:21:16 +10:00
Jacob Evans
b9165c03af Use PrivateKeySubprovider inside eth lightwallet
There's a loss of information when hex encoding and passing to eth light wallet (chain id is lost). This results in a different signature. While it may work on testnets it is not sufficient for our test cases. We can export the private key and use it in our PrivateKeyWalletSubprovider
2018-07-02 11:09:32 +10:00
Brandon Millman
86d4ffe7e5 Lint fixes 2018-07-01 14:51:02 -07:00
Brandon Millman
2dea179333 More cleanup 2018-07-01 14:51:02 -07:00
Brandon Millman
5a7908984e Consolidate logic for common menu items 2018-07-01 14:51:02 -07:00
Brandon Millman
955fdf5d13 Give connected header accessory more padding 2018-07-01 14:51:02 -07:00
Brandon Millman
a6f40d4187 Implement correct behavior for menu in the wallet 2018-07-01 14:50:55 -07:00
Brandon Millman
6daf754f5b Add menu to wallet 2018-07-01 14:50:55 -07:00
Brandon Millman
da8cf9981e Implement simple menu 2018-07-01 14:50:55 -07:00
Brandon Millman
be64184cfa Clean up a bit of the provider display logic 2018-07-01 14:50:55 -07:00
Brandon Millman
3031598843 Implement icon button 2018-07-01 14:50:55 -07:00
Brandon Millman
b9b00e10d3 Update relayer grid tiles to use Text 2018-06-30 12:37:34 -07:00
Amir Bandeali
6c34255a3e Merge pull request #781 from 0xProject/refactor/contracts/fileStructure
Update contracts file structure
2018-06-29 18:36:00 -07:00
Amir Bandeali
41064adc66 Fix build 2018-06-29 18:20:44 -07:00
Amir Bandeali
2fcc36bbad Update file structure 2018-06-29 18:05:40 -07:00
Amir Bandeali
762c0143eb Merge pull request #770 from 0xProject/feature/migrations/kovan-deploy
Add Kovan migrations
2018-06-29 17:49:15 -07:00
Amir Bandeali
6c6f34ee72 Update 2.0.0 artifacts 2018-06-29 17:41:25 -07:00
Francesco Agosti
42b7b0dab9 Merge pull request #787 from 0xProject/feature/website/portal-onboarding-polish
Portal v2 onboarding polish
2018-06-29 17:40:43 -07:00
Amir Bandeali
e58e35e098 Move ledgerhq module declarations to typescript-typings 2018-06-29 17:25:56 -07:00
Amir Bandeali
654b048602 Export LedgerEthereumClient type in subproviders 2018-06-29 17:25:56 -07:00
Amir Bandeali
3ece72af49 Update artifacts 2018-06-29 17:25:56 -07:00
Amir Bandeali
2ef31991c7 Add logging and updated artifacts 2018-06-29 17:25:56 -07:00
Amir Bandeali
d3293a5571 Fix migrations 2018-06-29 17:25:56 -07:00
Amir Bandeali
854752acdf Run prettier 2018-06-29 17:25:56 -07:00
Amir Bandeali
0c889385f1 Add Kovan artifacts 2018-06-29 17:25:56 -07:00
Amir Bandeali
6e1a549fcb Use ledger subprovider 2018-06-29 17:25:56 -07:00
Amir Bandeali
5f0a2953c6 Add Kovan migrations 2018-06-29 17:25:56 -07:00
Amir Bandeali
78b513c52a Merge pull request #797 from 0xProject/refactor/contracts/registerAssetProxy
Make registerAssetProxy append only
2018-06-29 17:25:21 -07:00
fragosti
8ffce78827 Remove state variable from Link component in Portal 2018-06-29 16:47:58 -07:00
Amir Bandeali
d4852092b8 Make registerAssetProxy append only 2018-06-29 16:25:16 -07:00
Brandon Millman
622ce0bf2e Update staging api link 2018-06-29 16:11:57 -07:00
Amir Bandeali
6a197a64e6 Merge pull request #793 from 0xProject/feature/contracts/transferFromFallback
Optimize transferFrom (saves ~2000 gas /fill)
2018-06-29 15:34:56 -07:00
Amir Bandeali
1e4c3ed22b Change getTransactionReceipt to awaitTransactionMined 2018-06-29 15:21:00 -07:00
Brandon Millman
e3521c6388 Move /docs route to the end 2018-06-29 15:20:44 -07:00
fragosti
9d81e069dc Remove extra call to scrollIntoView for wallet in onboarding 2018-06-29 14:04:41 -07:00
Amir Bandeali
8623a30763 Merge pull request #796 from 0xProject/fix/contracts/failingTransactionAssertions
Update expectRevertReasonOrAlwaysFailingTransactionAsync to check status codes
2018-06-29 14:03:28 -07:00
Alex Browne
6cf39896f1 Update expectRevertReasonOrAlwaysFailingTransactionAsync to check status codes 2018-06-29 13:46:42 -07:00
Amir Bandeali
44b6adaa29 Fix deployment to geth 2018-06-29 13:33:22 -07:00
Amir Bandeali
762a6199b2 Fix tests 2018-06-29 13:33:22 -07:00
Amir Bandeali
8da42b12f4 Remove transferFrom, implement in fallback function 2018-06-29 13:33:22 -07:00
fragosti
c473a0444c Bump automatic show onborading delay by 1000ms 2018-06-29 13:30:43 -07:00
fragosti
e693629bbd Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/portal-onboarding-polish 2018-06-29 13:27:19 -07:00
fragosti
0dbe883c3b Fix onboarding always starting 2018-06-29 13:24:31 -07:00
Brandon Millman
cc12bc9247 Merge pull request #792 from 0xProject/feature/website/wallet-polish
Various wallet polish items
2018-06-29 12:01:13 -07:00
Brandon Millman
ddec01e6c1 Change function to a const 2018-06-29 11:56:31 -07:00
Brandon Millman
03bc7bb935 Move wallet scrollIntoView into PortalOnboardingFlow 2018-06-29 11:55:00 -07:00
fragosti
5207dfdc0e Rename userHasAllowances bool to follow proper convention 2018-06-29 11:50:24 -07:00
fragosti
fc40efb761 Allow you to continue the onboarding flow once youve installed metamask and refreshed the page 2018-06-29 11:47:12 -07:00
Amir Bandeali
50556e2609 Merge pull request #774 from 0xProject/style/contracts/abiEncodeAsmComments
Added some comments for ASM hashing
2018-06-29 11:41:23 -07:00
Alex Browne
7a22298597 Merge pull request #794 from 0xProject/fix/devnet-minimum-blocks
Improve reliability of the minimum block number hack for devnet/geth
2018-06-29 11:21:17 -07:00
fragosti
36cadaae46 Use Image component where relevant and add back tracked token timestamp logic 2018-06-29 11:08:48 -07:00
Leonid Logvinov
09e921a562 Fix build after rebase 2018-06-29 17:52:55 +03:00
Leonid Logvinov
13cbaf56b2 Add a comment 2018-06-29 17:52:55 +03:00
Leonid Logvinov
62910c8e89 Assign true values to names vars 2018-06-29 17:52:55 +03:00
Leonid Logvinov
f20e1acad9 Fix a typo 2018-06-29 17:52:55 +03:00
Leonid Logvinov
5dea432ebf Set the interval to 0 in awaitTranscationSuccessAsync 2018-06-29 17:52:55 +03:00
Leonid Logvinov
016d82d766 Make promises dangerous 2018-06-29 17:52:54 +03:00
Leonid Logvinov
260c72cc20 Add a TODO comment 2018-06-29 17:52:54 +03:00
Leonid Logvinov
3d7bcd7ecb Add isSubscriptionToken assertion 2018-06-29 17:52:54 +03:00
Leonid Logvinov
ac9175bf88 Rename approved to approvedAddress 2018-06-29 17:52:54 +03:00
Leonid Logvinov
294d3bbdc1 Use removeUndefinedProperties for txOpts 2018-06-29 17:52:54 +03:00
Leonid Logvinov
6db614251e Rename getApprovedAsync to getApprovedIfExistsAsync 2018-06-29 17:52:54 +03:00
Leonid Logvinov
bcc588efe7 Add HACK comments 2018-06-29 17:52:54 +03:00
Leonid Logvinov
f7b3fc58bc Add assertions for txOpts and methodOpts 2018-06-29 17:52:54 +03:00
Leonid Logvinov
de40497330 Remove v2 artifact scripts 2018-06-29 17:52:54 +03:00
Leonid Logvinov
d84bb7ed7e Remove tokenTransferProxyAddress from config 2018-06-29 17:52:54 +03:00
Leonid Logvinov
f02ada2d11 Add a hack comment 2018-06-29 17:52:54 +03:00
Leonid Logvinov
48970d3424 Fix a typo 2018-06-29 17:52:54 +03:00
Leonid Logvinov
8940b1759d Fix linter errors 2018-06-29 17:52:54 +03:00
Leonid Logvinov
91a50d0f53 Fix addresses in WETH9 and ZRX token artifacts 2018-06-29 17:52:54 +03:00
Leonid Logvinov
ed4f8c5b66 Fix the token supply in migrations 2018-06-29 17:52:53 +03:00
Leonid Logvinov
2f07ee0a8f Dump assert version and make the order-watcher depend on the old assert version 2018-06-29 17:52:53 +03:00
Leonid Logvinov
8dd00a8eef Change event args names after templates change 2018-06-29 17:52:53 +03:00
Leonid Logvinov
d7845a177e Add contract-wrappers -> json-schemas and order-utils to postinstall hack 2018-06-29 17:52:53 +03:00
Leonid Logvinov
7a3be0a320 Change import paths from z_r_x and e_r_c to zrx and erc in migrations 2018-06-29 17:52:53 +03:00
Leonid Logvinov
14cebce304 Regenerate yarn.lock 2018-06-29 17:52:53 +03:00
Leonid Logvinov
9fcf9f2504 Export newly refactored contracts from contract-wrappers and index.ts 2018-06-29 17:52:53 +03:00
Leonid Logvinov
c466ab6cf2 Change artifacts list and add dependencies to package.json 2018-06-29 17:52:53 +03:00
Leonid Logvinov
01bf789ad4 Bump the version so that order-watcher doesn't pick it up 2018-06-29 17:52:53 +03:00
Leonid Logvinov
1a1ab5af54 Refactor event subscription tests 2018-06-29 17:52:53 +03:00
Leonid Logvinov
4089ad7b4b Refactor types 2018-06-29 17:52:53 +03:00
Leonid Logvinov
2adc299c78 Implement ERC721 token wrapper and token transfer proxy with tests 2018-06-29 17:52:53 +03:00
Leonid Logvinov
3aef323c13 Refactor ERC20 token transfer proxy and it's tests 2018-06-29 17:52:53 +03:00
Leonid Logvinov
a655cd046c Refactor ERC20 token wrapper and it's tests 2018-06-29 17:52:53 +03:00
Leonid Logvinov
9c8701f5f6 Refactor ether token wrapper test 2018-06-29 17:52:52 +03:00
Leonid Logvinov
7ac84aff0a Refactor base contract-wrapper class to use new names, artifact format and only decode logs from that contract 2018-06-29 17:52:52 +03:00
Leonid Logvinov
fd13c8f68c Refactor EtherToken contract wrapper to use new names and artifacts format 2018-06-29 17:52:52 +03:00
Leonid Logvinov
532964af42 Use new signature verification method in assertions 2018-06-29 17:52:52 +03:00
Leonid Logvinov
52d1407215 Export txDefaults from web3_wrapper.ts 2018-06-29 17:52:52 +03:00
Leonid Logvinov
ecb7356345 Refactor tokenUtils to not use tokenRegistry 2018-06-29 17:52:52 +03:00
Leonid Logvinov
edda7dae94 Add new test constants 2018-06-29 17:52:52 +03:00
Leonid Logvinov
32da0a376a Skip & refactor artifacts tests 2018-06-29 17:52:52 +03:00
Leonid Logvinov
073e76ee90 Run V2 migrations instead of V1 before tests 2018-06-29 17:52:52 +03:00
Leonid Logvinov
ceba82260f Remove unused params in filter_utils 2018-06-29 17:52:52 +03:00
Leonid Logvinov
a5a61c87fc Start unused parameter names with underscore 2018-06-29 17:52:52 +03:00
Leonid Logvinov
d34feb1e0a Remove old contracts and add new ones to/from artifacts.ts 2018-06-29 17:52:52 +03:00
Leonid Logvinov
6cc5e45183 Remove exchange-related functionality for now 2018-06-29 17:52:52 +03:00
Leonid Logvinov
618c7ef48a Update compact_wrtifacts 2018-06-29 17:52:52 +03:00
Leonid Logvinov
14047f9c7b Change import paths from z_r_x and e_r_c to zrx and erc. Also rename event args after templates change 2018-06-29 17:52:51 +03:00
Leonid Logvinov
f439f162d2 Change import paths from z_r_x and e_r_c to zrx and erc 2018-06-29 17:52:51 +03:00
Leonid Logvinov
5b685b32bd Rename TransferContractEventArgs to MetacoinTransferEventArgs after changing contracts templates 2018-06-29 17:52:51 +03:00
Leonid Logvinov
6ce151c676 Change import paths from z_r_x and e_r_c to zrx and erc 2018-06-29 17:52:51 +03:00
Leonid Logvinov
eb79b5d651 Pin contract-wrappers version 2018-06-29 17:52:51 +03:00
Leonid Logvinov
608e1c8960 Remove unused code/variables from abi-decoder 2018-06-29 17:52:51 +03:00
Leonid Logvinov
f8772d8850 Rename {{*}}ContractEventArgs to {{*}}EventArgs and append {{contractName}} to each event name (ERC721TransferEventArgs instead of TransferContractEventArgs) 2018-06-29 17:52:51 +03:00
Leonid Logvinov
ce2f408864 Update json-schema version to 1.0.0 2018-06-29 17:52:51 +03:00
Leonid Logvinov
c2a362e3ea Add to postinstall hack: rm fill-scenarios/node_modules/@0xproject 2018-06-29 17:52:51 +03:00
Leonid Logvinov
eafdd4d42d Remove generated contract directory before writing new contracts and replace z_r_x and e_r_c with zrx and erc accordingly 2018-06-29 17:52:51 +03:00
Fabio Berger
1a2c58494f Merge pull request #783 from 0xProject/miscenaleous-fixes
Migration Related Miscellaneous fixes
2018-06-29 11:59:49 +02:00
Fabio Berger
68c00976f1 Fix merge 2018-06-29 11:40:05 +02:00
Fabio Berger
aa2616b307 Merge v2-prototype 2018-06-29 11:34:38 +02:00
Jacob Evans
3062c18ebd Merge pull request #795 from 0xProject/miscellaneous-fixes/v2-exchange-register-assets
Register the asset proxies to exchange
2018-06-29 19:31:10 +10:00
Jacob Evans
a83f5241dc Register the asset proxies to exchange 2018-06-29 19:12:42 +10:00
Brandon Millman
f89acb49be Add dollar sign to NullTokenRow 2018-06-29 01:11:02 -07:00
Brandon Millman
2b5f45676f Remove unused imports and variables 2018-06-29 01:07:50 -07:00
Brandon Millman
aedd51a61b Refactor inline styles out of Wallet 2018-06-29 00:59:24 -07:00
Brandon Millman
0b5a49c17d Remove some hardcoded MetaMask colors 2018-06-28 23:31:17 -07:00
Brandon Millman
08f7666d21 Create AccountConnection component 2018-06-28 23:24:57 -07:00
Brandon Millman
81ff99276b Fix scrollbar bug 2018-06-28 23:03:30 -07:00
fragosti
e71862676c Bold all balances in onboarding 2018-06-28 18:02:32 -07:00
fragosti
67777c586d Customize allowance setting onboarding step if you have your allowances set 2018-06-28 18:00:10 -07:00
fragosti
9ada8e4ddf Re-center react-popper on every step 2018-06-28 17:51:39 -07:00
fragosti
0142e7fa8f Fix button hover and active hover state 2018-06-28 17:37:22 -07:00
fragosti
467e9abf5f Show eth balance in add eth balance onboarding step 2018-06-28 17:34:29 -07:00
fragosti
512980d9bd Change onboarding flow to communicate 3 steps 2018-06-28 17:25:58 -07:00
fragosti
e235a63119 Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/portal-onboarding-polish 2018-06-28 17:20:05 -07:00
Alex Browne
4c28b66539 Add @0xproject/utils as dependency to dev-utils/package.json 2018-06-28 15:42:56 -07:00
Greg Hysen
46d79e5115 Updated hashing comments as-per PR 2018-06-28 15:41:06 -07:00
Alex Browne
d79994fbb2 Improve reliability of the minimum block number hack for the devnet/geth 2018-06-28 15:32:14 -07:00
Brandon Millman
518a2da027 Merge pull request #791 from 0xProject/bug/website/broken-not-found
Fix NotFound component and render 0x.js docs for /docs
2018-06-28 12:35:18 -07:00
Brandon Millman
71fa92dbeb Fix NotFound component and render 0x.js docs for /docs 2018-06-28 12:24:34 -07:00
Brandon Millman
172d2353dd Start onboarding from relayer index 2018-06-28 11:50:08 -07:00
Brandon Millman
3315006c45 Fix learn how to set up account layout 2018-06-28 11:50:08 -07:00
Brandon Millman
6700745585 Fix typo 2018-06-28 11:50:08 -07:00
Brandon Millman
0ff18058ab Get rid of unused stuff in wallet 2018-06-28 11:50:08 -07:00
Brandon Millman
1a11283086 Fix body overlay on mobile 2018-06-28 11:50:08 -07:00
Brandon Millman
ed559be47c Change learn how to update your account styling 2018-06-28 11:50:08 -07:00
Brandon Millman
a60dd1cbaf Fix key issue and remove WalletDisconnectedItem 2018-06-28 11:50:08 -07:00
Brandon Millman
7ee37fb62a Implement new locked and uninstalled states 2018-06-28 11:50:08 -07:00
Brandon Millman
2970e103db Fix off center icon in wallet 2018-06-28 11:50:08 -07:00
Brandon Millman
78333b3026 Change wallet margin based on hover to prevent re-layout 2018-06-28 11:50:08 -07:00
Brandon Millman
1ca182e741 Update ProviderDisplay with new design 2018-06-28 11:50:08 -07:00
Brandon Millman
8419db53bb Implement provider name in header 2018-06-28 11:50:08 -07:00
Brandon Millman
f76c9bc226 Implement loading body rows 2018-06-28 11:50:08 -07:00
Brandon Millman
6a39a69afe Added Circle component 2018-06-28 11:50:08 -07:00
Francesco Agosti
2474d1d2f4 Merge pull request #780 from 0xProject/feature/website/support-new-metamask
Refactor Blockchain.ts to allow arbitrary provider state changes
2018-06-28 11:36:49 -07:00
fragosti
e4188f5d4c Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/support-new-metamask 2018-06-28 11:17:30 -07:00
Brandon Millman
0fcbd02d50 Merge pull request #762 from 0xProject/feature/website/scroll-to-token
Sort wallet tokens by timestamp added and scroll to newly added token
2018-06-28 10:47:43 -07:00
Brandon Millman
4969797c23 Remove isTracked field on token in favor of trackedTimestamp 2018-06-28 10:39:16 -07:00
Brandon Millman
0e932286d2 Use moment and lodash 2018-06-28 10:38:07 -07:00
Brandon Millman
366a9502dd Sort wallet tokens by timestamp added and scroll to newly added token 2018-06-28 10:38:07 -07:00
Fabio Berger
988a334758 Merge pull request #707 from 0xProject/feature/combinatorial-testing
OrderFill Declarative Testing & Combinatorial Tests [Merge after #760]
2018-06-28 11:04:16 +02:00
Fabio Berger
4fe6269043 Remove unused constants 2018-06-28 10:45:28 +02:00
Fabio Berger
646927962a Reduce the userAddresses to the individual addresses actually used by tests, as well as only deploy the number of ERC20 tokens needed for each test suite 2018-06-28 10:43:37 +02:00
Fabio Berger
b56baefaa6 Add await time constant 2018-06-28 09:34:13 +02:00
Fabio Berger
f49a507297 Add missing awaitTransactionSuccessAsync calls 2018-06-28 09:13:56 +02:00
fragosti
c20549e88d Scroll to top when going to relayers page from onboarding 2018-06-27 19:23:51 -07:00
fragosti
cd16986942 Bring you directly to relayers page once you finish onboarding 2018-06-27 19:21:09 -07:00
fragosti
e481404a14 Remove period in title from last step 2018-06-27 19:07:53 -07:00
fragosti
3dfde15133 Always restart onboarding from 0 and other small improvements 2018-06-27 18:56:14 -07:00
fragosti
4454cfa65d Customize flow depending on what steps you've completed 2018-06-27 18:21:51 -07:00
fragosti
382839464f Break wrapping ETH into a 3rd step 2018-06-27 17:00:07 -07:00
fragosti
cce5585795 Fix animation when coming from bottom 2018-06-27 16:29:38 -07:00
fragosti
26a9fe9127 Fix width issue with onboarding card on mobile 2018-06-27 16:21:50 -07:00
fragosti
47a267c3fa Clicking overlay closes onboarding 2018-06-27 15:14:21 -07:00
fragosti
36836eb942 Fix z index issue with wrap buttons and onboarding cards 2018-06-27 14:45:01 -07:00
fragosti
aad0804a1e Break wrath ETH step into 2 2018-06-27 14:33:04 -07:00
fragosti
3c68d9c297 Fix skip button position on first step 2018-06-27 13:51:37 -07:00
fragosti
ffdc7d13a9 Make onboarding bounce around less 2018-06-27 13:40:52 -07:00
fragosti
c5085d8364 Scroll to wallet when onboarding automatically starts as well 2018-06-27 13:36:38 -07:00
fragosti
00ad7bc470 Change asset for final onboarding step 2018-06-27 13:23:17 -07:00
fragosti
360927ec77 Changing provider to ledger more consistent with previous experience 2018-06-27 11:37:24 -07:00
fragosti
b6f546ebe0 Fix convention stuff 2018-06-27 11:17:32 -07:00
fragosti
2a092143dc Remove IS_MAINNET_ENABLED config 2018-06-27 10:40:07 -07:00
fragosti
de50407953 Rename all corresponding bools to shouldUseLedgerProvider 2018-06-27 10:34:17 -07:00
Fabio Berger
57d5fbfbd8 Merge pull request #766 from perissology/feature/solcov-ignore
[sol-cov] add ability to ignore covering specific code blocks
2018-06-27 19:00:16 +02:00
Fabio Berger
92322c0e07 Remove network 50 details 2018-06-27 18:42:34 +02:00
Fabio Berger
97ed453eb4 Re-generate and clean up artifacts for 2.0.0 2018-06-27 18:34:44 +02:00
Fabio Berger
654b782810 Add missing AssetProxyOwner from compile:v2 command 2018-06-27 18:34:03 +02:00
Fabio Berger
51211a21ba Improve ganache-core's GanacheOpts type and require it instead of any 2018-06-27 18:33:32 +02:00
Fabio Berger
133b6fe240 Encode ZRX address as needed. 2018-06-27 18:32:48 +02:00
Fabio Berger
c824fe8718 Add optimizer settings to migrations compiler.json 2018-06-27 18:31:34 +02:00
Fabio Berger
26d3a487a5 Update ganache-cli to latest 2018-06-27 18:31:18 +02:00
perissology
e0a2afc068 rename function 2018-06-27 07:26:12 -07:00
Fabio Berger
f6e97bb284 Merge pull request #763 from prettymuchbryce/invalid-argument-error
Fix OrderWatcher uncaught Error
2018-06-27 11:55:04 +02:00
Fabio Berger
6c8b998505 Fix tslint 2018-06-27 11:28:41 +02:00
Fabio Berger
f9fab216e9 Merge branch 'v2-prototype' into invalid-argument-error 2018-06-27 11:02:40 +02:00
Fabio Berger
c308359f59 Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype:
  Improve 'web3-provider-engine' typings
  Fix build
  Update artifacts
  Add more revert reasons to tests
  Make dispatchTransferFrom revert with reason from AssetProxy on failure
  Remove redundant files, hard code function selector in dispatchTransferFrom, and modify revert reason
  Updated offset of receiverData length to reflect new assetData encoding.
  ERC20 Custom storage layout
  Golf the authorization check
  ERC20 manual memory layout
  ERC20 inline return
  ERC721 inline return
  Golf ERC721 transferFrom
  Inline ERC20 tranferFrom selector constant
  Optimize ERC20 transferFrom
  Polish asset picker layout
  Update relayer grid fallback icon
  Change metamask install link based on browser
  Use ethereumjs-tx@1.3.5 instead of our fork

# Conflicts:
#	packages/contracts/test/asset_proxy/proxies.ts
#	packages/contracts/test/exchange/core.ts
#	packages/migrations/artifacts/2.0.0/DummyERC721Token.json
2018-06-27 10:59:37 +02:00
Fabio Berger
375d667144 Move combinatorial fillOrder tests into the fill_ordere test file 2018-06-27 10:43:12 +02:00
Nikita Galkin
84bd54ba40 Improve 'web3-provider-engine' typings 2018-06-27 09:26:48 +03:00
Amir Bandeali
73c36fe2d2 Merge pull request #773 from 0xProject/feature/contracts/abi-calldata-proxy
Optimize transfer
2018-06-26 18:38:30 -07:00
Amir Bandeali
ec3e9efdaa Fix build 2018-06-26 18:30:20 -07:00
Amir Bandeali
d5c389b7dc Update artifacts 2018-06-26 17:36:44 -07:00
Amir Bandeali
7f233dcb15 Add more revert reasons to tests 2018-06-26 17:34:43 -07:00
Fabio Berger
6a2421c683 Fix tests 2018-06-26 23:17:29 +02:00
Fabio Berger
d66ca7b5cb Fix enum name 2018-06-26 23:17:20 +02:00
fragosti
5e38cbd69c Never use trackedTokenState when fetching new token state 2018-06-26 13:58:31 -07:00
Amir Bandeali
b6d8dcb6e1 Make dispatchTransferFrom revert with reason from AssetProxy on failure 2018-06-26 13:57:55 -07:00
Amir Bandeali
08ee1ab2e6 Remove redundant files, hard code function selector in dispatchTransferFrom, and modify revert reason 2018-06-26 13:57:51 -07:00
fragosti
26edec5773 Fix bug where we are requesting tokens on a different network 2018-06-26 13:43:25 -07:00
fragosti
d72e06842f Remove unused variables 2018-06-26 12:48:00 -07:00
fragosti
0a0da63ac7 Make unsubscribing work 2018-06-26 12:33:38 -07:00
Greg Hysen
873ec898d8 Updated offset of receiverData length to reflect new assetData encoding. 2018-06-26 12:23:19 -07:00
Remco Bloemen
97a70d14a3 ERC20 Custom storage layout 2018-06-26 12:23:19 -07:00
Remco Bloemen
394fbebfa8 Golf the authorization check 2018-06-26 12:23:19 -07:00
Remco Bloemen
b79588c4a0 ERC20 manual memory layout 2018-06-26 12:23:19 -07:00
Remco Bloemen
3b46e82625 ERC20 inline return 2018-06-26 12:23:19 -07:00
Remco Bloemen
dbaf1fcd43 ERC721 inline return 2018-06-26 12:23:19 -07:00
Remco Bloemen
4caf1271e4 Golf ERC721 transferFrom 2018-06-26 12:23:19 -07:00
Remco Bloemen
6921943aff Inline ERC20 tranferFrom selector constant 2018-06-26 12:23:19 -07:00
Remco Bloemen
3ce90b8257 Optimize ERC20 transferFrom 2018-06-26 12:23:19 -07:00
fragosti
3866154b50 Fix stateful ledger dialog edge state 2018-06-26 12:16:10 -07:00
fragosti
64ed2464cf Get things working with legacy portal 2018-06-26 12:09:20 -07:00
fragosti
e27780aee9 Fix subtle issues with ledger config dialog 2018-06-26 11:59:23 -07:00
Brandon Millman
744e6e60c5 Polish asset picker layout 2018-06-26 11:17:00 -07:00
fragosti
f70c1ff009 Ledger to metamask to ledger working 2018-06-26 11:01:50 -07:00
Brandon Millman
3a808fe7fd Update relayer grid fallback icon 2018-06-26 10:40:59 -07:00
Brandon Millman
2ca169b3c4 Merge pull request #777 from 0xProject/feature/website/browser-detection
Change metamask install link based on browser
2018-06-26 10:29:26 -07:00
Alex Browne
098d486291 Merge pull request #776 from 0xProject/ethereum-js-tx-1.3.5
Use ethereumjs-tx@1.3.5 instead of our fork
2018-06-26 10:22:53 -07:00
Fabio Berger
ec4fb70b80 Merge pull request #760 from 0xProject/refactor/check-revert-reasons
Check Revert Reasons in Contract Tests
2018-06-26 19:20:19 +02:00
Fabio Berger
2a82807be4 Fix type issue 2018-06-26 19:16:57 +02:00
Fabio Berger
43ae868c69 Merge branch 'refactor/check-revert-reasons' into feature/combinatorial-testing
* refactor/check-revert-reasons:
  Temporarily switch revert reasons to `TransferFailed`. Should be `InvalidAmount` but because of an oversight in the assembly implementation of `dispatchTransferFrom`, it always throws `TransferFailed`
  Expect RevertReason be passed in, not string
  Rename RevertReasons to RevertReason since singular enum names are more common

# Conflicts:
#	packages/contracts/test/asset_proxy/proxies.ts
#	packages/contracts/test/exchange/core.ts
2018-06-26 18:53:44 +02:00
Fabio Berger
1bc742aed1 Temporarily switch revert reasons to TransferFailed. Should be InvalidAmount but because of an oversight in the assembly implementation of dispatchTransferFrom, it always throws TransferFailed 2018-06-26 18:49:10 +02:00
Fabio Berger
6dc852774e Update AbstractAssetWrapper 2018-06-26 08:52:25 +02:00
Fabio Berger
7967ebed57 Rename to singular 2018-06-26 08:51:40 +02:00
Fabio Berger
105b927397 Fix merge issues 2018-06-26 08:43:37 +02:00
Fabio Berger
9219f9d8ae Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (21 commits)
  Don't use variables for revert reasons
  Add comments to dispatchTransferFrom
  Document IAssetData
  Compute bytes4 proxyid constants
  Return inplace bytes in LibBytes.readBytesWithLength
  Add Greg's documentation to MixinErc721Transfer
  Add Greg's documentation to MixinErc20Transfer
  Gas golf the transfer success logic
  Optimize like in PR #767
  Run prettier and fix linting errors
  Fix tests
  Update tests
  Fix AssetProxyUtils
  Update tests
  Fix ERC721Proxy TokenId
  Update AssetProxyUtils
  Add IAssetData
  WIP
  ABI encoded asset data
  Remove proxyId argument from dispatchTransferFrom
  ...

# Conflicts:
#	packages/contracts/test/asset_proxy/proxies.ts
2018-06-26 08:13:59 +02:00
Fabio Berger
f780e6f235 Expect RevertReason be passed in, not string 2018-06-26 08:11:32 +02:00
Fabio Berger
27670f4da6 Rename RevertReasons to RevertReason since singular enum names are more common 2018-06-26 08:11:14 +02:00
Fabio Berger
e051743a3d Merge branch 'v2-prototype' into refactor/check-revert-reasons
* v2-prototype: (21 commits)
  Don't use variables for revert reasons
  Add comments to dispatchTransferFrom
  Document IAssetData
  Compute bytes4 proxyid constants
  Return inplace bytes in LibBytes.readBytesWithLength
  Add Greg's documentation to MixinErc721Transfer
  Add Greg's documentation to MixinErc20Transfer
  Gas golf the transfer success logic
  Optimize like in PR #767
  Run prettier and fix linting errors
  Fix tests
  Update tests
  Fix AssetProxyUtils
  Update tests
  Fix ERC721Proxy TokenId
  Update AssetProxyUtils
  Add IAssetData
  WIP
  ABI encoded asset data
  Remove proxyId argument from dispatchTransferFrom
  ...

# Conflicts:
#	packages/contracts/test/asset_proxy/proxies.ts
2018-06-26 08:07:37 +02:00
Fabio Berger
fb03003b3a Fix inconsistency between contract and reference implementation of order validation logic 2018-06-26 07:50:24 +02:00
Brandon Millman
e52d0a3512 Change metamask install link based on browser 2018-06-25 17:48:36 -07:00
Amir Bandeali
cba92a01b6 Merge pull request #743 from 0xProject/feature/contracts/abi-encoded
ABI encode assetData fields
2018-06-25 16:53:15 -07:00
Alex Browne
0a87364101 Use ethereumjs-tx@1.3.5 instead of our fork 2018-06-25 16:40:33 -07:00
Amir Bandeali
a89908540f Don't use variables for revert reasons 2018-06-25 16:34:06 -07:00
fragosti
c4e2dcafa4 Have basic network switching working 2018-06-25 16:26:34 -07:00
Amir Bandeali
0163984ea4 Add comments to dispatchTransferFrom 2018-06-25 16:19:08 -07:00
Remco Bloemen
db3ce08cab Document IAssetData 2018-06-25 16:19:08 -07:00
Remco Bloemen
1076959006 Compute bytes4 proxyid constants 2018-06-25 16:19:08 -07:00
Remco Bloemen
5127cbb22c Return inplace bytes in LibBytes.readBytesWithLength 2018-06-25 16:19:08 -07:00
Remco Bloemen
9175b43542 Add Greg's documentation to MixinErc721Transfer 2018-06-25 16:19:07 -07:00
Remco Bloemen
562fec01d8 Add Greg's documentation to MixinErc20Transfer 2018-06-25 16:19:07 -07:00
Remco Bloemen
b8051c8fed Gas golf the transfer success logic 2018-06-25 16:19:07 -07:00
Remco Bloemen
4df66a4802 Optimize like in PR #767 2018-06-25 16:19:07 -07:00
Amir Bandeali
a2ff63daa5 Run prettier and fix linting errors 2018-06-25 16:19:07 -07:00
Amir Bandeali
7ce0f9682f Fix tests 2018-06-25 16:19:07 -07:00
Remco Bloemen
3c6d0dc3e0 Update tests 2018-06-25 16:19:07 -07:00
Remco Bloemen
64a6fb2344 Fix AssetProxyUtils 2018-06-25 16:19:07 -07:00
Remco Bloemen
07734a5184 Update tests 2018-06-25 16:19:07 -07:00
Remco Bloemen
32d4994219 Fix ERC721Proxy TokenId 2018-06-25 16:19:07 -07:00
Remco Bloemen
08d22d2f3c Update AssetProxyUtils 2018-06-25 16:19:07 -07:00
Remco Bloemen
b7b0185baf Add IAssetData 2018-06-25 16:19:07 -07:00
Remco Bloemen
7b0c13c121 WIP 2018-06-25 16:19:07 -07:00
Remco Bloemen
a98ecc05af ABI encoded asset data 2018-06-25 16:19:07 -07:00
Remco Bloemen
f7337c1a05 Remove proxyId argument from dispatchTransferFrom 2018-06-25 16:19:07 -07:00
fragosti
53e2cda4c8 Remove existing networkId watching logic from BlockchainWatcher 2018-06-25 16:01:26 -07:00
Fabio Berger
8064914bb7 Prettier fixes 2018-06-25 23:17:56 +02:00
Fabio Berger
6bb2203f79 Small stylistic tweaks 2018-06-25 23:07:27 +02:00
Fabio Berger
3d56817da1 Update yarn.lock 2018-06-25 23:00:19 +02:00
Fabio Berger
31e3b9ff8b Fix and imprrove ethLightWalletSubprovider 2018-06-25 22:59:41 +02:00
Fabio Berger
b2e32aaf58 Remove legacy named subprovider 2018-06-25 22:59:24 +02:00
Fabio Berger
699de9174e Format type 2018-06-25 22:59:04 +02:00
Fabio Berger
1dd9ec4d5a Remove duplicate type 2018-06-25 22:58:50 +02:00
Fabio Berger
87d66ccf6c Fix Tslint issues 2018-06-25 22:58:36 +02:00
Fabio Berger
1134ff1075 Fix tslint issues 2018-06-25 20:17:00 +02:00
Fabio Berger
178676ef8c Fix lint errors 2018-06-25 20:08:00 +02:00
Greg Hysen
94740155e5 Comments for ASM hashing 2018-06-25 11:02:31 -07:00
Fabio Berger
9341afe764 Merge pull request #772 from 0xProject/add-coverage-instructions
Improve Contracts README Testing Section
2018-06-25 19:58:15 +02:00
Cavan
7ce1e9b18d Add eth-lightwallet subprovider and tests 2018-06-25 19:39:23 +02:00
Cavan
1821f60fb5 Move eth-lightwallet declaration to typings 2018-06-25 19:08:16 +02:00
Cavan
235d78565e Format subprovider using prettier 2018-06-25 19:06:22 +02:00
Cavan
db5880539b Update changelogs 2018-06-25 19:01:53 +02:00
Cavan
76f4d67f33 Remove timestamps and fix typings 2018-06-25 18:58:25 +02:00
Bryce
e59c57106c Run prettier 2018-06-25 09:44:56 -07:00
Cavan
bb4c748bf1 Formatting and standards updates 2018-06-25 18:42:13 +02:00
perissology
92cb9c3807 add /*solcov ignore next*/ tests 2018-06-25 08:18:02 -07:00
perissology
1a4e99431b support ignoring entire contracts 2018-06-25 07:55:19 -07:00
Fabio Berger
ec9d1ca57e Document all the contract test options in README 2018-06-25 15:18:02 +02:00
Fabio Berger
71c9b98896 Fix revertReason 2018-06-25 14:23:35 +02:00
Fabio Berger
71bac8c60b Update yarn.lock 2018-06-25 13:51:41 +02:00
Fabio Berger
7b0f7c2e5c Remove no longer used method 2018-06-25 13:51:18 +02:00
Fabio Berger
ad67a6add5 Check revert reasons in declarative and combinatorial tests 2018-06-25 13:51:00 +02:00
Fabio Berger
1353723b58 merge check-revert-reasons 2018-06-25 13:02:38 +02:00
Fabio Berger
f811c07454 Move RevertReasons to @0xproject/types package 2018-06-25 12:59:26 +02:00
Fabio Berger
bb85382824 Add missing import 2018-06-25 12:47:44 +02:00
Fabio Berger
3ed4a1ba20 Add missing import 2018-06-25 12:47:13 +02:00
Fabio Berger
c50da5d034 merge check-revert-reasons 2018-06-25 12:32:16 +02:00
Fabio Berger
9b196ba68c Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (97 commits)
  Fix typos in comments
  Add modifier and tests for removeAuthorizedAddressAtIndex
  Update and add tests
  Change removeAuthorizedAddress => removeAuthorizedAddressAtIndex
  Move isFunctionRemoveAuthorizedAddress to test
  Fix usage of `popLastByte`
  Fix LibBytes is a library
  Remove `areBytesEqual`
  Fix usage of `contentAddress()`
  Clean low bits in bytes4
  Clean high bits in address
  Refactor LibBytes.readBytes4 for consistency
  Fix LibBytes.equals
  Add trailing garbage testcase for LibBytes.equals
  Rename bytes.equals
  Add slice and sliceDestructive
  Rename bytes.rawAddress and add bytes.contentAddress
  Rename read/writeBytesWithLength
  Using LibBytes for bytes
  Make LibBytes a library
  ...

# Conflicts:
#	packages/contracts/src/utils/constants.ts
#	packages/contracts/test/exchange/core.ts
2018-06-25 11:49:14 +02:00
Fabio Berger
df79fb19af Merge branch 'v2-prototype' into refactor/check-revert-reasons
* v2-prototype: (48 commits)
  Fix typos in comments
  Add modifier and tests for removeAuthorizedAddressAtIndex
  Update and add tests
  Change removeAuthorizedAddress => removeAuthorizedAddressAtIndex
  Move isFunctionRemoveAuthorizedAddress to test
  Fix usage of `popLastByte`
  Fix LibBytes is a library
  Remove `areBytesEqual`
  Fix usage of `contentAddress()`
  Clean low bits in bytes4
  Clean high bits in address
  Refactor LibBytes.readBytes4 for consistency
  Fix LibBytes.equals
  Add trailing garbage testcase for LibBytes.equals
  Rename bytes.equals
  Add slice and sliceDestructive
  Rename bytes.rawAddress and add bytes.contentAddress
  Rename read/writeBytesWithLength
  Using LibBytes for bytes
  Make LibBytes a library
  ...

# Conflicts:
#	packages/contracts/src/contracts/current/utils/Ownable/Ownable.sol
#	packages/contracts/test/libraries/lib_bytes.ts
2018-06-25 11:45:17 +02:00
Leonid Logvinov
f8bde5ab9b Merge pull request #735 from feuGeneA/metacoin-independence
Metacoin independence
2018-06-25 11:35:24 +02:00
Jacob Evans
0cd37cbf7e Merge pull request #758 from 0xProject/fix/order-utils/known-order-hash
Fix known order hash value test in order-utils
2018-06-25 15:47:07 +10:00
Remco Bloemen
d621e4201d Merge pull request #698 from 0xProject/fix/contracts/using-libbytes
Fixes and refactoring regarding LibBytes
2018-06-23 14:08:40 +02:00
Remco Bloemen
82af1df3c3 Fix typos in comments 2018-06-23 13:55:02 +02:00
Amir Bandeali
ea8c2b8d69 Add modifier and tests for removeAuthorizedAddressAtIndex 2018-06-23 13:53:39 +02:00
Amir Bandeali
8ddcb6c841 Update and add tests 2018-06-23 13:53:39 +02:00
Amir Bandeali
1681361aed Change removeAuthorizedAddress => removeAuthorizedAddressAtIndex 2018-06-23 13:53:39 +02:00
Remco Bloemen
6a6f98299d Move isFunctionRemoveAuthorizedAddress to test 2018-06-23 13:53:39 +02:00
Remco Bloemen
19ba272d62 Fix usage of popLastByte 2018-06-23 13:53:39 +02:00
Remco Bloemen
2f8ceca2ef Fix LibBytes is a library 2018-06-23 13:53:39 +02:00
Remco Bloemen
ba1baafca5 Remove areBytesEqual 2018-06-23 13:53:38 +02:00
Remco Bloemen
20a07494f6 Fix usage of contentAddress() 2018-06-23 13:53:38 +02:00
Remco Bloemen
c66477c690 Clean low bits in bytes4 2018-06-23 13:53:38 +02:00
Remco Bloemen
5c612a186f Clean high bits in address 2018-06-23 13:53:38 +02:00
Remco Bloemen
943e556f43 Refactor LibBytes.readBytes4 for consistency 2018-06-23 13:53:38 +02:00
Remco Bloemen
4bf4f96f47 Fix LibBytes.equals 2018-06-23 13:53:38 +02:00
Remco Bloemen
384cd2f605 Add trailing garbage testcase for LibBytes.equals 2018-06-23 13:53:38 +02:00
Remco Bloemen
425af46f98 Rename bytes.equals 2018-06-23 13:53:38 +02:00
Remco Bloemen
c83ee04662 Add slice and sliceDestructive 2018-06-23 13:53:38 +02:00
Remco Bloemen
2054cd78da Rename bytes.rawAddress and add bytes.contentAddress 2018-06-23 13:53:38 +02:00
Remco Bloemen
88982f98ff Rename read/writeBytesWithLength 2018-06-23 13:53:38 +02:00
Remco Bloemen
2ea0b839d3 Using LibBytes for bytes 2018-06-23 13:53:38 +02:00
Remco Bloemen
afd83e59b8 Make LibBytes a library 2018-06-23 13:53:38 +02:00
Remco Bloemen
7f84049538 Merge LibMem and LibBytes 2018-06-23 13:53:38 +02:00
Remco Bloemen
98840c9c5f Use provided mem in refernce memcpy 2018-06-23 13:53:38 +02:00
Amir Bandeali
26cacfa247 Merge pull request #749 from 0xProject/feature/contracts/transactionHashAsm
Converted `hashZeroExTransaction` to assembly. Saves 1k gas
2018-06-22 16:57:50 -07:00
Bryce Neal
4b2d27b5e5 CHANGELOG spacing 2018-06-22 16:57:49 -07:00
Bryce
69625946b1 Typings and comment 2018-06-22 16:56:19 -07:00
Bryce
f7fe9b0961 Update at abi_decoder 2018-06-22 16:41:47 -07:00
Greg Hysen
7fcd34eb36 Apply mask to address to zero-out unused bytes. 2018-06-22 16:35:50 -07:00
Brandon Millman
1f5848ba82 Remove extra border from the bottom of the wallet 2018-06-22 16:07:07 -07:00
perissology
bbd414bdcd add ability to ignore covering specific code blocks 2018-06-22 15:59:36 -07:00
Brandon Millman
a1737a28d0 Do not render ZRX or WETH as removable tracked tokens 2018-06-22 15:57:34 -07:00
Brandon Millman
66be42d1f8 Center items in portal drawer header 2018-06-22 15:33:58 -07:00
Francesco Agosti
c984c0f2c0 Merge pull request #764 from 0xProject/feature/website/relay-grid-stacking-bug
Fix issue where hovered tiles appear over top bar
2018-06-22 15:16:13 -07:00
fragosti
89d2bb7ecd Fix issue where hovered tiles appear over top bar 2018-06-22 14:32:21 -07:00
Bryce Neal
9f8cad93f7 CHANGELOG spacing 2018-06-22 14:08:21 -07:00
Bryce Neal
a207260fe0 Fix CHANGELOG spacing. 2018-06-22 14:07:19 -07:00
Bryce
1ef4a47255 Fix spacing 2018-06-22 14:06:45 -07:00
Bryce
b8aa68b4d1 Add CHANGELOG entry 2018-06-22 14:05:23 -07:00
Bryce
61edbac6e5 Remove package-lock 2018-06-22 14:02:29 -07:00
Bryce
d315133d34 Re-throw if not INVALID_ARGUMENT 2018-06-22 14:01:14 -07:00
Bryce
82d59dbea8 Address INVALID_ARGUMENT issue 2018-06-22 13:35:49 -07:00
Francesco Agosti
42884e0871 Merge pull request #746 from 0xProject/feature/website/relayer-grid-polish
Relayer grid polish
2018-06-22 13:11:33 -07:00
fragosti
7fb8b546f9 Remove unecessary position relative rules 2018-06-22 12:22:31 -07:00
fragosti
80fe1938b8 Fix tslint error 2018-06-22 12:04:45 -07:00
fragosti
2409afae95 Merge https://github.com/0xProject/0x-monorepo into v2-prototype 2018-06-22 11:54:37 -07:00
fragosti
06705f9e88 Remove diverse from about page 2018-06-22 11:54:24 -07:00
fragosti
2b408e71ac Use Ops instead of Operations in Mels description 2018-06-22 11:47:57 -07:00
Brandon Millman
b097193486 Merge pull request #750 from 0xProject/bug/website/fix-add-token
Various add token flow bugs
2018-06-22 11:43:02 -07:00
Brandon Millman
543f2c91fe Pulled out reset AssetPicker state into a common variable 2018-06-22 11:37:57 -07:00
fragosti
05c0088445 Comment out Chris, and move Mel up in about page 2018-06-22 11:22:33 -07:00
Fabio Berger
2f6f815d81 Fix tslint 2018-06-22 18:54:18 +02:00
Fabio Berger
1e03fbe1a8 Fix prettier 2018-06-22 18:50:02 +02:00
Fabio Berger
4409f11b24 Rename ContractLibErrors to RevertReasons 2018-06-22 18:45:45 +02:00
Fabio Berger
7a216901be Remove revert reason 'Exchange' prefix 2018-06-22 18:41:55 +02:00
Fabio Berger
0e7c254b93 Move constants over to ContractLibError enum and update all tests 2018-06-22 18:36:15 +02:00
Fabio Berger
ba14850c9a Standardize ERC20 error strings given convention 2018-06-22 18:35:35 +02:00
Fabio Berger
59d3a21993 Fix test now that contract reverts with message 2018-06-22 17:39:41 +02:00
Fabio Berger
d2faa49bf4 Merge branch 'v2-prototype' into refactor/check-revert-reasons
* v2-prototype:
  Check that assetProxy exists before attempting transfer
2018-06-22 17:15:51 +02:00
Fabio Berger
438c0e27ea Merge pull request #748 from 0xProject/fix/contracts/nullAssetProxy
Check that assetProxy exists before attempting transfer
2018-06-22 17:14:22 +02:00
Fabio Berger
4c14372b4a Add revert reason checks to wrapper tests 2018-06-22 17:12:52 +02:00
Fabio Berger
8b4077d7de Fix tests 2018-06-22 17:12:31 +02:00
Fabio Berger
914b009361 Change Whitelist error messages to conform to rest and added revert reason checks to transactions tests 2018-06-22 17:12:17 +02:00
Jacob Evans
b2a4b7eb88 Fix known order hash value test 2018-06-22 23:00:22 +10:00
Fabio Berger
daa50442c9 Add revert reason checks to match_orders tests 2018-06-22 14:28:01 +02:00
Fabio Berger
76fd7f47eb Fix tests 2018-06-22 14:13:44 +02:00
Fabio Berger
fbf840cb68 Merge branch 'v2-prototype' into refactor/check-revert-reasons
* v2-prototype:
  Update ganache-core in yarn.lock
  Add coverage and test:circleci command to sra-report
  Add missing artifacts
  Skip failing tests temporarily
  Fix web3-wrapper test
  fix name
  Add missing package tests from circleci
2018-06-22 13:26:59 +02:00
Fabio Berger
798a647b71 Merge pull request #757 from 0xProject/fix/circle-ci
Add missing package tests from circleci
2018-06-22 13:26:12 +02:00
Fabio Berger
26a0b09064 Update ganache-core in yarn.lock 2018-06-22 13:12:55 +02:00
Fabio Berger
98570b5da1 Add coverage and test:circleci command to sra-report 2018-06-22 12:50:52 +02:00
Fabio Berger
e923d7dafb Add missing artifacts 2018-06-22 12:33:23 +02:00
Fabio Berger
64b6861880 Skip failing tests temporarily 2018-06-22 12:33:10 +02:00
Fabio Berger
c46e11cae2 Fix web3-wrapper test 2018-06-22 12:32:12 +02:00
Fabio Berger
82ccfa21e1 fix name 2018-06-22 12:02:40 +02:00
Fabio Berger
13f7fc1fd2 Add missing package tests from circleci 2018-06-22 11:59:14 +02:00
Fabio Berger
018cc14a87 Fix expected version in test 2018-06-22 10:47:38 +02:00
Fabio Berger
3ce295a2af Merge branch 'v2-prototype' into refactor/check-revert-reasons
* v2-prototype: (40 commits)
  Use make-promises-safe as a preloader instead of manually importing
  Updated compiler runs to be 1,000,000
  Add event to setSignatureValidatorApproval, rename signer => signerAddress accross all contracts
  Add senderAddress to Fill and Cancel logs, add comments to events and types
  Fix Island component
  Add missing image assets for Chris and Mel
  Fix some bugs in sol-cov
  Remove unreachable PreSigned check
  Fix linting
  Buttons look hella disabled now
  Remove border radius, fix width issue for unlock step
  Add Chris and Mel to about page
  fix linter issues
  only call getLocationByOffset if source if defined
  Set settleOrder and settleMatchedOrders to private
  Prevent prettier issue
  Support mobile friendly onboarding flows
  Removed MixinSettlement. Moved `settleOrder` into `MixinExchangeCore` and `settleMatchedOrders` into `MixinMatchOrders`
  Migrations after rebasing
  Linter
  ...
2018-06-22 10:39:07 +02:00
Fabio Berger
a30107ab86 Check revert reason in dispatcher tests 2018-06-22 10:38:08 +02:00
Fabio Berger
d8df6968d3 remove unused import 2018-06-22 10:37:25 +02:00
Fabio Berger
0515c6acde Merge pull request #752 from 0xProject/make-promises-safe-preloader
Use make-promises-safe as a preloader instead of manually importing
2018-06-22 10:32:06 +02:00
Amir Bandeali
607b44e01d Check that assetProxy exists before attempting transfer 2018-06-21 22:45:15 -07:00
Amir Bandeali
5c0bae2070 Merge pull request #751 from 0xProject/feature/contracts/compilerRuns
Updated compiler runs to be 1,000,000
2018-06-21 22:06:31 -07:00
Alex Browne
4012e31115 Use make-promises-safe as a preloader instead of manually importing 2018-06-21 19:17:33 -07:00
Greg Hysen
2d8e9eda56 Converted hashZeroExTransaction to assembly. Saves 1k gas 2018-06-21 18:49:17 -07:00
Brandon Millman
4375a0e07e Fix state mutation in reducer 2018-06-21 18:06:34 -07:00
Brandon Millman
a07cfb7abc Do not add empty token to local storage 2018-06-21 18:06:34 -07:00
Greg Hysen
c131d82699 Updated compiler runs to be 1,000,000 2018-06-21 17:58:39 -07:00
fragosti
de2dcbae5a Lint and fix typo 2018-06-21 17:42:37 -07:00
fragosti
b0000bb276 Fix z-index issues 2018-06-21 17:40:33 -07:00
fragosti
82789d5315 Fix issues that arose from merge 2018-06-21 17:40:33 -07:00
Brandon Millman
3df5882711 Remove Background component 2018-06-21 17:40:33 -07:00
Brandon Millman
b6765b849c Padding adjustment 2018-06-21 17:40:33 -07:00
Brandon Millman
df94e5f164 Remove styles from Portal component 2018-06-21 17:40:33 -07:00
Brandon Millman
79edc12c76 Add Background component 2018-06-21 17:40:33 -07:00
Brandon Millman
bd03151c2a Various relayer grid ui polish items 2018-06-21 17:40:33 -07:00
Amir Bandeali
7c0fdc7ecf Merge pull request #740 from 0xProject/feature/contracts/updateEvents
Update events
2018-06-21 17:14:14 -07:00
Amir Bandeali
b333ed91de Add event to setSignatureValidatorApproval, rename signer => signerAddress accross all contracts 2018-06-21 16:10:12 -07:00
Amir Bandeali
6a073d5f86 Add senderAddress to Fill and Cancel logs, add comments to events and types 2018-06-21 16:09:38 -07:00
Alex Browne
c7159b2be4 Merge pull request #747 from 0xProject/fix/sol-cov-bugs
Fix some bugs in sol-cov
2018-06-21 13:50:30 -07:00
Amir Bandeali
2d98193c83 Merge pull request #744 from NoteGio/v2-prototype-unreachable
Remove unreachable PreSigned check
2018-06-21 13:38:23 -07:00
fragosti
685756f9d5 Fix Island component 2018-06-21 13:26:33 -07:00
fragosti
535bb364b6 Add missing image assets for Chris and Mel 2018-06-21 13:17:51 -07:00
Francesco Agosti
c740539f48 Merge pull request #739 from 0xProject/feature/website/mobile-friendly-onboarding
Add support for mobile-friendly onboarding flows
2018-06-21 13:16:13 -07:00
Alex Browne
4cf331067b Fix some bugs in sol-cov 2018-06-21 13:14:13 -07:00
Austin Roberts
a3ba7683f4 Remove unreachable PreSigned check
This code was unreachable, as it had the exact same condition as line 206.
2018-06-21 14:15:20 -05:00
fragosti
5edfec68cf Fix linting 2018-06-21 12:12:44 -07:00
fragosti
eb494f78fa Buttons look hella disabled now 2018-06-21 12:09:38 -07:00
fragosti
d963941be0 Remove border radius, fix width issue for unlock step 2018-06-21 11:33:47 -07:00
Francesco Agosti
8ab65fdde4 Merge pull request #742 from 0xProject/feature/website/chris-mel-about-page
Add Chris and Mel to about page
2018-06-21 11:32:10 -07:00
fragosti
8e2c0bb977 Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/mobile-friendly-onboarding 2018-06-21 11:06:53 -07:00
fragosti
f1f1064f70 Add Chris and Mel to about page 2018-06-21 10:57:26 -07:00
Brandon Millman
88500e3714 Merge pull request #734 from 0xProject/feature/website/shadow-styling
Update Island shadow styling and use Island in more places
2018-06-21 10:31:48 -07:00
Leonid Logvinov
eae2a4df8b Merge pull request #702 from perissology/feature/missing-sources
[sol-cov] Only collect coverage for provided sources
2018-06-21 19:28:35 +02:00
perissology
ade8e95d2e fix linter issues 2018-06-21 09:12:30 -07:00
Fabio Berger
a0b225b8b1 Test revert reasons in proxy tests 2018-06-21 17:43:48 +02:00
Fabio Berger
323e8756ba remove only 2018-06-21 17:27:26 +02:00
Fabio Berger
ada5428df7 Check revert reasons in Authorizable tests 2018-06-21 17:23:59 +02:00
Fabio Berger
7869c19245 Change revert reason in ownable to be similar to all other revert reasons 2018-06-21 17:23:42 +02:00
Fabio Berger
5706b29c8c remove .only 2018-06-21 17:06:44 +02:00
Fabio Berger
8ff7b2405f Update yarn.lock 2018-06-21 16:53:14 +02:00
Fabio Berger
eaabe15863 Update core tests to actually check revert message 2018-06-21 16:53:05 +02:00
Fabio Berger
63b2ae743b Add command to remove all node_modules, nested and hoisted 2018-06-21 16:52:01 +02:00
perissology
c5ea985a70 only call getLocationByOffset if source if defined 2018-06-21 06:24:50 -07:00
Remco Bloemen
11b35b89f5 Merge pull request #692 from 0xProject/refactor/contracts/RemovedMixinSettlement
Removed MixinSettlement
2018-06-21 13:26:40 +02:00
Greg Hysen
6d5b16725d Set settleOrder and settleMatchedOrders to private 2018-06-20 17:27:45 -07:00
fragosti
c34897036e Prevent prettier issue 2018-06-20 16:05:19 -07:00
fragosti
1e51af1d4b Support mobile friendly onboarding flows 2018-06-20 15:51:17 -07:00
Greg Hysen
8ee6e26608 Removed MixinSettlement. Moved settleOrder into MixinExchangeCore and settleMatchedOrders into MixinMatchOrders 2018-06-20 15:36:28 -07:00
Brandon Millman
4d36f38f96 Merge pull request #733 from 0xProject/bug/website/identicon-layout
Move some layout logic out of the Identicon component
2018-06-20 15:25:51 -07:00
Greg Hysen
d31ca444e1 Merge pull request #736 from 0xProject/feature/contracts/MixinSignatureValidatorTests
MixinSignatureValidator Test Cases + Bug Fixes
2018-06-20 14:18:13 -07:00
Greg Hysen
090b3014c0 Migrations after rebasing 2018-06-20 14:00:21 -07:00
Greg Hysen
491a322ceb Linter 2018-06-20 13:54:39 -07:00
Greg Hysen
12e16d532b Renamed constants in test wallet/validator 2018-06-20 13:54:39 -07:00
Greg Hysen
7814a391d8 Few more minor #nit wording changes 2018-06-20 13:54:39 -07:00
Greg Hysen
322151b0d5 Changed wording of two tests #nit 2018-06-20 13:54:39 -07:00
Greg Hysen
4a136cafda Minor improvements to MixinSignatureValidator tests 2018-06-20 13:54:39 -07:00
Greg Hysen
d0df25d9e2 Remove .only 2018-06-20 13:54:39 -07:00
Greg Hysen
8d003dbc30 Fixed two mislabelled revert reasons + Signature Validator revert tests working on Geth 2018-06-20 13:54:39 -07:00
Greg Hysen
2c7358d64f Minor style tweaks 2018-06-20 13:54:39 -07:00
Greg Hysen
94e260cec6 Fixed how trezor messages are signed in signature_utils. Now uses byteLength instead of length. 2018-06-20 13:54:39 -07:00
Greg Hysen
783ac3c105 Fixed callAsync template. Previously did not append callData, so we couldn’t specify from address 2018-06-20 13:54:39 -07:00
Greg Hysen
d46e3f6778 Twenty new tests for MixinSignatureValidator. Fixed handling of unsupported types. Fixed trezor prefix. 2018-06-20 13:54:39 -07:00
Alex Browne
6fe3158778 Merge pull request #725 from 0xProject/feature/revert-trace-code-snippets
Include source code snippets in revert stack traces
2018-06-20 12:36:04 -07:00
Alex Browne
bbd12e33ec Update version for @types/solidity-parser-antlr 2018-06-20 12:22:39 -07:00
Alex Browne
e4d55242d8 Update to match latest type definitions and other small changes 2018-06-20 12:22:39 -07:00
Alex Browne
dedddcfcf5 Update sol-cov CHANGELOG.json 2018-06-20 12:22:39 -07:00
Alex Browne
613a78bcf6 Include source code snippets in revert stack traces 2018-06-20 12:19:30 -07:00
Alex Browne
f5decb1d7e Merge pull request #738 from 0xProject/fix/changelogs
Fix CHANGELOG entries changed during incorrect merge (2a4456b)
2018-06-20 12:19:04 -07:00
Fabio Berger
47b4c236c3 Fix CHANGELOG entries changed during incorrect merge (2a4456b) 2018-06-20 20:29:22 +02:00
fragosti
39ccb2df0b Scroll to wallet for mobile onboarding 2018-06-20 11:25:59 -07:00
Fabio Berger
5bfdffda11 Add support for approveAll in assetWrapper and fillOrderScenarios 2018-06-20 19:14:04 +02:00
Fabio Berger
247f8c8557 Fix orderValidationUtils where was confusing a makerAssetAmount as a takerAssetAmount 2018-06-20 19:13:30 +02:00
Fabio Berger
3ce449e167 Improve verbose logging 2018-06-20 19:12:31 +02:00
F. Eugene Aumson
663f9657ea ethereum-types now only has v0.0.2, no 0.0.1 2018-06-20 09:06:38 -04:00
F. Eugene Aumson
457f951aaf add missing metacoin dependencies 2018-06-20 09:06:38 -04:00
F. Eugene Aumson
feafd57027 make metacoin tsconfig independent 2018-06-20 09:06:32 -04:00
Fabio Berger
5c0183c71e Fix merge variable name issue 2018-06-20 14:08:56 +02:00
Fabio Berger
fb7d425244 Add support for setting allowance to unlimited 2018-06-20 13:56:27 +02:00
Fabio Berger
3fab40efe5 Add noop conditionals for clarity 2018-06-20 13:55:45 +02:00
Fabio Berger
0bbdbc9e63 Rename for clarity 2018-06-20 13:55:28 +02:00
Fabio Berger
9bc481ff62 Split balance and allowance amount types in prep of adding the "unlimited" allowance enum value 2018-06-20 13:36:57 +02:00
Fabio Berger
32dea43d2e Remove unneeded explicit type def 2018-06-20 13:31:57 +02:00
Fabio Berger
632da71a8d Add TS 2.7 numeric separators to improve readability 2018-06-20 13:31:21 +02:00
Fabio Berger
2ffab22185 Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (22 commits)
  Fix closing parens in liborder
  Update after rebase
  ERC721Proxy Always call safeTransferFrom
  Rename makerEpoch => orderEpoch
  Make cancelOrdersUpTo compatible with sender abstraction
  Update PR template
  Use Image component instead of img tag
  Assembler orderHash function
  Optimize and remove redundant encodePacked
  Fix linting issue
  Fix bug where we do fetch balances on wallet login
  Check network state immediately instead of waiting for delay
  Fix onboarding persisting when changing routes
  Consolidate account state messaging logic
  Only elevate wallet zIndex when onboarding is in progress
  Rebase and update feedback
  Run linter
  Add Portal v2 logging
  Simplified handling of source < 32 edge case
  Basic EIP712 encoder
  ...
2018-06-20 13:25:29 +02:00
Fabio Berger
5541327968 Add ability for verbose logging 2018-06-20 13:24:09 +02:00
Jacob Evans
096eaa20d7 Merge pull request #637 from 0xProject/bug/contracts/eip712-191-prefix
Add missing EIP191 prefix for EIP712 and Execute Transaction
2018-06-20 10:54:51 +10:00
fragosti
e5fe6b915e Change Island to use styled-components 2018-06-19 17:32:01 -07:00
Jacob Evans
512bd84cc2 Fix closing parens in liborder 2018-06-20 10:27:45 +10:00
Jacob Evans
ebbcbeedd2 Merge pull request #730 from 0xProject/bug/contracts/eip712-191-prefix-asm-orderhash
Assembler orderHash function
2018-06-20 10:25:31 +10:00
Jacob Evans
be17308e50 Merge pull request #717 from 0xProject/feature/contracts/erc721proxy-always-safeTransferFrom
ERC721Proxy Always call safeTransferFrom
2018-06-20 10:24:12 +10:00
Jacob Evans
25fa29e6e1 Update after rebase 2018-06-20 10:01:41 +10:00
Jacob Evans
bddc47f9b2 ERC721Proxy Always call safeTransferFrom 2018-06-20 10:00:59 +10:00
fragosti
51948d7760 Show start onboarding flow button on top of wallet on mobile 2018-06-19 16:39:52 -07:00
Brandon Millman
5817a30031 Update Island shadow styling and use Island in more places 2018-06-19 16:25:43 -07:00
Amir Bandeali
e216eb1e7b Merge pull request #714 from 0xProject/feature/contracts/cancelOrdersUpToSender
Make cancelOrdersUpTo compatible with sender abstraction
2018-06-19 15:23:28 -07:00
Brandon Millman
549c6afa0a Move some layout logic out of the Identicon component 2018-06-19 13:55:29 -07:00
Amir Bandeali
6b08e6b809 Rename makerEpoch => orderEpoch 2018-06-19 13:52:23 -07:00
Francesco Agosti
0438fdde49 Merge pull request #724 from 0xProject/bug/website/onboarding-improvements
Fix Wallet appearing over Drawer, and Onboarding not exiting when changing routes
2018-06-19 13:47:52 -07:00
Francesco Agosti
be4ea18119 Merge pull request #727 from 0xProject/bug/website/fix-fetching-balances-on-wallet-login
Fix bug where we do not fetch balances on wallet login
2018-06-19 13:43:08 -07:00
fragosti
a75d6531f2 Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into bug/website/onboarding-improvements 2018-06-19 13:29:54 -07:00
Brandon Millman
da69ddc19b Merge pull request #732 from 0xProject/feature/update-pr-template
Update PR template
2018-06-19 13:16:42 -07:00
Amir Bandeali
e92926e881 Make cancelOrdersUpTo compatible with sender abstraction 2018-06-19 13:04:55 -07:00
Brandon Millman
7dd208fb49 Merge pull request #723 from 0xProject/bug/website/drawer-address
Consolidate account state display message logic
2018-06-19 10:44:18 -07:00
Brandon Millman
5305db689d Update PR template 2018-06-19 10:41:27 -07:00
Francesco Agosti
2338c7a3b3 Merge pull request #706 from 0xProject/feature/website/portal-v2-analytics
Add logging to Portal V2
2018-06-19 10:32:35 -07:00
Brandon Millman
829bc96209 Use Image component instead of img tag 2018-06-19 10:30:28 -07:00
fragosti
7454e16aae Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/portal-v2-analytics 2018-06-19 10:19:38 -07:00
Brandon Millman
e4acad60e9 Merge pull request #726 from 0xProject/bug/website/late-eth-balance
Check network state immediately instead of waiting for delay
2018-06-19 10:03:08 -07:00
Fabio Berger
f35af1fb6d Fix typo 2018-06-19 17:53:16 +02:00
Fabio Berger
c0e008c601 Rename NewOrderFactory to OrderFactoryFromScenario for clarity 2018-06-19 17:41:10 +02:00
Fabio Berger
9acf4458c0 Remove hack in ERC20Wrapper 2018-06-19 17:38:15 +02:00
Fabio Berger
70de264d4d Cleanup coreCombinatorialUtils 2018-06-19 17:31:26 +02:00
Fabio Berger
1a0b9e4612 Comments and cleanup 2018-06-19 17:25:08 +02:00
Remco Bloemen
66dc70c057 Merge pull request #683 from 0xProject/fix/contracts/memcpy
Simplified handling of source < 32 edge case
2018-06-19 13:53:25 +02:00
Fabio Berger
6641f34d76 Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype:
  Prettier fix
  Update default params in sendRawPaylodAsync for improved JSON-RPC compatibility
  Fix missed merge conflicts
  Fix additional versions and update yarn.lock
  Add OrderWatcherConfig type to 0x.js docs page
  Export OrderWatcherConfig from 0x.js
  Update all package versions to match latest published to NPM
  Update CHANGELOG's with publishes performed on development branch
  Rebase with latest removing PROXY_ID from transfer
  Split transfer impl and AssetProxyMixin
  change @0xproject/types to ethereum-types
  remove mistaken comment
  workaround for TypeScript trailing comma bug
  Document contract_templates
2018-06-19 13:48:58 +02:00
Fabio Berger
f3ae5d8160 Prettier fix 2018-06-19 13:46:39 +02:00
Fabio Berger
d937541aa0 Merge pull request #701 from feuGeneA/v2-prototype
Document use of contract_templates (take 2; based on v2-prototype, not master)
2018-06-19 13:44:55 +02:00
Fabio Berger
21707d7ff6 Merge pull request #728 from 0xProject/fix/post-dev-publish
Update v2-prototype w/ development changes since publish
2018-06-19 13:18:36 +02:00
Leonid Logvinov
3002bc0eee Merge pull request #731 from avonian/v2-prototype
Fix sendRawPaylodAsync for improved JSON-RPC compatibility
2018-06-19 13:17:20 +02:00
Ara Kevonian
df50232ed9 Update default params in sendRawPaylodAsync for improved JSON-RPC compatibility 2018-06-19 04:13:32 -07:00
Fabio Berger
17d49067e9 Fix missed merge conflicts 2018-06-19 12:56:22 +02:00
Remco Bloemen
9a2e023a51 Assembler orderHash function 2018-06-19 12:55:04 +02:00
Jacob Evans
9c747f3160 Merge pull request #659 from 0xProject/feature/contracts/split-proxy-internal-logic
Split transfer implementation and AssetProxyMixin
2018-06-19 20:41:06 +10:00
Fabio Berger
08ea71cb24 Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (40 commits)
  Increase number of columns in relayer grid for small screens
  Make isValidSignature public
  Make batchFill methods return FIllResults struct
  Remove remove_tags script
  Small fixes
  Use semver package instead of getNextPatchVersion
  Use semver library instead of semverUtils
  small fixes
  Show all errors of a given kind at once rather then throwing after the first instance is encountered
  fix package.json
  Add more prepublish checks
  remove remove_tags script
  Create a shared Image component
  Adjust version in changelog
  Update RelayerGridTile render logic to incorportate colors and logos
  Add max width to top bar
  Set max-width for LargeLayout
  Finish last onboarding step
  Finish set allowance step
  Add onboarding assets
  ...
2018-06-19 12:35:32 +02:00
Fabio Berger
a96abe2422 Fix additional versions and update yarn.lock 2018-06-19 12:32:43 +02:00
Fabio Berger
84a4a888e6 Add OrderWatcherConfig type to 0x.js docs page 2018-06-19 11:34:44 +02:00
Fabio Berger
e3299b546e Export OrderWatcherConfig from 0x.js 2018-06-19 11:33:46 +02:00
Fabio Berger
f2e0f1b2f1 Update all package versions to match latest published to NPM 2018-06-19 11:32:55 +02:00
Fabio Berger
2a4456b9ca Update CHANGELOG's with publishes performed on development branch 2018-06-19 11:16:30 +02:00
Jacob Evans
560a55bfd1 Optimize and remove redundant encodePacked 2018-06-19 17:32:17 +10:00
fragosti
d32f0fad12 Fix linting issue 2018-06-18 18:56:31 -07:00
fragosti
031e7d270d Fix bug where we do fetch balances on wallet login 2018-06-18 18:08:38 -07:00
Brandon Millman
3b73a0e269 Check network state immediately instead of waiting for delay 2018-06-18 18:01:38 -07:00
fragosti
bdd299dd9e Fix onboarding persisting when changing routes 2018-06-18 17:24:31 -07:00
Brandon Millman
f97e605bf6 Consolidate account state messaging logic 2018-06-18 17:08:44 -07:00
fragosti
db9ff76754 Only elevate wallet zIndex when onboarding is in progress 2018-06-18 16:57:28 -07:00
Jacob Evans
190eafc30e Merge branch 'v2-prototype' into bug/contracts/eip712-191-prefix 2018-06-18 21:50:35 +10:00
Jacob Evans
d4ee0e8622 Rebase and update feedback
Cache the domain separator data with address this
Use the EIP712Types enum for types everywhere
Rename EIP712 struct ExecuteTransaction to ZeroExTransaction
2018-06-18 21:46:05 +10:00
Jacob Evans
96c90e6295 Rebase with latest removing PROXY_ID from transfer 2018-06-18 16:36:30 +10:00
Jacob Evans
ff95da411b Split transfer impl and AssetProxyMixin 2018-06-18 15:24:12 +10:00
F. Eugene Aumson
8bac1706a1 change @0xproject/types to ethereum-types 2018-06-15 10:37:37 -04:00
fragosti
2cc7289b7b Merge branch 'v2-prototype' of https://github.com/0xProject/0x-monorepo into feature/website/portal-v2-analytics 2018-06-14 15:50:46 -07:00
fragosti
81d6df925e Run linter 2018-06-14 15:47:59 -07:00
fragosti
677e77d0ae Add Portal v2 logging 2018-06-14 15:43:10 -07:00
Fabio Berger
0d0c1af7f7 Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype:
  Run prettify
  Implement allowance and final flow step
  Render TokenAllowance
  Add utilities for getting tokens from tokensByAddress
  Wrap AllowanceToggle in redux container
2018-06-15 00:03:47 +02:00
Fabio Berger
fb55def54f Add ability to tweak the relevant balances/allowances for the maker and taker for a fillScenario. Convert more of the core tests to the declarative form. 2018-06-15 00:03:00 +02:00
Fabio Berger
eea86757d5 - Refactor assetWrapper to contain more of the normalizing logic instead of erc20Wrapper and erc721Wrapper
- Add burn method to DummyERC721Token
- Add additional methods to assetWrapper to set balance/allowances on ERC20 and ERC721 tokens
- Use approve instead of approveAll for ERC721 tokens
2018-06-15 00:00:02 +02:00
perissology
7a41a5249f Collect coverage for provided sources
When solidity generates source maps during contract compilation, the
contracts are referred to by an id, which corresponds to an array index.

We may not want to cover all sources that were included in a compilation,
but because we use array indexes (vs. the id that is provided by solidity
compiler) to map the contract to the sourceMap, the provided sourceCodes
array must include the code at the correct index. This can result in
empty slots in the sourceCodes array.

This commit allows the coverage to only be collected for the contracts
with provided sourceCode.
2018-06-14 11:17:04 -07:00
F. Eugene Aumson
f9e05d0cad remove mistaken comment
It must have been left over from when an abi-gen output was modified to
be the source of this template.
2018-06-14 13:52:10 -04:00
F. Eugene Aumson
15a63c4bc5 workaround for TypeScript trailing comma bug
before this change, TypeScript compilation of the generated contract
wrapper was giving me the following errors:

$ abi-gen --abis 'build/contracts/*.json' --out build/types --template contract_templates/contract.handlebars --partials 'contract_templates/partials/*.handlebars'
Found 7 partial templates
Found 1 ABI files
Processing: Migrations...
Created: build/types/migrations.ts
$ tsc
build/types/migrations.ts(81,23): error TS1013: A rest parameter or binding pattern may not have a trailing comma.
build/types/migrations.ts(108,23): error TS1013: A rest parameter or binding pattern may not have a trailing comma.
build/types/migrations.ts(130,23): error TS1013: A rest parameter or binding pattern may not have a trailing comma.
build/types/migrations.ts(146,25): error TS1013: A rest parameter or binding pattern may not have a trailing comma.
build/types/migrations.ts(173,25): error TS1013: A rest parameter or binding pattern may not have a trailing comma.
build/types/migrations.ts(195,25): error TS1013: A rest parameter or binding pattern may not have a trailing comma.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Here is the generated code around the first error:

74:    public setCompleted = {
75:        async sendTransactionAsync(
76:            completed: BigNumber,
77:            txData: Partial<TxData> = {},
78:        ): Promise<string> {
79:            const self = this as any as MigrationsContract;
80:            const inputAbi = self._lookupAbi('setCompleted(uint256)').inputs;
81:            [completed,
82:    ] = BaseContract._formatABIDataItemList(inputAbi, [completed,
83:    ], BaseContract._bigNumberToString.bind(self));

All of the other errors are the same, a destructuring assignment with a
single element but with a trailing comma.

This is legal JavaScript but it is not allowed by the TypeScript
compiler, apparently per the bug described at
https://github.com/Microsoft/TypeScript/issues/24628 .

While awaiting the 3.0 version of TypeScript, it's a simple enough
change to have the template not append a trailing comma.
2018-06-14 13:51:18 -04:00
F. Eugene Aumson
4a2e4d2b55 Document contract_templates 2018-06-14 13:51:10 -04:00
Fabio Berger
12033abe09 Rename OrderAmountScenario to OrderAssetAmountScenario and convert generateOrderCombinations to generateFillOrderCombinations 2018-06-14 12:07:57 +02:00
Fabio Berger
f9410d5d00 Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (27 commits)
  Add back redirector behind feature flag
  Update minHeight in Text
  Use Text components in Values
  Use spread operator instead of React.createElement
  Fix issue with positions hash
  Revert localhost config
  Use Text in Teams
  Use Text in OpenPositions
  Use Text component for HeaderItem
  Remove FloatingImage
  Move FilledImage into components/ui
  Replace FlatButton with Button in Retry
  Fix incorrect colors
  Add font family to Button component and use in Join0x component
  Consolidate jobs page grey colors with shared colors
  Fix lint errors
  Remove extra packages
  Implement small open positions
  Implement large screen open positions
  Teams section
  ...
2018-06-14 11:17:58 +02:00
Fabio Berger
c232a32991 Use a defaultFillScenario in fillOrder tests 2018-06-14 11:17:13 +02:00
Fabio Berger
57f37939d5 Fix incorrect string values in enum 2018-06-14 11:16:51 +02:00
Fabio Berger
432ff58107 Fix calculation of expFilledTakerAmount and expected values in events emitted 2018-06-14 11:16:32 +02:00
Fabio Berger
d31b051fc5 Replace initial set of legacy manually written fillOrder tests with declarative FillScenario tests 2018-06-14 10:41:04 +02:00
Fabio Berger
98405a39db Add ability to specify takerAssetFillAmount and taker scenarios as part of a FillScenario 2018-06-14 10:40:17 +02:00
Fabio Berger
6239686afa Fix divide by zero bug 2018-06-13 18:36:30 +02:00
Fabio Berger
45186b70ec Move orderFill combinatorialTests to exchange folder 2018-06-13 16:14:48 +02:00
Fabio Berger
b4fead9606 Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (26 commits)
  Rename _coverageCollector -> _profilerCollector in TraceCollectionSubprovider
  Refactor sol-cov to de-duplicate code for coverage and profiling
  Rename popByte and popAddress
  Hard code test addresses/bytes32 instead of generating pseudorandom ones
  Update artifacts
  Rename computeCoverageAsync -> computeSingleTraceCoverageAsync
  Fix linter errors
  Refactor sol-cov to avoid keeping traceInfo in memory
  Unpop byte rather than making deep copy
  Pass gas in to marketBuyOrdersNoThrow
  Looks up the memory location of makerAssetData/takerAssetData
  Make ZRX_PROXY_ID constant rather than popping it from ZRX_ASSET_DATA
  Add tests for deepCopyBytes and missing write methods from LibBytes
  Pop id from assetData before dispatching to AssetProxies
  Upgrade solidity-parser-entlr 0.2.11 => 0.2.12
  Fix import order
  Fix typos
  Add CHANGELOGs
  Speed-up sol-cov
  Increase delay when sending transactions during devnet startup
  ...
2018-06-13 16:10:05 +02:00
Fabio Berger
61243b418e Implement initial set of orderFill combinatorial tests 2018-06-13 16:09:04 +02:00
Fabio Berger
fe75660e88 Refactor ERC20 and ERC721 wrappers for V2 and introduce the assetWrapper superset 2018-06-13 16:01:01 +02:00
Fabio Berger
946e6c1644 Remaining refactors of order-utils components for V2 2018-06-13 13:20:13 +02:00
Fabio Berger
3eb232b3fc For some reason order-watcher tests were timeing out so I increased the timeout limit 2018-06-13 13:18:19 +02:00
Fabio Berger
38de1c9a31 Remove comment since we have added the tests 2018-06-13 13:16:22 +02:00
Fabio Berger
78dcb87a75 Variable rename for clarity 2018-06-13 13:11:45 +02:00
Fabio Berger
7e78f5941a Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (68 commits)
  Stop exporting ArtifactWriter
  Fix no-unused-variable tslint rule to include parameters and fix issues
  Fix linter exclude rule
  Validate all signature types rather then only ECSignatures
  Store the instantiated OrderValidationUtils
  Remove global hooks from tests and deploy contracts from within the specific tests
  Add EmitStatement to ASTVisitor
  Fix tslint issues
  Add back artifacts file
  Fix a bug in SolCompilerArtifacts adapter config overriding
  Move OrderValidationUtils (+ tests) and ExchangeTransferSimulator to order-utils
  export parseECSignature method
  Export ArtifactWriter from migrations package
  Remove unused artifact file
  Pass in generated contract wrapper to orderValidationUtils at instantiation
  Refactor orderValidationUtils to use the generated contract wrapper instead of the higher-level one
  Refactor ExchangeTransferSimulator public interface to accet an AbstractBalanceAndProxyAllowanceLazyStore so that this module could be re-used in different contexts.
  Increase timeout for contract migrations
  Remove some copy-paste code
  Await transactions in migrations
  ...
2018-06-12 00:23:48 +02:00
Remco Bloemen
82d1412d45 Simplified handling of source < 32 edge case 2018-06-11 09:19:52 +02:00
Jacob Evans
a8d328bfc9 Basic EIP712 encoder 2018-06-07 16:09:30 -07:00
Fabio Berger
20f9318597 Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype:
  Fix linter issue
  Fix linter issue
  Fix tslint issues
  Fix missing paths
  Fixed path
  Use source-map-support package to include correct line numbers in mocha
  move generated contract wrappers from `contract_wrappers/generated/` to `generated_contract_wrappers` in package with no non-generated contract wrappers
2018-06-07 21:45:48 +02:00
Fabio Berger
b646c84414 Merge branch 'fix/order-utils/remaining-v2-changes' into feature/combinatorial-testing
* fix/order-utils/remaining-v2-changes:
  Fix tslint failure
  Pass in fee and assetAmount rather then the whole signedOrder
2018-06-07 18:52:14 +02:00
Fabio Berger
7b7664bd66 Merge branch 'fix/order-utils/remaining-v2-changes' into feature/combinatorial-testing
* fix/order-utils/remaining-v2-changes:
  Revert to returning orderState on invalid order
  - Refactor remainingFillableCalculator so it can be used for the maker and taker side - Moved the tests over from order-watcher - Did some token -> asset renaming
  Update naming in orderStateUtils to use asset over token, also removed cancelledAmount since in V2 it's binary.
2018-06-07 18:22:00 +02:00
Fabio Berger
ab5e021bda POC: Generates an order from spec, get's the amount fillable 2018-06-07 18:00:13 +02:00
Fabio Berger
0fc9814004 merge v2-prototype 2018-06-07 12:18:53 +02:00
Fabio Berger
e617da3bbf Implement initial generateOrder function that given the scenario values for an order, generates the actual order. 2018-06-06 22:13:50 +02:00
Jacob Evans
a59e9f024e Update Order utils to use eip712 2018-06-05 14:08:04 -07:00
Jacob Evans
4670cc1a5f Add missing EIP191 prefix for EIP712 2018-06-04 17:41:00 -07:00
713 changed files with 29755 additions and 13816 deletions

View File

@@ -53,9 +53,9 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
# HACK(albrow): we need to sleep 15 seconds to ensure the devnet is
# HACK(albrow): we need to sleep 10 seconds to ensure the devnet is
# initialized
- run: sleep 15 && TEST_PROVIDER=geth yarn wsrun test contracts
- run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test contracts
test-rest:
docker:
- image: circleci/node:9
@@ -64,31 +64,41 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0xproject/contract-wrappers
- run: yarn wsrun test:circleci @0xproject/sol-compiler
- run: yarn wsrun test:circleci @0xproject/0x.js
- run: yarn wsrun test:circleci @0xproject/assert
- run: yarn wsrun test:circleci @0xproject/base-contract
- run: yarn wsrun test:circleci @0xproject/connect
- run: yarn wsrun test:circleci @0xproject/contract-wrappers
- run: yarn wsrun test:circleci @0xproject/dev-utils
- run: yarn wsrun test:circleci @0xproject/json-schemas
- run: yarn wsrun test:circleci @0xproject/subproviders
- run: yarn wsrun test:circleci @0xproject/sol-cov
- run: yarn wsrun test:circleci @0xproject/metacoin
- run: yarn wsrun test:circleci @0xproject/order-utils
- run: yarn wsrun test:circleci @0xproject/order-watcher
- run: yarn wsrun test:circleci @0xproject/sol-compiler
- run: yarn wsrun test:circleci @0xproject/sol-cov
- run: yarn wsrun test:circleci @0xproject/sra-report
- run: yarn wsrun test:circleci @0xproject/subproviders
- run: yarn wsrun test:circleci @0xproject/web3-wrapper
- save_cache:
key: coverage-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
key: coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/contract-wrappers/coverage/lcov.info
- save_cache:
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/sol-compiler/coverage/lcov.info
- ~/repo/packages/0x.js/coverage/lcov.info
- save_cache:
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/assert/coverage/lcov.info
- save_cache:
key: coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/base-contract/coverage/lcov.info
- save_cache:
key: coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/connect/coverage/lcov.info
- save_cache:
key: coverage-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/contract-wrappers/coverage/lcov.info
- save_cache:
key: coverage-dev-utils-{{ .Environment.CIRCLE_SHA1 }}
paths:
@@ -98,17 +108,37 @@ jobs:
paths:
- ~/repo/packages/json-schemas/coverage/lcov.info
- save_cache:
key: coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/subproviders/coverage/lcov.info
- ~/repo/packages/metacoin/coverage/lcov.info
- save_cache:
key: coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/order-utils/coverage/lcov.info
- save_cache:
key: coverage-order-watcher-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/order-watcher/coverage/lcov.info
- save_cache:
key: coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/sol-compiler/coverage/lcov.info
- save_cache:
key: coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/sol-cov/coverage/lcov.info
- save_cache:
key: coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
key: coverage-sra-report-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/metacoin/coverage/lcov.info
- ~/repo/packages/sra-report/coverage/lcov.info
- save_cache:
key: coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/subproviders/coverage/lcov.info
- save_cache:
key: coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/web3-wrapper/coverage/lcov.info
static-tests:
working_directory: ~/repo
docker:
@@ -127,9 +157,15 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-base-contract-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-connect-{{ .Environment.CIRCLE_SHA1 }}
@@ -144,22 +180,31 @@ jobs:
- coverage-json-schemas-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
- coverage-order-utils-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
- coverage-order-watcher-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-sol-compiler-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
- coverage-sol-cov-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-metacoin-{{ .Environment.CIRCLE_SHA1 }}
- coverage-sra-report-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-subproviders-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-web3-wrapper-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-contracts-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn report_coverage
workflows:
version: 2

10
.gitignore vendored
View File

@@ -67,6 +67,9 @@ generated_docs/
TODO.md
# VSCode file
.vscode
packages/website/public/bundle*
packages/react-docs/example/public/bundle*
@@ -81,14 +84,15 @@ packages/contract-wrappers/test/artifacts/
# generated contract wrappers
packages/0x.js/src/generated_contract_wrappers/
packages/contracts/src/generated_contract_wrappers/
packages/contracts/generated_contract_wrappers/
packages/contract-wrappers/src/contract_wrappers/generated/
packages/metacoin/src/contract_wrappers
packages/fill-scenarios/src/generated_contract_wrappers/
packages/order-watcher/src/generated_contract_wrappers/
packages/order-utils/src/generated_contract_wrappers/
packages/migrations/src/v1/contract_wrappers
packages/migrations/src/v2/contract_wrappers
packages/migrations/src/1.0.0/contract_wrappers
packages/migrations/src/2.0.0/contract_wrappers
packages/migrations/src/2.0.0-beta-testnet/contract_wrappers
# solc-bin in sol-compiler
packages/sol-compiler/solc_bin/

View File

@@ -3,12 +3,13 @@ lib
/packages/contract-wrappers/src/contract_wrappers/generated/
/packages/metacoin/src/contract_wrappers
/packages/0x.js/src/generated_contract_wrappers/
/packages/contracts/src/generated_contract_wrappers/
/packages/contracts/generated_contract_wrappers/
/packages/fill-scenarios/src/generated_contract_wrappers/
/packages/order-watcher/src/generated_contract_wrappers/
/packages/order-utils/src/generated_contract_wrappers/
/packages/migrations/src/v1/contract_wrappers
/packages/migrations/src/v2/contract_wrappers
/packages/migrations/src/1.0.0/contract_wrappers
/packages/migrations/src/2.0.0/contract_wrappers
/packages/migrations/src/2.0.0-beta-testnet/contract_wrappers
/packages/0x.js/test/artifacts
/packages/contracts/src/artifacts
/packages/metacoin/artifacts
@@ -16,5 +17,6 @@ lib
/packages/order-watcher/test/artifacts
/packages/migrations/artifacts/1.0.0
/packages/migrations/artifacts/2.0.0
/packages/migrations/artifacts/2.0.0-beta-testnet
package.json
scripts/postpublish_utils.js

View File

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

View File

@@ -1,24 +1,10 @@
<!--- 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
## Testing instructions
<!--- 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. -->
<!--- Please describe how reviewers can test your changes -->
## Types of changes

View File

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

View File

@@ -2,7 +2,7 @@
"private": true,
"name": "0x-monorepo",
"engines": {
"node" : ">=6.12"
"node": ">=6.12"
},
"workspaces": [
"packages/*"
@@ -25,12 +25,13 @@
"build": "wsrun build $PKG --fast-exit -r --stages",
"build:monorepo_scripts": "PKG=@0xproject/monorepo-scripts yarn build",
"clean": "wsrun clean $PKG --fast-exit -r --parallel",
"remove_node_modules": "lerna clean --yes; rm -rf node_modules",
"rebuild": "run-s clean build",
"test": "wsrun test $PKG --fast-exit --serial --exclude-missing",
"stage_docs": "wsrun docs:stage $PKG --fast-exit --parallel --exclude-missing",
"lint": "wsrun lint $PKG --fast-exit --parallel --exclude-missing",
"comment:postinstall": "HACK: For some reason `yarn` is not setting up symlinks properly for order-utils. We temporarily set them manually. Remove this after V2 refactor is complete.",
"postinstall": "rm -rf `pwd`/packages/order-utils/node_modules/@0xproject; mkdir `pwd`/packages/order-utils/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-utils/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/types `pwd`/packages/order-utils/node_modules/@0xproject/types; rm -f `pwd`/packages/contracts/node_modules/@0xproject/types; ln -s `pwd`/packages/types `pwd`/packages/contracts/node_modules/@0xproject/types; mkdir -p `pwd`/packages/fill-scenarios/node_modules/@0xproject; ln -s `pwd`/packages/types `pwd`/packages/fill-scenarios/node_modules/@0xproject/types; ln -s `pwd`/packages/order-utils `pwd`/packages/fill-scenarios/node_modules/@0xproject/order-utils"
"postinstall": "rm -rf `pwd`/packages/order-utils/node_modules/@0xproject; mkdir `pwd`/packages/order-utils/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-utils/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/assert `pwd`/packages/order-utils/node_modules/@0xproject/assert; ln -s `pwd`/packages/types `pwd`/packages/order-utils/node_modules/@0xproject/types; rm -f `pwd`/packages/contracts/node_modules/@0xproject/types; ln -s `pwd`/packages/types `pwd`/packages/contracts/node_modules/@0xproject/types; rm -rf `pwd`/packages/fill-scenarios/node_modules/@0xproject; mkdir -p `pwd`/packages/fill-scenarios/node_modules/@0xproject; ln -s `pwd`/packages/types `pwd`/packages/fill-scenarios/node_modules/@0xproject/types; ln -s `pwd`/packages/json-schemas `pwd`/packages/fill-scenarios/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/fill-scenarios/node_modules/@0xproject/order-utils; rm -rf `pwd`/packages/contract-wrappers/node_modules/@0xproject; mkdir -p `pwd`/packages/contract-wrappers/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contract-wrappers/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/assert `pwd`/packages/contract-wrappers/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/contract-wrappers/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/types `pwd`/packages/contract-wrappers/node_modules/@0xproject/types; ln -s `pwd`/packages/fill-scenarios `pwd`/packages/contract-wrappers/node_modules/@0xproject/fill-scenarios; rm -rf `pwd`/packages/assert/node_modules/@0xproject; mkdir -p `pwd`/packages/assert/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/assert/node_modules/@0xproject/json-schemas"
},
"config": {
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
@@ -38,7 +39,7 @@
"devDependencies": {
"async-child-process": "^1.1.1",
"coveralls": "^3.0.0",
"ganache-cli": "^6.1.0",
"ganache-cli": "6.1.3",
"lcov-result-merger": "^3.0.0",
"lerna": "^2.5.1",
"npm-run-all": "^4.1.2",
@@ -47,7 +48,6 @@
"source-map-support": "^0.5.6"
},
"resolutions": {
"ethereumjs-tx": "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default",
"ethers": "0xproject/ethers.js#eip-838-reasons"
}
}

View File

@@ -1,4 +1,40 @@
[
{
"timestamp": 1529397769,
"version": "0.38.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527617805,
"version": "0.38.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527617227,
"version": "0.38.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527616612,
"version": "0.38.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.38.0",
"changes": [

View File

@@ -5,12 +5,28 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.38.4 - _June 19, 2018_
* Dependencies updated
## v0.38.3 - _May 29, 2018_
* Dependencies updated
## v0.38.2 - _May 29, 2018_
* Dependencies updated
## v0.38.1 - _May 29, 2018_
* Dependencies updated
## v0.38.0 - _May 22, 2018_
* Renamed createOrderStateWatcher to createOrderWatcherAsync since it is now async (#579)
* Renamed ZeroExError to ContractWrappersErrors since they now lives in the @0xproject/contract-wrappers subpackage (#579)
## v0.37.2 - _May 4, 2018_
## v0.37.2 - _May 5, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "0x.js",
"version": "0.38.0",
"version": "0.38.4",
"engines": {
"node": ">=6.12"
},
@@ -30,7 +30,7 @@
"clean": "shx rm -rf _bundles lib test_temp scripts src/generated_contract_wrappers",
"build:umd:prod": "NODE_ENV=production webpack",
"build:commonjs": "tsc && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"run_mocha": "mocha --require source-map-support/register lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "node scripts/stage_docs.js",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
@@ -69,12 +69,12 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@0xproject/abi-gen": "^0.3.0",
"@0xproject/dev-utils": "^0.4.2",
"@0xproject/migrations": "^0.0.6",
"@0xproject/monorepo-scripts": "^0.1.20",
"@0xproject/sol-compiler": "^0.5.0",
"@0xproject/tslint-config": "^0.4.18",
"@0xproject/abi-gen": "^0.3.2",
"@0xproject/dev-utils": "^0.4.4",
"@0xproject/migrations": "^0.0.8",
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/sol-compiler": "^0.5.2",
"@0xproject/tslint-config": "^0.4.20",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",
@@ -100,18 +100,18 @@
"webpack": "^3.1.0"
},
"dependencies": {
"@0xproject/assert": "^0.2.10",
"@0xproject/base-contract": "^0.3.2",
"@0xproject/contract-wrappers": "^0.0.2",
"@0xproject/order-utils": "0.0.5",
"@0xproject/order-watcher": "^0.0.2",
"@0xproject/sol-compiler": "^0.5.0",
"@0xproject/types": "0.7.0",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",
"ethereum-types": "^0.0.1",
"ethers": "^3.0.15",
"@0xproject/assert": "^0.2.12",
"@0xproject/base-contract": "^0.3.4",
"@0xproject/contract-wrappers": "^0.0.5",
"@0xproject/order-utils": "^0.0.7",
"@0xproject/order-watcher": "^0.0.6",
"@0xproject/sol-compiler": "^0.5.2",
"@0xproject/types": "^0.8.1",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"@0xproject/web3-wrapper": "^0.7.1",
"ethereum-types": "^0.0.2",
"ethers": "3.0.22",
"lodash": "^4.17.4"
},
"publishConfig": {

View File

@@ -19,6 +19,8 @@ export {
TransactionReceiptWithDecodedLogs,
} from '@0xproject/types';
export { OrderWatcherConfig } from '@0xproject/order-watcher';
export {
EventCallback,
ContractEvent,

View File

@@ -3,7 +3,6 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
import 'make-promises-safe';
import 'mocha';
import { ApprovalContractEventArgs, LogWithDecodedArgs, TokenEvents, ZeroEx } from '../src';

View File

@@ -1,5 +1,4 @@
import { web3Factory } from '@0xproject/dev-utils';
import 'make-promises-safe';
import { ZeroEx } from '../src';

View File

@@ -1,4 +1,35 @@
[
{
"version": "0.4.0",
"changes": [
{
"note": "Convert e_r_c to erc in generated file names",
"pr": 822
},
{
"note": "Remove the output directory before writing to it",
"pr": 822
}
]
},
{
"timestamp": 1529397769,
"version": "0.3.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.3.1",
"changes": [
{
"note": "Incorrect publish that was unpublished"
}
],
"timestamp": 1527810075
},
{
"version": "0.3.0",
"changes": [

View File

@@ -5,11 +5,19 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.3.2 - _June 19, 2018_
* Dependencies updated
## v0.3.1 - _June 1, 2018_
* Incorrect publish that was unpublished
## v0.3.0 - _May 22, 2018_
* Properly export the executable binary (#588)
## v0.2.13 - _May 4, 2018_
## v0.2.13 - _May 5, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/abi-gen",
"version": "0.3.0",
"version": "0.3.2",
"engines": {
"node": ">=6.12"
},
@@ -27,21 +27,23 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
"dependencies": {
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"ethereum-types": "^0.0.1",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"ethereum-types": "^0.0.2",
"chalk": "^2.3.0",
"glob": "^7.1.2",
"handlebars": "^4.0.11",
"lodash": "^4.17.4",
"rimraf": "^2.6.2",
"mkdirp": "^0.5.1",
"to-snake-case": "^1.0.0",
"yargs": "^10.0.3"
},
"devDependencies": {
"@0xproject/monorepo-scripts": "^0.1.20",
"@0xproject/tslint-config": "^0.4.18",
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/tslint-config": "^0.4.20",
"@types/glob": "^5.0.33",
"@types/rimraf": "^2.0.2",
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",
"@types/node": "^8.0.53",

View File

@@ -8,6 +8,7 @@ import { sync as globSync } from 'glob';
import * as Handlebars from 'handlebars';
import * as _ from 'lodash';
import * as mkdirp from 'mkdirp';
import * as rimraf from 'rimraf';
import * as yargs from 'yargs';
import toSnakeCase = require('to-snake-case');
@@ -72,9 +73,9 @@ function registerPartials(partialsGlob: string): void {
function writeOutputFile(name: string, renderedTsCode: string): void {
let fileName = toSnakeCase(name);
if (fileName === 'z_r_x_token') {
fileName = 'zrx_token';
}
// HACK: Snake case doesn't make a lot of sense for abbreviated names but we can't reliably detect abbreviations
// so we special-case the abbreviations we use.
fileName = fileName.replace('z_r_x', 'zrx').replace('e_r_c', 'erc');
const filePath = `${args.output}/${fileName}.ts`;
fs.writeFileSync(filePath, renderedTsCode);
logUtils.log(`Created: ${chalk.bold(filePath)}`);
@@ -96,6 +97,7 @@ if (_.isEmpty(abiFileNames)) {
process.exit(1);
} else {
logUtils.log(`Found ${chalk.green(`${abiFileNames.length}`)} ${chalk.bold('ABI')} files`);
rimraf.sync(args.output);
mkdirp.sync(args.output);
}
for (const abiFileName of abiFileNames) {

View File

@@ -1,4 +1,32 @@
[
{
"version": "0.2.13",
"changes": [
{
"note":
"Fix bug in string enum assertion. We erroneously were checking against the enum keys, not values",
"pr": 821
}
]
},
{
"timestamp": 1529397769,
"version": "0.2.12",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "0.2.11",
"changes": [
{
"note": "Incorrect publish that was unpublished"
}
],
"timestamp": 1527810075
},
{
"timestamp": 1527008270,
"version": "0.2.10",

View File

@@ -5,11 +5,19 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.2.12 - _June 19, 2018_
* Dependencies updated
## v0.2.11 - _June 1, 2018_
* Incorrect publish that was unpublished
## v0.2.10 - _May 22, 2018_
* Dependencies updated
## v0.2.9 - _May 4, 2018_
## v0.2.9 - _May 5, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/assert",
"version": "0.2.10",
"version": "0.3.0",
"engines": {
"node": ">=6.12"
},
@@ -12,7 +12,7 @@
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib test_temp scripts",
"lint": "tslint --project .",
"run_mocha": "mocha --require source-map-support/register lib/test/**/*_test.js --exit",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
"prepublishOnly": "run-p build",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test",
@@ -31,8 +31,8 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
"devDependencies": {
"@0xproject/monorepo-scripts": "^0.1.20",
"@0xproject/tslint-config": "^0.4.18",
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/tslint-config": "^0.4.20",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/valid-url": "^1.0.2",
@@ -48,9 +48,9 @@
"typescript": "2.7.1"
},
"dependencies": {
"@0xproject/json-schemas": "0.7.22",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/json-schemas": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"lodash": "^4.17.4",
"valid-url": "^1.0.9"
},

View File

@@ -41,8 +41,8 @@ export const assert = {
value: string,
stringEnum: any /* There is no base type for every string enum */,
): void {
const doesBelongToStringEnum = !_.isUndefined(stringEnum[value]);
const enumValues = _.keys(stringEnum);
const enumValues = _.values(stringEnum);
const doesBelongToStringEnum = _.includes(enumValues, value);
const enumValuesAsStrings = _.map(enumValues, enumValue => `'${enumValue}'`);
const enumValuesAsString = enumValuesAsStrings.join(', ');
assert.assert(

View File

@@ -2,7 +2,6 @@ import { schemas } from '@0xproject/json-schemas';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import 'make-promises-safe';
import 'mocha';
import { assert } from '../src/index';

View File

@@ -1,4 +1,23 @@
[
{
"version": "0.3.4",
"changes": [
{
"note":
"Update EthersJs to fix the `value.toLowerCase()` is not a function bug caused by `ethers.js` breaking patch version https://github.com/ethers-io/ethers.js/issues/201"
}
],
"timestamp": 1529397769
},
{
"timestamp": 1527810075,
"version": "0.3.3",
"changes": [
{
"note": "Incorrect publish that was unpublished"
}
]
},
{
"timestamp": 1527008270,
"version": "0.3.2",

View File

@@ -5,11 +5,19 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.3.4 - _June 19, 2018_
* Update EthersJs to fix the `value.toLowerCase()` is not a function bug caused by `ethers.js` breaking patch version https://github.com/ethers-io/ethers.js/issues/201
## v0.3.3 - _June 1, 2018_
* Incorrect publish that was unpublished
## v0.3.2 - _May 22, 2018_
* Dependencies updated
## v0.3.1 - _May 4, 2018_
## v0.3.1 - _May 5, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/base-contract",
"version": "0.3.2",
"version": "0.3.4",
"engines": {
"node": ">=6.12"
},
@@ -14,7 +14,7 @@
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test",
"test:circleci": "yarn test:coverage",
"run_mocha": "mocha --require source-map-support/register lib/test/**/*_test.js --bail --exit",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"lint": "tslint --project . --exclude **/src/contract_wrappers/**/*",
@@ -30,8 +30,8 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
"devDependencies": {
"@0xproject/monorepo-scripts": "^0.1.20",
"@0xproject/tslint-config": "^0.4.18",
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/tslint-config": "^0.4.20",
"@types/lodash": "4.14.104",
"chai": "^4.0.1",
"copyfiles": "^1.2.0",
@@ -43,11 +43,11 @@
"typescript": "2.7.1"
},
"dependencies": {
"ethereum-types": "^0.0.1",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",
"ethers": "^3.0.15",
"ethereum-types": "^0.0.2",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"@0xproject/web3-wrapper": "^0.7.1",
"ethers": "3.0.22",
"lodash": "^4.17.4"
},
"publishConfig": {

View File

@@ -80,7 +80,7 @@ export class BaseContract {
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
} as any;
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
txDataWithDefaults.gas = await estimateGasAsync(txData);
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults as any);
}
return txDataWithDefaults;
}

View File

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

View File

@@ -1,4 +1,22 @@
[
{
"timestamp": 1529397769,
"version": "0.6.15",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527616612,
"version": "0.6.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527008270,
"version": "0.6.13",

View File

@@ -5,11 +5,19 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.6.15 - _June 19, 2018_
* Dependencies updated
## v0.6.14 - _May 29, 2018_
* Dependencies updated
## v0.6.13 - _May 22, 2018_
* Dependencies updated
## v0.6.12 - _May 4, 2018_
## v0.6.12 - _May 5, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/connect",
"version": "0.6.13",
"version": "0.6.15",
"engines": {
"node": ">=6.12"
},
@@ -20,7 +20,7 @@
"clean": "shx rm -rf lib test_temp scripts",
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
"lint": "tslint --project .",
"run_mocha": "mocha --require source-map-support/register lib/test/**/*_test.js --exit",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
"test": "run-s copy_test_fixtures run_mocha",
"rebuild_and_test": "run-s clean build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
@@ -51,19 +51,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
"dependencies": {
"@0xproject/assert": "^0.2.10",
"@0xproject/json-schemas": "0.7.22",
"@0xproject/types": "^0.7.0",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/assert": "^0.2.12",
"@0xproject/json-schemas": "0.8.1",
"@0xproject/types": "^0.8.1",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.4",
"query-string": "^5.0.1",
"websocket": "^1.0.25"
},
"devDependencies": {
"@0xproject/monorepo-scripts": "^0.1.20",
"@0xproject/tslint-config": "^0.4.18",
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/tslint-config": "^0.4.20",
"@types/fetch-mock": "^5.12.1",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,28 @@
[
{
"version": "0.1.0",
"version": "1.0.0",
"changes": [
{
"note": "Update blockstream to v5.0 and propogate up caught errors to active subscriptions"
},
{
"note": "Update to v2 of 0x rpotocol",
"pr": 822
}
]
},
{
"timestamp": 1529397769,
"version": "0.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1527617227,
"version": "0.0.4",
"changes": [
{
"note": "Expose 'abi' ContractAbi property on all contract wrappers"

View File

@@ -5,6 +5,18 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.0.5 - _June 19, 2018_
* Dependencies updated
## v0.0.4 - _May 29, 2018_
* Dependencies updated
## v0.0.3 - _May 29, 2018_
* Dependencies updated
## v0.0.2 - _May 22, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/contract-wrappers",
"version": "0.0.2",
"version": "0.0.6",
"description": "Smart TS wrappers for 0x smart contracts",
"keywords": [
"0xproject",
@@ -13,23 +13,20 @@
"scripts": {
"watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"pre_build": "run-s generate_contract_wrappers update_test_artifacts update_compact_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
"pre_build": "run-s generate_contract_wrappers update_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers",
"lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*",
"test:circleci": "run-s test:coverage",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"update_compact_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts",
"update_test_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/1.0.0/$i.json test/artifacts; done;",
"update_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts",
"clean": "shx rm -rf _bundles lib test_temp scripts test/artifacts src/contract_wrappers/generated",
"run_mocha": "mocha --require source-map-support/register lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"config": {
"compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry",
"contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy_v1 MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels",
"postpublish": {
"assets": [
"packages/contract-wrappers/_bundles/index.js",
@@ -46,13 +43,13 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@0xproject/abi-gen": "^0.3.0",
"@0xproject/dev-utils": "^0.4.2",
"@0xproject/migrations": "^0.0.6",
"@0xproject/monorepo-scripts": "^0.1.20",
"@0xproject/sol-compiler": "^0.5.0",
"@0xproject/subproviders": "^0.10.2",
"@0xproject/tslint-config": "^0.4.18",
"@0xproject/abi-gen": "^0.3.2",
"@0xproject/dev-utils": "^0.4.4",
"@0xproject/migrations": "^0.0.8",
"@0xproject/monorepo-scripts": "^0.2.1",
"@0xproject/sol-compiler": "^0.5.2",
"@0xproject/subproviders": "^0.10.4",
"@0xproject/tslint-config": "^0.4.20",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",
@@ -74,22 +71,22 @@
"source-map-support": "^0.5.0",
"tslint": "5.8.0",
"typescript": "2.7.1",
"web3-provider-engine": "^14.0.4"
"web3-provider-engine": "14.0.6"
},
"dependencies": {
"@0xproject/assert": "^0.2.10",
"@0xproject/base-contract": "^0.3.2",
"@0xproject/fill-scenarios": "^0.0.2",
"@0xproject/json-schemas": "0.7.22",
"@0xproject/order-utils": "0.0.5",
"@0xproject/types": "0.7.0",
"@0xproject/typescript-typings": "^0.3.2",
"@0xproject/utils": "^0.6.2",
"@0xproject/web3-wrapper": "^0.6.4",
"ethereum-types": "^0.0.1",
"ethereumjs-blockstream": "^2.0.6",
"@0xproject/assert": "^0.3.0",
"@0xproject/base-contract": "^0.3.4",
"@0xproject/order-utils": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.1",
"@0xproject/utils": "^0.7.1",
"@0xproject/web3-wrapper": "^0.7.1",
"@0xproject/fill-scenarios": "^1.0.0",
"@0xproject/json-schemas": "^1.0.0",
"@0xproject/types": "^1.0.0",
"ethereum-types": "^0.0.2",
"ethereumjs-blockstream": "5.0.0",
"ethereumjs-util": "^5.1.1",
"ethers": "^3.0.15",
"ethers": "3.0.22",
"js-sha3": "^0.7.0",
"lodash": "^4.17.4",
"uuid": "^3.1.0"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,301 @@
{
"contractName": "WETH9",
"compilerOutput": {
"abi": [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "guy",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "src",
"type": "address"
},
{
"name": "dst",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "wad",
"type": "uint256"
}
],
"name": "withdraw",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "dst",
"type": "address"
},
{
"name": "wad",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "deposit",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"payable": true,
"stateMutability": "payable",
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": true,
"name": "_spender",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_from",
"type": "address"
},
{
"indexed": true,
"name": "_to",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Deposit",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "_owner",
"type": "address"
},
{
"indexed": false,
"name": "_value",
"type": "uint256"
}
],
"name": "Withdrawal",
"type": "event"
}
]
},
"networks": {
"1": {
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
},
"3": {
"address": "0xc00fd9820cd2898cc4c054b7bf142de637ad129a"
},
"4": {
"address": "0xc778417e063141139fce010982780140aa0cd5ab"
},
"42": {
"address": "0x653e49e301e508a13237c0ddc98ae7d4cd2667a1"
},
"50": {
"address": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082"
}
}
}

View File

@@ -1,5 +1,8 @@
{
"contract_name": "ZRX",
"contractName": "ZRXToken",
"compilerOutput": {
"abi": []
},
"networks": {
"1": {
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
@@ -14,7 +17,7 @@
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
},
"50": {
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,15 +1,8 @@
import {
Artifact,
BlockParamLiteral,
ContractAbi,
FilterObject,
LogEntry,
LogWithDecodedArgs,
RawLog,
} from '@0xproject/types';
import { intervalUtils } from '@0xproject/utils';
import { ContractArtifact } from '@0xproject/sol-compiler';
import { AbiDecoder, intervalUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream';
import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from 'ethereum-types';
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
import * as _ from 'lodash';
import {
@@ -19,7 +12,6 @@ import {
ContractWrappersError,
EventCallback,
IndexedFilterValues,
InternalContractWrappersError,
} from '../types';
import { constants } from '../utils/constants';
import { filterUtils } from '../utils/filter_utils';
@@ -29,9 +21,10 @@ const CONTRACT_NAME_TO_NOT_FOUND_ERROR: {
} = {
ZRX: ContractWrappersError.ZRXContractDoesNotExist,
EtherToken: ContractWrappersError.EtherTokenContractDoesNotExist,
Token: ContractWrappersError.TokenContractDoesNotExist,
TokenRegistry: ContractWrappersError.TokenRegistryContractDoesNotExist,
TokenTransferProxy: ContractWrappersError.TokenTransferProxyContractDoesNotExist,
ERC20Token: ContractWrappersError.ERC20TokenContractDoesNotExist,
ERC20Proxy: ContractWrappersError.ERC20ProxyContractDoesNotExist,
ERC721Token: ContractWrappersError.ERC721TokenContractDoesNotExist,
ERC721Proxy: ContractWrappersError.ERC721ProxyContractDoesNotExist,
Exchange: ContractWrappersError.ExchangeContractDoesNotExist,
};
@@ -39,7 +32,8 @@ export abstract class ContractWrapper {
public abstract abi: ContractAbi;
protected _web3Wrapper: Web3Wrapper;
protected _networkId: number;
private _blockAndLogStreamerIfExists?: BlockAndLogStreamer;
private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined;
private _blockPollingIntervalMs: number;
private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer;
private _filters: { [filterToken: string]: FilterObject };
private _filterCallbacks: {
@@ -47,9 +41,12 @@ export abstract class ContractWrapper {
};
private _onLogAddedSubscriptionToken: string | undefined;
private _onLogRemovedSubscriptionToken: string | undefined;
constructor(web3Wrapper: Web3Wrapper, networkId: number) {
constructor(web3Wrapper: Web3Wrapper, networkId: number, blockPollingIntervalMs?: number) {
this._web3Wrapper = web3Wrapper;
this._networkId = networkId;
this._blockPollingIntervalMs = _.isUndefined(blockPollingIntervalMs)
? constants.DEFAULT_BLOCK_POLLING_INTERVAL
: blockPollingIntervalMs;
this._filters = {};
this._filterCallbacks = {};
this._blockAndLogStreamerIfExists = undefined;
@@ -107,14 +104,12 @@ export abstract class ContractWrapper {
protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>(
log: LogEntry,
): LogWithDecodedArgs<ArgsType> | RawLog {
if (_.isUndefined(this._web3Wrapper.abiDecoder)) {
throw new Error(InternalContractWrappersError.NoAbiDecoder);
}
const logWithDecodedArgs = this._web3Wrapper.abiDecoder.tryToDecodeLogOrNoop(log);
const abiDecoder = new AbiDecoder([this.abi]);
const logWithDecodedArgs = abiDecoder.tryToDecodeLogOrNoop(log);
return logWithDecodedArgs;
}
protected async _getContractAbiAndAddressFromArtifactsAsync(
artifact: Artifact,
artifact: ContractArtifact,
addressIfExists?: string,
): Promise<[ContractAbi, string]> {
let contractAddress: string;
@@ -128,12 +123,12 @@ export abstract class ContractWrapper {
}
const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(contractAddress);
if (!doesContractExist) {
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contract_name]);
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contractName]);
}
const abiAndAddress: [ContractAbi, string] = [artifact.abi, contractAddress];
const abiAndAddress: [ContractAbi, string] = [artifact.compilerOutput.abi, contractAddress];
return abiAndAddress;
}
protected _getContractAddress(artifact: Artifact, addressIfExists?: string): string {
protected _getContractAddress(artifact: ContractArtifact, addressIfExists?: string): string {
if (_.isUndefined(addressIfExists)) {
const contractAddress = artifact.networks[this._networkId].address;
if (_.isUndefined(contractAddress)) {
@@ -163,12 +158,13 @@ export abstract class ContractWrapper {
this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
this._onBlockAndLogStreamerError.bind(this),
);
const catchAllLogFilter = {};
this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval(
this._reconcileBlockAsync.bind(this),
constants.DEFAULT_BLOCK_POLLING_INTERVAL,
this._blockPollingIntervalMs,
this._onReconcileBlockError.bind(this),
);
let isRemoved = false;
@@ -180,6 +176,14 @@ export abstract class ContractWrapper {
this._onLogStateChanged.bind(this, isRemoved),
);
}
private _onBlockAndLogStreamerError(err: Error): void {
// Propogate all Blockstream subscriber errors to all
// top-level subscriptions
const filterCallbacks = _.values(this._filterCallbacks);
_.each(filterCallbacks, filterCallback => {
filterCallback(err);
});
}
private _onReconcileBlockError(err: Error): void {
const filterTokens = _.keys(this._filterCallbacks);
_.each(filterTokens, filterToken => {

View File

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

View File

@@ -1,10 +1,12 @@
import { schemas } from '@0xproject/json-schemas';
import { ContractAbi, LogWithDecodedArgs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { methodOptsSchema } from '../schemas/method_opts_schema';
import { txOptsSchema } from '../schemas/tx_opts_schema';
import {
BlockRange,
ContractWrappersError,
@@ -17,23 +19,30 @@ import { assert } from '../utils/assert';
import { constants } from '../utils/constants';
import { ContractWrapper } from './contract_wrapper';
import { TokenContract, TokenContractEventArgs, TokenEvents } from './generated/token';
import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper';
import { ERC20ProxyWrapper } from './erc20_proxy_wrapper';
import { ERC20TokenContract, ERC20TokenEventArgs, ERC20TokenEvents } from './generated/erc20_token';
const removeUndefinedProperties = _.pickBy;
/**
* This class includes all the functionality related to interacting with ERC20 token contracts.
* All ERC20 method calls are supported, along with some convenience methods for getting/setting allowances
* to the 0x Proxy smart contract.
* to the 0x ERC20 Proxy smart contract.
*/
export class TokenWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.Token.abi;
export class ERC20TokenWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.ERC20Token.compilerOutput.abi;
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
private _tokenContractsByAddress: { [address: string]: TokenContract };
private _tokenTransferProxyWrapper: TokenTransferProxyWrapper;
constructor(web3Wrapper: Web3Wrapper, networkId: number, tokenTransferProxyWrapper: TokenTransferProxyWrapper) {
super(web3Wrapper, networkId);
private _tokenContractsByAddress: { [address: string]: ERC20TokenContract };
private _erc20ProxyWrapper: ERC20ProxyWrapper;
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
erc20ProxyWrapper: ERC20ProxyWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
this._tokenContractsByAddress = {};
this._tokenTransferProxyWrapper = tokenTransferProxyWrapper;
this._erc20ProxyWrapper = erc20ProxyWrapper;
}
/**
* Retrieves an owner's ERC20 token balance.
@@ -45,17 +54,18 @@ export class TokenWrapper extends ContractWrapper {
public async getBalanceAsync(
tokenAddress: string,
ownerAddress: string,
methodOpts?: MethodOpts,
methodOpts: MethodOpts = {},
): Promise<BigNumber> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
const txData = {};
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, defaultBlock);
let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, methodOpts.defaultBlock);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
balance = new BigNumber(balance);
return balance;
@@ -78,20 +88,25 @@ export class TokenWrapper extends ContractWrapper {
amountInBaseUnits: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('spenderAddress', spenderAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedSpenderAddress = spenderAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
assert.isETHAddressHex('spenderAddress', spenderAddress);
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const normalizedSpenderAddress = spenderAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const txHash = await tokenContract.approve.sendTransactionAsync(normalizedSpenderAddress, amountInBaseUnits, {
from: normalizedOwnerAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
});
const txHash = await tokenContract.approve.sendTransactionAsync(
normalizedSpenderAddress,
amountInBaseUnits,
removeUndefinedProperties({
from: normalizedOwnerAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
);
return txHash;
}
/**
@@ -112,16 +127,10 @@ export class TokenWrapper extends ContractWrapper {
spenderAddress: string,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('spenderAddress', spenderAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const normalizedSpenderAddress = spenderAddress.toLowerCase();
const txHash = await this.setAllowanceAsync(
normalizedTokenAddress,
normalizedOwnerAddress,
normalizedSpenderAddress,
tokenAddress,
ownerAddress,
spenderAddress,
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
txOpts,
);
@@ -139,23 +148,24 @@ export class TokenWrapper extends ContractWrapper {
tokenAddress: string,
ownerAddress: string,
spenderAddress: string,
methodOpts?: MethodOpts,
methodOpts: MethodOpts = {},
): Promise<BigNumber> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('spenderAddress', spenderAddress);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const normalizedSpenderAddress = spenderAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const defaultBlock = _.isUndefined(methodOpts) ? undefined : methodOpts.defaultBlock;
const txData = {};
let allowanceInBaseUnits = await tokenContract.allowance.callAsync(
normalizedOwnerAddress,
normalizedSpenderAddress,
txData,
defaultBlock,
methodOpts.defaultBlock,
);
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits);
@@ -170,20 +180,10 @@ export class TokenWrapper extends ContractWrapper {
public async getProxyAllowanceAsync(
tokenAddress: string,
ownerAddress: string,
methodOpts?: MethodOpts,
methodOpts: MethodOpts = {},
): Promise<BigNumber> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
const allowanceInBaseUnits = await this.getAllowanceAsync(
normalizedTokenAddress,
normalizedOwnerAddress,
proxyAddress,
methodOpts,
);
const proxyAddress = this._erc20ProxyWrapper.getContractAddress();
const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts);
return allowanceInBaseUnits;
}
/**
@@ -202,16 +202,10 @@ export class TokenWrapper extends ContractWrapper {
amountInBaseUnits: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
const proxyAddress = this._tokenTransferProxyWrapper.getContractAddress();
const proxyAddress = this._erc20ProxyWrapper.getContractAddress();
const txHash = await this.setAllowanceAsync(
normalizedTokenAddress,
normalizedOwnerAddress,
tokenAddress,
ownerAddress,
proxyAddress,
amountInBaseUnits,
txOpts,
@@ -234,13 +228,9 @@ export class TokenWrapper extends ContractWrapper {
ownerAddress: string,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('ownerAddress', ownerAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedOwnerAddress = ownerAddress.toLowerCase();
const txHash = await this.setProxyAllowanceAsync(
normalizedTokenAddress,
normalizedOwnerAddress,
tokenAddress,
ownerAddress,
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
txOpts,
);
@@ -263,12 +253,13 @@ export class TokenWrapper extends ContractWrapper {
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('toAddress', toAddress);
await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper);
assert.isETHAddressHex('toAddress', toAddress);
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedFromAddress = fromAddress.toLowerCase();
const normalizedToAddress = toAddress.toLowerCase();
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
@@ -277,11 +268,15 @@ export class TokenWrapper extends ContractWrapper {
throw new Error(ContractWrappersError.InsufficientBalanceForTransfer);
}
const txHash = await tokenContract.transfer.sendTransactionAsync(normalizedToAddress, amountInBaseUnits, {
from: normalizedFromAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
});
const txHash = await tokenContract.transfer.sendTransactionAsync(
normalizedToAddress,
amountInBaseUnits,
removeUndefinedProperties({
from: normalizedFromAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
);
return txHash;
}
/**
@@ -306,15 +301,16 @@ export class TokenWrapper extends ContractWrapper {
amountInBaseUnits: BigNumber,
txOpts: TransactionOpts = {},
): Promise<string> {
assert.isETHAddressHex('toAddress', toAddress);
assert.isETHAddressHex('fromAddress', fromAddress);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isETHAddressHex('fromAddress', fromAddress);
assert.isETHAddressHex('toAddress', toAddress);
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
const normalizedToAddress = toAddress.toLowerCase();
const normalizedFromAddress = fromAddress.toLowerCase();
const normalizedTokenAddress = tokenAddress.toLowerCase();
const normalizedSenderAddress = senderAddress.toLowerCase();
assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits);
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
@@ -336,11 +332,11 @@ export class TokenWrapper extends ContractWrapper {
normalizedFromAddress,
normalizedToAddress,
amountInBaseUnits,
{
removeUndefinedProperties({
from: normalizedSenderAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
},
}),
);
return txHash;
}
@@ -353,22 +349,22 @@ export class TokenWrapper extends ContractWrapper {
* @param callback Callback that gets called when a log is added/removed
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends TokenContractEventArgs>(
public subscribe<ArgsType extends ERC20TokenEventArgs>(
tokenAddress: string,
eventName: TokenEvents,
eventName: ERC20TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
): string {
assert.isETHAddressHex('tokenAddress', tokenAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const subscriptionToken = this._subscribe<ArgsType>(
normalizedTokenAddress,
eventName,
indexFilterValues,
artifacts.Token.abi,
artifacts.ERC20Token.compilerOutput.abi,
callback,
);
return subscriptionToken;
@@ -378,6 +374,7 @@ export class TokenWrapper extends ContractWrapper {
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken);
}
/**
@@ -395,42 +392,44 @@ export class TokenWrapper extends ContractWrapper {
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
public async getLogsAsync<ArgsType extends ERC20TokenEventArgs>(
tokenAddress: string,
eventName: TokenEvents,
eventName: ERC20TokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
const normalizedTokenAddress = tokenAddress.toLowerCase();
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const logs = await this._getLogsAsync<ArgsType>(
normalizedTokenAddress,
eventName,
blockRange,
indexFilterValues,
artifacts.Token.abi,
artifacts.ERC20Token.compilerOutput.abi,
);
return logs;
}
// HACK: We don't want this method to be visible to the other units within that package but not to the end user.
// TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused.
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstances(): void {
this.unsubscribeAll();
this._tokenContractsByAddress = {};
}
private async _getTokenContractAsync(tokenAddress: string): Promise<TokenContract> {
private async _getTokenContractAsync(tokenAddress: string): Promise<ERC20TokenContract> {
const normalizedTokenAddress = tokenAddress.toLowerCase();
let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress];
if (!_.isUndefined(tokenContract)) {
return tokenContract;
}
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(
artifacts.Token,
artifacts.ERC20Token,
normalizedTokenAddress,
);
const contractInstance = new TokenContract(
const contractInstance = new ERC20TokenContract(
abi,
address,
this._web3Wrapper.getProvider(),

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
import { schemas } from '@0xproject/json-schemas';
import { ContractAbi, LogWithDecodedArgs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
@@ -9,22 +9,29 @@ import { BlockRange, ContractWrappersError, EventCallback, IndexedFilterValues,
import { assert } from '../utils/assert';
import { ContractWrapper } from './contract_wrapper';
import { EtherTokenContract, EtherTokenContractEventArgs, EtherTokenEvents } from './generated/ether_token';
import { TokenWrapper } from './token_wrapper';
import { ERC20TokenWrapper } from './erc20_token_wrapper';
import { WETH9Contract, WETH9EventArgs, WETH9Events } from './generated/weth9';
const removeUndefinedProperties = _.pickBy;
/**
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
*/
export class EtherTokenWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.EtherToken.abi;
public abi: ContractAbi = artifacts.EtherToken.compilerOutput.abi;
private _etherTokenContractsByAddress: {
[address: string]: EtherTokenContract;
[address: string]: WETH9Contract;
} = {};
private _tokenWrapper: TokenWrapper;
constructor(web3Wrapper: Web3Wrapper, networkId: number, tokenWrapper: TokenWrapper) {
super(web3Wrapper, networkId);
this._tokenWrapper = tokenWrapper;
private _erc20TokenWrapper: ERC20TokenWrapper;
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
erc20TokenWrapper: ERC20TokenWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
this._erc20TokenWrapper = erc20TokenWrapper;
}
/**
* Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens
@@ -52,12 +59,14 @@ export class EtherTokenWrapper extends ContractWrapper {
assert.assert(ethBalanceInWei.gte(amountInWei), ContractWrappersError.InsufficientEthBalanceForDeposit);
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
const txHash = await wethContract.deposit.sendTransactionAsync({
from: normalizedDepositorAddress,
value: amountInWei,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
});
const txHash = await wethContract.deposit.sendTransactionAsync(
removeUndefinedProperties({
from: normalizedDepositorAddress,
value: amountInWei,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
);
return txHash;
}
/**
@@ -81,7 +90,7 @@ export class EtherTokenWrapper extends ContractWrapper {
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
const normalizedWithdrawerAddress = withdrawer.toLowerCase();
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(
const WETHBalanceInBaseUnits = await this._erc20TokenWrapper.getBalanceAsync(
normalizedEtherTokenAddress,
normalizedWithdrawerAddress,
);
@@ -91,11 +100,14 @@ export class EtherTokenWrapper extends ContractWrapper {
);
const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress);
const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
from: normalizedWithdrawerAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
});
const txHash = await wethContract.withdraw.sendTransactionAsync(
amountInWei,
removeUndefinedProperties({
from: normalizedWithdrawerAddress,
gas: txOpts.gasLimit,
gasPrice: txOpts.gasPrice,
}),
);
return txHash;
}
/**
@@ -107,15 +119,15 @@ export class EtherTokenWrapper extends ContractWrapper {
* the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends EtherTokenContractEventArgs>(
public async getLogsAsync<ArgsType extends WETH9EventArgs>(
etherTokenAddress: string,
eventName: EtherTokenEvents,
eventName: WETH9Events,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._getLogsAsync<ArgsType>(
@@ -123,7 +135,7 @@ export class EtherTokenWrapper extends ContractWrapper {
eventName,
blockRange,
indexFilterValues,
artifacts.EtherToken.abi,
artifacts.EtherToken.compilerOutput.abi,
);
return logs;
}
@@ -136,22 +148,22 @@ export class EtherTokenWrapper extends ContractWrapper {
* @param callback Callback that gets called when a log is added/removed
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends EtherTokenContractEventArgs>(
public subscribe<ArgsType extends WETH9EventArgs>(
etherTokenAddress: string,
eventName: EtherTokenEvents,
eventName: WETH9Events,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
): string {
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
assert.doesBelongToStringEnum('eventName', eventName, EtherTokenEvents);
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscribe<ArgsType>(
normalizedEtherTokenAddress,
eventName,
indexFilterValues,
artifacts.EtherToken.abi,
artifacts.EtherToken.compilerOutput.abi,
callback,
);
return subscriptionToken;
@@ -161,6 +173,7 @@ export class EtherTokenWrapper extends ContractWrapper {
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken);
}
/**
@@ -187,7 +200,7 @@ export class EtherTokenWrapper extends ContractWrapper {
this.unsubscribeAll();
this._etherTokenContractsByAddress = {};
}
private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<EtherTokenContract> {
private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<WETH9Contract> {
let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress];
if (!_.isUndefined(etherTokenContract)) {
return etherTokenContract;
@@ -196,7 +209,7 @@ export class EtherTokenWrapper extends ContractWrapper {
artifacts.EtherToken,
etherTokenAddress,
);
const contractInstance = new EtherTokenContract(
const contractInstance = new WETH9Contract(
abi,
address,
this._web3Wrapper.getProvider(),

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,75 +0,0 @@
import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
/**
* Copy on read store for filled/cancelled taker amounts
*/
export class OrderFilledCancelledLazyStore implements AbstractOrderFilledCancelledFetcher {
private _exchangeWrapper: ExchangeWrapper;
private _defaultBlock: BlockParamLiteral;
private _filledTakerAmount: {
[orderHash: string]: BigNumber;
};
private _cancelledTakerAmount: {
[orderHash: string]: BigNumber;
};
constructor(exchange: ExchangeWrapper, defaultBlock: BlockParamLiteral) {
this._exchangeWrapper = exchange;
this._defaultBlock = defaultBlock;
this._filledTakerAmount = {};
this._cancelledTakerAmount = {};
}
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
if (_.isUndefined(this._filledTakerAmount[orderHash])) {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const filledTakerAmount = await this._exchangeWrapper.getFilledTakerAmountAsync(orderHash, methodOpts);
this.setFilledTakerAmount(orderHash, filledTakerAmount);
}
const cachedFilled = this._filledTakerAmount[orderHash];
return cachedFilled;
}
public setFilledTakerAmount(orderHash: string, filledTakerAmount: BigNumber): void {
this._filledTakerAmount[orderHash] = filledTakerAmount;
}
public deleteFilledTakerAmount(orderHash: string): void {
delete this._filledTakerAmount[orderHash];
}
public async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
if (_.isUndefined(this._cancelledTakerAmount[orderHash])) {
const methodOpts = {
defaultBlock: this._defaultBlock,
};
const cancelledTakerAmount = await this._exchangeWrapper.getCancelledTakerAmountAsync(
orderHash,
methodOpts,
);
this.setCancelledTakerAmount(orderHash, cancelledTakerAmount);
}
const cachedCancelled = this._cancelledTakerAmount[orderHash];
return cachedCancelled;
}
public setCancelledTakerAmount(orderHash: string, cancelledTakerAmount: BigNumber): void {
this._cancelledTakerAmount[orderHash] = cancelledTakerAmount;
}
public deleteCancelledTakerAmount(orderHash: string): void {
delete this._cancelledTakerAmount[orderHash];
}
public deleteAll(): void {
this._filledTakerAmount = {};
this._cancelledTakerAmount = {};
}
public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber> {
const unavailableTakerAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
return unavailableTakerAmount;
}
public getZRXTokenAddress(): string {
const zrxToken = this._exchangeWrapper.getZRXTokenAddress();
return zrxToken;
}
}

View File

@@ -1,26 +1,25 @@
import { BigNumber } from '@0xproject/utils';
import {
BlockParam,
ContractEventArg,
LogEntryEvent,
LogWithDecodedArgs,
Order,
OrderState,
SignedOrder,
} from '@0xproject/types';
import { OrderState, SignedOrder } from '@0xproject/types';
import { BlockParam, ContractEventArg, DecodedLogArgs, LogEntryEvent, LogWithDecodedArgs } from 'ethereum-types';
import { EtherTokenContractEventArgs, EtherTokenEvents } from './contract_wrappers/generated/ether_token';
import { ExchangeContractEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange';
import { TokenContractEventArgs, TokenEvents } from './contract_wrappers/generated/token';
import { ERC20TokenEventArgs, ERC20TokenEvents } from './contract_wrappers/generated/erc20_token';
import { ERC721TokenEventArgs, ERC721TokenEvents } from './contract_wrappers/generated/erc721_token';
import { ExchangeEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange';
import { WETH9EventArgs, WETH9Events } from './contract_wrappers/generated/weth9';
export enum ExchangeWrapperError {
AssetDataMismatch = 'ASSET_DATA_MISMATCH',
}
export enum ContractWrappersError {
ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
EtherTokenContractDoesNotExist = 'ETHER_TOKEN_CONTRACT_DOES_NOT_EXIST',
TokenTransferProxyContractDoesNotExist = 'TOKEN_TRANSFER_PROXY_CONTRACT_DOES_NOT_EXIST',
TokenRegistryContractDoesNotExist = 'TOKEN_REGISTRY_CONTRACT_DOES_NOT_EXIST',
TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST',
ERC20ProxyContractDoesNotExist = 'ERC20_PROXY_CONTRACT_DOES_NOT_EXIST',
ERC721ProxyContractDoesNotExist = 'ERC721_PROXY_CONTRACT_DOES_NOT_EXIST',
ERC20TokenContractDoesNotExist = 'ERC20_TOKEN_CONTRACT_DOES_NOT_EXIST',
ERC721TokenContractDoesNotExist = 'ERC721_TOKEN_CONTRACT_DOES_NOT_EXIST',
ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK',
InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER',
InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER',
@@ -30,30 +29,24 @@ export enum ContractWrappersError {
OutOfGas = 'OUT_OF_GAS',
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
ERC721OwnerNotFound = 'ERC_721_OWNER_NOT_FOUND',
ERC721NoApproval = 'ERC_721_NO_APPROVAL',
}
export enum InternalContractWrappersError {
NoAbiDecoder = 'NO_ABI_DECODER',
ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY',
WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY',
}
export type LogEvent = LogEntryEvent;
export interface DecodedLogEvent<ArgsType> {
export interface DecodedLogEvent<ArgsType extends DecodedLogArgs> {
isRemoved: boolean;
log: LogWithDecodedArgs<ArgsType>;
}
export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void;
export enum ExchangeContractErrCodes {
ERROR_FILL_EXPIRED, // Order has already expired
ERROR_FILL_NO_VALUE, // Order has already been fully filled or cancelled
ERROR_FILL_TRUNCATION, // Rounding error too large
ERROR_FILL_BALANCE_ALLOWANCE, // Insufficient balance or allowance for token transfer
ERROR_CANCEL_EXPIRED, // Order has already expired
ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled
}
export type EventCallback<ArgsType extends DecodedLogArgs> = (
err: null | Error,
log?: DecodedLogEvent<ArgsType>,
) => void;
export interface ContractEvent {
logIndex: number;
@@ -67,7 +60,7 @@ export interface ContractEvent {
args: ContractEventArgs;
}
export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs;
export type ContractEventArgs = ExchangeEventArgs | ERC20TokenEventArgs | ERC721TokenEventArgs | WETH9EventArgs;
// [address, name, symbol, decimals, ipfsHash, swarmHash]
export type TokenMetadata = [string, string, string, number, string, string];
@@ -90,7 +83,7 @@ export interface TokenAddressBySymbol {
[symbol: string]: string;
}
export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents;
export type ContractEvents = ERC20TokenEvents | ERC721TokenEvents | ExchangeEvents | WETH9Events;
export interface IndexedFilterValues {
[index: string]: ContractEventArg;
@@ -101,14 +94,9 @@ export interface BlockRange {
toBlock: BlockParam;
}
export interface OrderCancellationRequest {
order: Order | SignedOrder;
takerTokenCancelAmount: BigNumber;
}
export interface OrderFillRequest {
signedOrder: SignedOrder;
takerTokenFillAmount: BigNumber;
takerAssetFillAmount: BigNumber;
}
export type AsyncMethod = (...args: any[]) => Promise<any>;
@@ -119,17 +107,19 @@ export type SyncMethod = (...args: any[]) => any;
* gasPrice: Gas price to use with every transaction
* exchangeContractAddress: The address of an exchange contract to use
* zrxContractAddress: The address of the ZRX contract to use
* tokenRegistryContractAddress: The address of a token registry contract to use
* tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use
* erc20ProxyContractAddress: The address of the erc20 token transfer proxy contract to use
* erc721ProxyContractAddress: The address of the erc721 token transfer proxy contract to use
* orderWatcherConfig: All the configs related to the orderWatcher
* blockPollingIntervalMs: The interval to use for block polling in event watching methods (defaults to 1000)
*/
export interface ContractWrappersConfig {
networkId: number;
gasPrice?: BigNumber;
exchangeContractAddress?: string;
zrxContractAddress?: string;
tokenRegistryContractAddress?: string;
tokenTransferProxyContractAddress?: string;
erc20ProxyContractAddress?: string;
erc721ProxyContractAddress?: string;
blockPollingIntervalMs?: number;
}
/**
@@ -180,3 +170,19 @@ export enum TransferType {
}
export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void;
export interface OrderInfo {
orderStatus: number;
orderHash: string;
orderTakerAssetFilledAmount: BigNumber;
}
export enum OrderStatus {
INVALID,
INVALID_MAKER_ASSET_AMOUNT,
INVALID_TAKER_ASSET_AMOUNT,
FILLABLE,
EXPIRED,
FULLY_FILLED,
CANCELLED,
}

View File

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

View File

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

View File

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

View File

@@ -1,8 +1,7 @@
import { BlockParamLiteral, ExchangeContractErrs } from '@0xproject/types';
import { ExchangeContractErrs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store';
import { TokenWrapper } from '../contract_wrappers/token_wrapper';
import { TradeSide, TransferType } from '../types';
import { constants } from '../utils/constants';

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,4 @@
import * as chai from 'chai';
import 'make-promises-safe';
import { ContractWrappers } from '../src';
@@ -10,7 +9,7 @@ import { provider } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
describe('TokenTransferProxyWrapper', () => {
describe('ERC20ProxyWrapper', () => {
let contractWrappers: ContractWrappers;
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
@@ -20,15 +19,15 @@ describe('TokenTransferProxyWrapper', () => {
});
describe('#isAuthorizedAsync', () => {
it('should return false if the address is not authorized', async () => {
const isAuthorized = await contractWrappers.proxy.isAuthorizedAsync(constants.NULL_ADDRESS);
const isAuthorized = await contractWrappers.erc20Proxy.isAuthorizedAsync(constants.NULL_ADDRESS);
expect(isAuthorized).to.be.false();
});
});
describe('#getAuthorizedAddressesAsync', () => {
it('should return the list of authorized addresses', async () => {
const authorizedAddresses = await contractWrappers.proxy.getAuthorizedAddressesAsync();
const authorizedAddresses = await contractWrappers.erc20Proxy.getAuthorizedAddressesAsync();
for (const authorizedAddress of authorizedAddresses) {
const isAuthorized = await contractWrappers.proxy.isAuthorizedAsync(authorizedAddress);
const isAuthorized = await contractWrappers.erc20Proxy.isAuthorizedAsync(authorizedAddress);
expect(isAuthorized).to.be.true();
}
});

View File

@@ -1,38 +1,36 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { EmptyWalletSubprovider } from '@0xproject/subproviders';
import { DoneCallback, Provider } from '@0xproject/types';
import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import 'make-promises-safe';
import { Provider } from 'ethereum-types';
import 'mocha';
import Web3ProviderEngine = require('web3-provider-engine');
import {
ApprovalContractEventArgs,
BlockParamLiteral,
BlockRange,
ContractWrappers,
ContractWrappersError,
DecodedLogEvent,
Token,
TokenEvents,
TransferContractEventArgs,
ERC20TokenApprovalEventArgs,
ERC20TokenEvents,
ERC20TokenTransferEventArgs,
} from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { TokenUtils } from './utils/token_utils';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('TokenWrapper', () => {
describe('ERC20Wrapper', () => {
let contractWrappers: ContractWrappers;
let userAddresses: string[];
let tokens: Token[];
let tokenUtils: TokenUtils;
let tokens: string[];
let coinbase: string;
let addressWithoutFunds: string;
const config = {
@@ -41,8 +39,7 @@ describe('TokenWrapper', () => {
before(async () => {
contractWrappers = new ContractWrappers(provider, config);
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
tokens = await contractWrappers.tokenRegistry.getTokensAsync();
tokenUtils = new TokenUtils(tokens);
tokens = tokenUtils.getDummyERC20TokenAddresses();
coinbase = userAddresses[0];
addressWithoutFunds = userAddresses[1];
});
@@ -53,26 +50,26 @@ describe('TokenWrapper', () => {
await blockchainLifecycle.revertAsync();
});
describe('#transferAsync', () => {
let token: Token;
let tokenAddress: string;
let transferAmount: BigNumber;
before(() => {
token = tokens[0];
tokenAddress = tokens[0];
transferAmount = new BigNumber(42);
});
it('should successfully transfer tokens', async () => {
const fromAddress = coinbase;
const toAddress = addressWithoutFunds;
const preBalance = await contractWrappers.token.getBalanceAsync(token.address, toAddress);
const preBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress);
expect(preBalance).to.be.bignumber.equal(0);
await contractWrappers.token.transferAsync(token.address, fromAddress, toAddress, transferAmount);
const postBalance = await contractWrappers.token.getBalanceAsync(token.address, toAddress);
await contractWrappers.erc20Token.transferAsync(tokenAddress, fromAddress, toAddress, transferAmount);
const postBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress);
return expect(postBalance).to.be.bignumber.equal(transferAmount);
});
it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => {
const fromAddress = addressWithoutFunds;
const toAddress = coinbase;
return expect(
contractWrappers.token.transferAsync(token.address, fromAddress, toAddress, transferAmount),
contractWrappers.erc20Token.transferAsync(tokenAddress, fromAddress, toAddress, transferAmount),
).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer);
});
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
@@ -80,16 +77,21 @@ describe('TokenWrapper', () => {
const fromAddress = coinbase;
const toAddress = coinbase;
return expect(
contractWrappers.token.transferAsync(nonExistentTokenAddress, fromAddress, toAddress, transferAmount),
).to.be.rejectedWith(ContractWrappersError.TokenContractDoesNotExist);
contractWrappers.erc20Token.transferAsync(
nonExistentTokenAddress,
fromAddress,
toAddress,
transferAmount,
),
).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist);
});
});
describe('#transferFromAsync', () => {
let token: Token;
let tokenAddress: string;
let toAddress: string;
let senderAddress: string;
before(async () => {
token = tokens[0];
tokenAddress = tokens[0];
toAddress = addressWithoutFunds;
senderAddress = userAddresses[2];
});
@@ -97,19 +99,19 @@ describe('TokenWrapper', () => {
const fromAddress = coinbase;
const transferAmount = new BigNumber(42);
const fromAddressBalance = await contractWrappers.token.getBalanceAsync(token.address, fromAddress);
const fromAddressBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, fromAddress);
expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount);
const fromAddressAllowance = await contractWrappers.token.getAllowanceAsync(
token.address,
const fromAddressAllowance = await contractWrappers.erc20Token.getAllowanceAsync(
tokenAddress,
fromAddress,
toAddress,
);
expect(fromAddressAllowance).to.be.bignumber.equal(0);
return expect(
contractWrappers.token.transferFromAsync(
token.address,
contractWrappers.erc20Token.transferFromAsync(
tokenAddress,
fromAddress,
toAddress,
senderAddress,
@@ -121,11 +123,11 @@ describe('TokenWrapper', () => {
const fromAddress = coinbase;
const transferAmount = new BigNumber(42);
await contractWrappers.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount);
await contractWrappers.erc20Token.setAllowanceAsync(tokenAddress, fromAddress, toAddress, transferAmount);
return expect(
contractWrappers.token.transferFromAsync(
token.address,
contractWrappers.erc20Token.transferFromAsync(
tokenAddress,
fromAddress,
toAddress,
senderAddress,
@@ -137,20 +139,25 @@ describe('TokenWrapper', () => {
const fromAddress = addressWithoutFunds;
const transferAmount = new BigNumber(42);
const fromAddressBalance = await contractWrappers.token.getBalanceAsync(token.address, fromAddress);
const fromAddressBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, fromAddress);
expect(fromAddressBalance).to.be.bignumber.equal(0);
await contractWrappers.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
const fromAddressAllowance = await contractWrappers.token.getAllowanceAsync(
token.address,
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
fromAddress,
senderAddress,
transferAmount,
);
const fromAddressAllowance = await contractWrappers.erc20Token.getAllowanceAsync(
tokenAddress,
fromAddress,
senderAddress,
);
expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount);
return expect(
contractWrappers.token.transferFromAsync(
token.address,
contractWrappers.erc20Token.transferFromAsync(
tokenAddress,
fromAddress,
toAddress,
senderAddress,
@@ -161,42 +168,47 @@ describe('TokenWrapper', () => {
it('should successfully transfer tokens', async () => {
const fromAddress = coinbase;
const preBalance = await contractWrappers.token.getBalanceAsync(token.address, toAddress);
const preBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress);
expect(preBalance).to.be.bignumber.equal(0);
const transferAmount = new BigNumber(42);
await contractWrappers.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount);
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
fromAddress,
senderAddress,
transferAmount,
);
await contractWrappers.token.transferFromAsync(
token.address,
await contractWrappers.erc20Token.transferFromAsync(
tokenAddress,
fromAddress,
toAddress,
senderAddress,
transferAmount,
);
const postBalance = await contractWrappers.token.getBalanceAsync(token.address, toAddress);
const postBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress);
return expect(postBalance).to.be.bignumber.equal(transferAmount);
});
it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => {
const fromAddress = coinbase;
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
return expect(
contractWrappers.token.transferFromAsync(
contractWrappers.erc20Token.transferFromAsync(
nonExistentTokenAddress,
fromAddress,
toAddress,
senderAddress,
new BigNumber(42),
),
).to.be.rejectedWith(ContractWrappersError.TokenContractDoesNotExist);
).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist);
});
});
describe('#getBalanceAsync', () => {
describe('With provider with accounts', () => {
it('should return the balance for an existing ERC20 token', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const balance = await contractWrappers.token.getBalanceAsync(token.address, ownerAddress);
const balance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, ownerAddress);
const expectedBalance = new BigNumber('1000000000000000000000000000');
return expect(balance).to.be.bignumber.equal(expectedBalance);
});
@@ -204,13 +216,13 @@ describe('TokenWrapper', () => {
const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065';
const ownerAddress = coinbase;
return expect(
contractWrappers.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress),
).to.be.rejectedWith(ContractWrappersError.TokenContractDoesNotExist);
contractWrappers.erc20Token.getBalanceAsync(nonExistentTokenAddress, ownerAddress),
).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist);
});
it('should return a balance of 0 for a non-existent owner address', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593';
const balance = await contractWrappers.token.getBalanceAsync(token.address, nonExistentOwner);
const balance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, nonExistentOwner);
const expectedBalance = new BigNumber(0);
return expect(balance).to.be.bignumber.equal(expectedBalance);
});
@@ -222,9 +234,12 @@ describe('TokenWrapper', () => {
zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config);
});
it('should return balance even when called with provider instance without addresses', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const balance = await zeroExContractWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress);
const balance = await zeroExContractWithoutAccounts.erc20Token.getBalanceAsync(
tokenAddress,
ownerAddress,
);
const expectedBalance = new BigNumber('1000000000000000000000000000');
return expect(balance).to.be.bignumber.equal(expectedBalance);
});
@@ -232,12 +247,12 @@ describe('TokenWrapper', () => {
});
describe('#setAllowanceAsync', () => {
it("should set the spender's allowance", async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const spenderAddress = addressWithoutFunds;
const allowanceBeforeSet = await contractWrappers.token.getAllowanceAsync(
token.address,
const allowanceBeforeSet = await contractWrappers.erc20Token.getAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
);
@@ -245,15 +260,15 @@ describe('TokenWrapper', () => {
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
const amountInBaseUnits = new BigNumber(50);
await contractWrappers.token.setAllowanceAsync(
token.address,
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
amountInBaseUnits,
);
const allowanceAfterSet = await contractWrappers.token.getAllowanceAsync(
token.address,
const allowanceAfterSet = await contractWrappers.erc20Token.getAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
);
@@ -263,44 +278,50 @@ describe('TokenWrapper', () => {
});
describe('#setUnlimitedAllowanceAsync', () => {
it("should set the unlimited spender's allowance", async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const spenderAddress = addressWithoutFunds;
await contractWrappers.token.setUnlimitedAllowanceAsync(token.address, ownerAddress, spenderAddress);
const allowance = await contractWrappers.token.getAllowanceAsync(
token.address,
await contractWrappers.erc20Token.setUnlimitedAllowanceAsync(tokenAddress, ownerAddress, spenderAddress);
const allowance = await contractWrappers.erc20Token.getAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
);
return expect(allowance).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
return expect(allowance).to.be.bignumber.equal(
contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
);
});
it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => {
const transferAmount = new BigNumber(5);
const zrx = tokenUtils.getProtocolTokenOrThrow();
const zrxAddress = tokenUtils.getProtocolTokenAddress();
const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses;
await contractWrappers.token.setAllowanceAsync(
zrx.address,
await contractWrappers.erc20Token.setAllowanceAsync(
zrxAddress,
coinbase,
userWithNormalAllowance,
transferAmount,
);
await contractWrappers.token.setUnlimitedAllowanceAsync(zrx.address, coinbase, userWithUnlimitedAllowance);
await contractWrappers.erc20Token.setUnlimitedAllowanceAsync(
zrxAddress,
coinbase,
userWithUnlimitedAllowance,
);
const initBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance);
const initBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync(
userWithUnlimitedAllowance,
);
await contractWrappers.token.transferFromAsync(
zrx.address,
await contractWrappers.erc20Token.transferFromAsync(
zrxAddress,
coinbase,
userWithNormalAllowance,
userWithNormalAllowance,
transferAmount,
);
await contractWrappers.token.transferFromAsync(
zrx.address,
await contractWrappers.erc20Token.transferFromAsync(
zrxAddress,
coinbase,
userWithUnlimitedAllowance,
userWithUnlimitedAllowance,
@@ -324,20 +345,20 @@ describe('TokenWrapper', () => {
describe('#getAllowanceAsync', () => {
describe('With provider with accounts', () => {
it('should get the proxy allowance', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const spenderAddress = addressWithoutFunds;
const amountInBaseUnits = new BigNumber(50);
await contractWrappers.token.setAllowanceAsync(
token.address,
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
amountInBaseUnits,
);
const allowance = await contractWrappers.token.getAllowanceAsync(
token.address,
const allowance = await contractWrappers.erc20Token.getAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
);
@@ -345,11 +366,11 @@ describe('TokenWrapper', () => {
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
});
it('should return 0 if no allowance set yet', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const spenderAddress = addressWithoutFunds;
const allowance = await contractWrappers.token.getAllowanceAsync(
token.address,
const allowance = await contractWrappers.erc20Token.getAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
);
@@ -364,20 +385,20 @@ describe('TokenWrapper', () => {
zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config);
});
it('should get the proxy allowance', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const spenderAddress = addressWithoutFunds;
const amountInBaseUnits = new BigNumber(50);
await contractWrappers.token.setAllowanceAsync(
token.address,
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
amountInBaseUnits,
);
const allowance = await zeroExContractWithoutAccounts.token.getAllowanceAsync(
token.address,
const allowance = await zeroExContractWithoutAccounts.erc20Token.getAllowanceAsync(
tokenAddress,
ownerAddress,
spenderAddress,
);
@@ -388,42 +409,50 @@ describe('TokenWrapper', () => {
});
describe('#getProxyAllowanceAsync', () => {
it('should get the proxy allowance', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const amountInBaseUnits = new BigNumber(50);
await contractWrappers.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits);
await contractWrappers.erc20Token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amountInBaseUnits);
const allowance = await contractWrappers.token.getProxyAllowanceAsync(token.address, ownerAddress);
const allowance = await contractWrappers.erc20Token.getProxyAllowanceAsync(tokenAddress, ownerAddress);
const expectedAllowance = amountInBaseUnits;
return expect(allowance).to.be.bignumber.equal(expectedAllowance);
});
});
describe('#setProxyAllowanceAsync', () => {
it('should set the proxy allowance', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
const allowanceBeforeSet = await contractWrappers.token.getProxyAllowanceAsync(token.address, ownerAddress);
const allowanceBeforeSet = await contractWrappers.erc20Token.getProxyAllowanceAsync(
tokenAddress,
ownerAddress,
);
const expectedAllowanceBeforeAllowanceSet = new BigNumber(0);
expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet);
const amountInBaseUnits = new BigNumber(50);
await contractWrappers.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits);
await contractWrappers.erc20Token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amountInBaseUnits);
const allowanceAfterSet = await contractWrappers.token.getProxyAllowanceAsync(token.address, ownerAddress);
const allowanceAfterSet = await contractWrappers.erc20Token.getProxyAllowanceAsync(
tokenAddress,
ownerAddress,
);
const expectedAllowanceAfterAllowanceSet = amountInBaseUnits;
return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet);
});
});
describe('#setUnlimitedProxyAllowanceAsync', () => {
it('should set the unlimited proxy allowance', async () => {
const token = tokens[0];
const tokenAddress = tokens[0];
const ownerAddress = coinbase;
await contractWrappers.token.setUnlimitedProxyAllowanceAsync(token.address, ownerAddress);
const allowance = await contractWrappers.token.getProxyAllowanceAsync(token.address, ownerAddress);
return expect(allowance).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, ownerAddress);
const allowance = await contractWrappers.erc20Token.getProxyAllowanceAsync(tokenAddress, ownerAddress);
return expect(allowance).to.be.bignumber.equal(
contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
);
});
});
describe('#subscribe', () => {
@@ -432,11 +461,10 @@ describe('TokenWrapper', () => {
const transferAmount = new BigNumber(42);
const allowanceAmount = new BigNumber(42);
before(() => {
const token = tokens[0];
tokenAddress = token.address;
tokenAddress = tokens[0];
});
afterEach(() => {
contractWrappers.token.unsubscribeAll();
contractWrappers.erc20Token.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,
@@ -446,7 +474,7 @@ describe('TokenWrapper', () => {
it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => {
(async () => {
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<TransferContractEventArgs>) => {
(logEvent: DecodedLogEvent<ERC20TokenTransferEventArgs>) => {
expect(logEvent.isRemoved).to.be.false();
expect(logEvent.log.logIndex).to.be.equal(0);
expect(logEvent.log.transactionIndex).to.be.equal(0);
@@ -457,14 +485,24 @@ describe('TokenWrapper', () => {
expect(args._value).to.be.bignumber.equal(transferAmount);
},
);
contractWrappers.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callback);
await contractWrappers.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Transfer,
indexFilterValues,
callback,
);
await contractWrappers.erc20Token.transferAsync(
tokenAddress,
coinbase,
addressWithoutFunds,
transferAmount,
);
})().catch(done);
});
it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => {
(async () => {
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
(logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => {
expect(logEvent).to.not.be.undefined();
expect(logEvent.isRemoved).to.be.false();
const args = logEvent.log.args;
@@ -473,8 +511,13 @@ describe('TokenWrapper', () => {
expect(args._value).to.be.bignumber.equal(allowanceAmount);
},
);
contractWrappers.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
await contractWrappers.token.setAllowanceAsync(
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Approval,
indexFilterValues,
callback,
);
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
coinbase,
addressWithoutFunds,
@@ -485,42 +528,52 @@ describe('TokenWrapper', () => {
it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => {
(async () => {
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
(_logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
},
);
contractWrappers.token.subscribe(
contractWrappers.erc20Token.subscribe(
tokenAddress,
TokenEvents.Transfer,
ERC20TokenEvents.Transfer,
indexFilterValues,
callbackNeverToBeCalled,
);
const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)();
contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID);
contractWrappers.token.subscribe(
contractWrappers.erc20Token.subscribe(
tokenAddress,
TokenEvents.Transfer,
ERC20TokenEvents.Transfer,
indexFilterValues,
callbackToBeCalled,
);
await contractWrappers.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
await contractWrappers.erc20Token.transferAsync(
tokenAddress,
coinbase,
addressWithoutFunds,
transferAmount,
);
})().catch(done);
});
it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => {
(async () => {
const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(
(logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => {
(_logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => {
done(new Error('Expected this subscription to have been cancelled'));
},
);
const subscriptionToken = contractWrappers.token.subscribe(
const subscriptionToken = contractWrappers.erc20Token.subscribe(
tokenAddress,
TokenEvents.Transfer,
ERC20TokenEvents.Transfer,
indexFilterValues,
callbackNeverToBeCalled,
);
contractWrappers.token.unsubscribe(subscriptionToken);
await contractWrappers.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount);
contractWrappers.erc20Token.unsubscribe(subscriptionToken);
await contractWrappers.erc20Token.transferAsync(
tokenAddress,
coinbase,
addressWithoutFunds,
transferAmount,
);
done();
})().catch(done);
});
@@ -534,16 +587,15 @@ describe('TokenWrapper', () => {
};
let txHash: string;
before(() => {
const token = tokens[0];
tokenAddress = token.address;
tokenTransferProxyAddress = contractWrappers.proxy.getContractAddress();
tokenAddress = tokens[0];
tokenTransferProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
});
it('should get logs with decoded args emitted by Approval', async () => {
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
const eventName = TokenEvents.Approval;
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const eventName = ERC20TokenEvents.Approval;
const indexFilterValues = {};
const logs = await contractWrappers.token.getLogsAsync<ApprovalContractEventArgs>(
const logs = await contractWrappers.erc20Token.getLogsAsync<ERC20TokenApprovalEventArgs>(
tokenAddress,
eventName,
blockRange,
@@ -554,14 +606,14 @@ describe('TokenWrapper', () => {
expect(logs[0].event).to.be.equal(eventName);
expect(args._owner).to.be.equal(coinbase);
expect(args._spender).to.be.equal(tokenTransferProxyAddress);
expect(args._value).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
expect(args._value).to.be.bignumber.equal(contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
});
it('should only get the logs with the correct event name', async () => {
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
const differentEventName = TokenEvents.Transfer;
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const differentEventName = ERC20TokenEvents.Transfer;
const indexFilterValues = {};
const logs = await contractWrappers.token.getLogsAsync(
const logs = await contractWrappers.erc20Token.getLogsAsync(
tokenAddress,
differentEventName,
blockRange,
@@ -570,15 +622,18 @@ describe('TokenWrapper', () => {
expect(logs).to.have.length(0);
});
it('should only get the logs with the correct indexed fields', async () => {
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(tokenAddress, addressWithoutFunds);
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
const eventName = TokenEvents.Approval;
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(
tokenAddress,
addressWithoutFunds,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
const eventName = ERC20TokenEvents.Approval;
const indexFilterValues = {
_owner: coinbase,
};
const logs = await contractWrappers.token.getLogsAsync<ApprovalContractEventArgs>(
const logs = await contractWrappers.erc20Token.getLogsAsync<ERC20TokenApprovalEventArgs>(
tokenAddress,
eventName,
blockRange,

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
import { devConstants } from '@0xproject/dev-utils';
import { runV1MigrationsAsync } from '@0xproject/migrations';
import { runV2MigrationsAsync } from '@0xproject/migrations';
import { provider } from './utils/web3_wrapper';
@@ -12,6 +12,6 @@ before('migrate contracts', async function(): Promise<void> {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const artifactsDir = `../migrations/artifacts/1.0.0`;
await runV1MigrationsAsync(provider, artifactsDir, txDefaults);
const artifactsDir = `../migrations/artifacts/2.0.0`;
await runV2MigrationsAsync(provider, artifactsDir, txDefaults);
});

View File

@@ -1,540 +0,0 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { OrderError } from '@0xproject/order-utils';
import { BlockParamLiteral } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import 'make-promises-safe';
import * as Sinon from 'sinon';
import { ContractWrappers, ExchangeContractErrs, SignedOrder, Token } from '../src';
import { BalanceAndProxyAllowanceLazyStore } from '../src/stores/balance_proxy_allowance_lazy_store';
import { TradeSide, TransferType } from '../src/types';
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
import { OrderValidationUtils } from '../src/utils/order_validation_utils';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { TokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('OrderValidation', () => {
let contractWrappers: ContractWrappers;
let userAddresses: string[];
let tokens: Token[];
let tokenUtils: TokenUtils;
let exchangeContractAddress: string;
let zrxTokenAddress: string;
let fillScenarios: FillScenarios;
let makerTokenAddress: string;
let takerTokenAddress: string;
let coinbase: string;
let makerAddress: string;
let takerAddress: string;
let feeRecipient: string;
const fillableAmount = new BigNumber(5);
const fillTakerAmount = new BigNumber(5);
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
};
before(async () => {
contractWrappers = new ContractWrappers(provider, config);
exchangeContractAddress = contractWrappers.exchange.getContractAddress();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
tokens = await contractWrappers.tokenRegistry.getTokensAsync();
tokenUtils = new TokenUtils(tokens);
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
fillScenarios = new FillScenarios(provider, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
makerTokenAddress = makerToken.address;
takerTokenAddress = takerToken.address;
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('validateOrderFillableOrThrowAsync', () => {
it('should succeed if the order is fillable', async () => {
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
);
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder);
});
it('should succeed if the maker is buying ZRX and has no ZRX balance', async () => {
const makerFee = new BigNumber(2);
const takerFee = new BigNumber(2);
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
makerTokenAddress,
zrxTokenAddress,
makerFee,
takerFee,
makerAddress,
takerAddress,
fillableAmount,
feeRecipient,
);
const zrxMakerBalance = await contractWrappers.token.getBalanceAsync(zrxTokenAddress, makerAddress);
await contractWrappers.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance);
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder);
});
it('should succeed if the maker is buying ZRX and has no ZRX balance and there is no specified taker', async () => {
const makerFee = new BigNumber(2);
const takerFee = new BigNumber(2);
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
makerTokenAddress,
zrxTokenAddress,
makerFee,
takerFee,
makerAddress,
constants.NULL_ADDRESS,
fillableAmount,
feeRecipient,
);
const zrxMakerBalance = await contractWrappers.token.getBalanceAsync(zrxTokenAddress, makerAddress);
await contractWrappers.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance);
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder);
});
it('should succeed if the order is asymmetric and fillable', async () => {
const makerFillableAmount = fillableAmount;
// tslint:disable-next-line:custom-no-magic-numbers
const takerFillableAmount = fillableAmount.minus(4);
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
makerFillableAmount,
takerFillableAmount,
);
await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder);
});
it('should throw when the order is fully filled or cancelled', async () => {
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
);
await contractWrappers.exchange.cancelOrderAsync(signedOrder, fillableAmount);
return expect(contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith(
ExchangeContractErrs.OrderRemainingFillAmountZero,
);
});
it('should throw when order is expired', async () => {
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
expirationInPast,
);
return expect(contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith(
ExchangeContractErrs.OrderFillExpired,
);
});
});
describe('validateFillOrderAndThrowIfInvalidAsync', () => {
it('should throw when the fill amount is zero', async () => {
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
);
const zeroFillAmount = new BigNumber(0);
return expect(
contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
signedOrder,
zeroFillAmount,
takerAddress,
),
).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero);
});
it('should throw when the signature is invalid', async () => {
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
);
// 27 <--> 28
// tslint:disable-next-line:custom-no-magic-numbers
signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27;
return expect(
contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
signedOrder,
fillableAmount,
takerAddress,
),
).to.be.rejectedWith(OrderError.InvalidSignature);
});
it('should throw when the order is fully filled or cancelled', async () => {
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
);
await contractWrappers.exchange.cancelOrderAsync(signedOrder, fillableAmount);
return expect(
contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
signedOrder,
fillableAmount,
takerAddress,
),
).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero);
});
it('should throw when sender is not a taker', async () => {
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
);
// tslint:disable-next-line:custom-no-magic-numbers
const nonTakerAddress = userAddresses[6];
return expect(
contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
signedOrder,
fillTakerAmount,
nonTakerAddress,
),
).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
});
it('should throw when order is expired', async () => {
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
expirationInPast,
);
return expect(
contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
signedOrder,
fillTakerAmount,
takerAddress,
),
).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired);
});
it('should throw when there a rounding error would have occurred', async () => {
const makerAmount = new BigNumber(3);
const takerAmount = new BigNumber(5);
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
makerAmount,
takerAmount,
);
const fillTakerAmountThatCausesRoundingError = new BigNumber(3);
return expect(
contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync(
signedOrder,
fillTakerAmountThatCausesRoundingError,
takerAddress,
),
).to.be.rejectedWith(ExchangeContractErrs.OrderFillRoundingError);
});
});
describe('#validateFillOrKillOrderAndThrowIfInvalidAsync', () => {
it('should throw if remaining fillAmount is less then the desired fillAmount', async () => {
const signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
);
const tooLargeFillAmount = new BigNumber(7);
const fillAmountDifference = tooLargeFillAmount.minus(fillableAmount);
await contractWrappers.token.transferAsync(takerTokenAddress, coinbase, takerAddress, fillAmountDifference);
await contractWrappers.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, tooLargeFillAmount);
await contractWrappers.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference);
await contractWrappers.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount);
return expect(
contractWrappers.exchange.validateFillOrKillOrderThrowIfInvalidAsync(
signedOrder,
tooLargeFillAmount,
takerAddress,
),
).to.be.rejectedWith(ExchangeContractErrs.InsufficientRemainingFillAmount);
});
});
describe('validateCancelOrderAndThrowIfInvalidAsync', () => {
let signedOrder: SignedOrder;
const cancelAmount = new BigNumber(3);
beforeEach(async () => {
[coinbase, makerAddress, takerAddress] = userAddresses;
const [makerToken, takerToken] = tokenUtils.getDummyTokens();
makerTokenAddress = makerToken.address;
takerTokenAddress = takerToken.address;
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
);
});
it('should throw when cancel amount is zero', async () => {
const zeroCancelAmount = new BigNumber(0);
return expect(
contractWrappers.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount),
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero);
});
it('should throw when order is expired', async () => {
const expirationInPast = new BigNumber(1496826058); // 7th Jun 2017
const expiredSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
fillableAmount,
expirationInPast,
);
return expect(
contractWrappers.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount),
).to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired);
});
it('should throw when order is already cancelled or filled', async () => {
await contractWrappers.exchange.cancelOrderAsync(signedOrder, fillableAmount);
return expect(
contractWrappers.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount),
).to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
});
});
describe('#validateFillOrderBalancesAllowancesThrowIfInvalidAsync', () => {
let exchangeTransferSimulator: ExchangeTransferSimulator;
let transferFromAsync: Sinon.SinonSpy;
const bigNumberMatch = (expected: BigNumber) => {
return Sinon.match((value: BigNumber) => value.eq(expected));
};
beforeEach('create exchangeTransferSimulator', async () => {
const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(
contractWrappers.token,
BlockParamLiteral.Latest,
);
exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore);
transferFromAsync = Sinon.spy();
exchangeTransferSimulator.transferFromAsync = transferFromAsync as any;
});
it('should call exchangeTransferSimulator.transferFrom in a correct order', async () => {
const makerFee = new BigNumber(2);
const takerFee = new BigNumber(2);
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
makerTokenAddress,
takerTokenAddress,
makerFee,
takerFee,
makerAddress,
takerAddress,
fillableAmount,
feeRecipient,
);
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTransferSimulator,
signedOrder,
fillableAmount,
takerAddress,
zrxTokenAddress,
);
// tslint:disable-next-line:custom-no-magic-numbers
expect(transferFromAsync.callCount).to.be.equal(4);
expect(
transferFromAsync
.getCall(0)
.calledWith(
makerTokenAddress,
makerAddress,
takerAddress,
bigNumberMatch(fillableAmount),
TradeSide.Maker,
TransferType.Trade,
),
).to.be.true();
expect(
transferFromAsync
.getCall(1)
.calledWith(
takerTokenAddress,
takerAddress,
makerAddress,
bigNumberMatch(fillableAmount),
TradeSide.Taker,
TransferType.Trade,
),
).to.be.true();
expect(
transferFromAsync
.getCall(2)
.calledWith(
zrxTokenAddress,
makerAddress,
feeRecipient,
bigNumberMatch(makerFee),
TradeSide.Maker,
TransferType.Fee,
),
).to.be.true();
expect(
transferFromAsync
.getCall(3)
.calledWith(
zrxTokenAddress,
takerAddress,
feeRecipient,
bigNumberMatch(takerFee),
TradeSide.Taker,
TransferType.Fee,
),
).to.be.true();
});
it('should call exchangeTransferSimulator.transferFrom with correct values for an open order', async () => {
const makerFee = new BigNumber(2);
const takerFee = new BigNumber(2);
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
makerTokenAddress,
takerTokenAddress,
makerFee,
takerFee,
makerAddress,
constants.NULL_ADDRESS,
fillableAmount,
feeRecipient,
);
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTransferSimulator,
signedOrder,
fillableAmount,
takerAddress,
zrxTokenAddress,
);
// tslint:disable-next-line:custom-no-magic-numbers
expect(transferFromAsync.callCount).to.be.equal(4);
expect(
transferFromAsync
.getCall(0)
.calledWith(
makerTokenAddress,
makerAddress,
takerAddress,
bigNumberMatch(fillableAmount),
TradeSide.Maker,
TransferType.Trade,
),
).to.be.true();
expect(
transferFromAsync
.getCall(1)
.calledWith(
takerTokenAddress,
takerAddress,
makerAddress,
bigNumberMatch(fillableAmount),
TradeSide.Taker,
TransferType.Trade,
),
).to.be.true();
expect(
transferFromAsync
.getCall(2)
.calledWith(
zrxTokenAddress,
makerAddress,
feeRecipient,
bigNumberMatch(makerFee),
TradeSide.Maker,
TransferType.Fee,
),
).to.be.true();
expect(
transferFromAsync
.getCall(3)
.calledWith(
zrxTokenAddress,
takerAddress,
feeRecipient,
bigNumberMatch(takerFee),
TradeSide.Taker,
TransferType.Fee,
),
).to.be.true();
});
it('should correctly round the fillMakerTokenAmount', async () => {
const makerTokenAmount = new BigNumber(3);
const takerTokenAmount = new BigNumber(1);
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
makerTokenAddress,
takerTokenAddress,
makerAddress,
takerAddress,
makerTokenAmount,
takerTokenAmount,
);
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTransferSimulator,
signedOrder,
takerTokenAmount,
takerAddress,
zrxTokenAddress,
);
// tslint:disable-next-line:custom-no-magic-numbers
expect(transferFromAsync.callCount).to.be.equal(4);
const makerFillAmount = transferFromAsync.getCall(0).args[3];
expect(makerFillAmount).to.be.bignumber.equal(makerTokenAmount);
});
it('should correctly round the makerFeeAmount', async () => {
const makerFee = new BigNumber(2);
const takerFee = new BigNumber(4);
const signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync(
makerTokenAddress,
takerTokenAddress,
makerFee,
takerFee,
makerAddress,
takerAddress,
fillableAmount,
constants.NULL_ADDRESS,
);
const fillTakerTokenAmount = fillableAmount.div(2).round(0);
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTransferSimulator,
signedOrder,
fillTakerTokenAmount,
takerAddress,
zrxTokenAddress,
);
const makerPartialFee = makerFee.div(2);
const takerPartialFee = takerFee.div(2);
// tslint:disable-next-line:custom-no-magic-numbers
expect(transferFromAsync.callCount).to.be.equal(4);
const partialMakerFee = transferFromAsync.getCall(2).args[3];
expect(partialMakerFee).to.be.bignumber.equal(makerPartialFee);
const partialTakerFee = transferFromAsync.getCall(3).args[3];
expect(partialTakerFee).to.be.bignumber.equal(takerPartialFee);
});
});
}); // tslint:disable-line:max-file-line-count

View File

@@ -2,14 +2,14 @@ import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils
import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import 'make-promises-safe';
import 'mocha';
import * as Sinon from 'sinon';
import { ApprovalContractEventArgs, ContractWrappers, DecodedLogEvent, Token, TokenEvents } from '../src';
import { ContractWrappers, DecodedLogEvent, ERC20TokenApprovalEventArgs, ERC20TokenEvents, Token } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
@@ -18,7 +18,6 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('SubscriptionTest', () => {
let contractWrappers: ContractWrappers;
let userAddresses: string[];
let tokens: Token[];
let coinbase: string;
let addressWithoutFunds: string;
const config = {
@@ -27,7 +26,6 @@ describe('SubscriptionTest', () => {
before(async () => {
contractWrappers = new ContractWrappers(provider, config);
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
tokens = await contractWrappers.tokenRegistry.getTokensAsync();
coinbase = userAddresses[0];
addressWithoutFunds = userAddresses[1];
});
@@ -43,11 +41,11 @@ describe('SubscriptionTest', () => {
const allowanceAmount = new BigNumber(42);
let stubs: Sinon.SinonStub[] = [];
before(() => {
const token = tokens[0];
tokenAddress = token.address;
const tokenAddresses = tokenUtils.getDummyERC20TokenAddresses();
tokenAddress = tokenAddresses[0];
});
afterEach(() => {
contractWrappers.token.unsubscribeAll();
contractWrappers.erc20Token.unsubscribeAll();
_.each(stubs, s => s.restore());
stubs = [];
});
@@ -56,8 +54,13 @@ describe('SubscriptionTest', () => {
const errMsg = 'Error fetching block';
const callback = callbackErrorReporter.assertNodeCallbackError(done, errMsg);
stubs = [Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws(new Error(errMsg))];
contractWrappers.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
await contractWrappers.token.setAllowanceAsync(
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Approval,
indexFilterValues,
callback,
);
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
coinbase,
addressWithoutFunds,
@@ -70,8 +73,13 @@ describe('SubscriptionTest', () => {
const errMsg = 'Error fetching logs';
const callback = callbackErrorReporter.assertNodeCallbackError(done, errMsg);
stubs = [Sinon.stub((contractWrappers as any)._web3Wrapper, 'getLogsAsync').throws(new Error(errMsg))];
contractWrappers.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
await contractWrappers.token.setAllowanceAsync(
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Approval,
indexFilterValues,
callback,
);
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
coinbase,
addressWithoutFunds,
@@ -81,14 +89,20 @@ describe('SubscriptionTest', () => {
});
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
(async () => {
const callback = (err: Error | null, logEvent?: DecodedLogEvent<ApprovalContractEventArgs>) => _.noop;
contractWrappers.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback);
const callback = (err: Error | null, _logEvent?: DecodedLogEvent<ERC20TokenApprovalEventArgs>) =>
_.noop;
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Approval,
indexFilterValues,
callback,
);
stubs = [
Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws(
new Error('JSON RPC error'),
),
];
contractWrappers.token.unsubscribeAll();
contractWrappers.erc20Token.unsubscribeAll();
done();
})().catch(done);
});

View File

@@ -1,137 +0,0 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
import * as chai from 'chai';
import * as _ from 'lodash';
import 'make-promises-safe';
import 'mocha';
import { ContractWrappers, Token } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7;
describe('TokenRegistryWrapper', () => {
let contractWrappers: ContractWrappers;
let tokens: Token[];
const tokenAddressBySymbol: { [symbol: string]: string } = {};
const tokenAddressByName: { [symbol: string]: string } = {};
const tokenBySymbol: { [symbol: string]: Token } = {};
const tokenByName: { [symbol: string]: Token } = {};
const registeredSymbol = 'ZRX';
const registeredName = '0x Protocol Token';
const unregisteredSymbol = 'MAL';
const unregisteredName = 'Malicious Token';
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
};
before(async () => {
contractWrappers = new ContractWrappers(provider, config);
tokens = await contractWrappers.tokenRegistry.getTokensAsync();
_.map(tokens, token => {
tokenAddressBySymbol[token.symbol] = token.address;
tokenAddressByName[token.name] = token.address;
tokenBySymbol[token.symbol] = token;
tokenByName[token.name] = token;
});
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('#getTokensAsync', () => {
it('should return all the tokens added to the tokenRegistry during the migration', async () => {
expect(tokens).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION);
const schemaValidator = new SchemaValidator();
_.each(tokens, token => {
const validationResult = schemaValidator.validate(token, schemas.tokenSchema);
expect(validationResult.errors).to.have.lengthOf(0);
});
});
});
describe('#getTokenAddressesAsync', () => {
it('should return all the token addresses added to the tokenRegistry during the migration', async () => {
const tokenAddresses = await contractWrappers.tokenRegistry.getTokenAddressesAsync();
expect(tokenAddresses).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION);
const schemaValidator = new SchemaValidator();
_.each(tokenAddresses, tokenAddress => {
const validationResult = schemaValidator.validate(tokenAddress, schemas.addressSchema);
expect(validationResult.errors).to.have.lengthOf(0);
expect(tokenAddress).to.not.be.equal(constants.NULL_ADDRESS);
});
});
});
describe('#getTokenAddressBySymbol', () => {
it('should return correct address for a token in the registry', async () => {
const tokenAddress = await contractWrappers.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(
registeredSymbol,
);
expect(tokenAddress).to.be.equal(tokenAddressBySymbol[registeredSymbol]);
});
it('should return undefined for a token out of registry', async () => {
const tokenAddress = await contractWrappers.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(
unregisteredSymbol,
);
expect(tokenAddress).to.be.undefined();
});
});
describe('#getTokenAddressByName', () => {
it('should return correct address for a token in the registry', async () => {
const tokenAddress = await contractWrappers.tokenRegistry.getTokenAddressByNameIfExistsAsync(
registeredName,
);
expect(tokenAddress).to.be.equal(tokenAddressByName[registeredName]);
});
it('should return undefined for a token out of registry', async () => {
const tokenAddress = await contractWrappers.tokenRegistry.getTokenAddressByNameIfExistsAsync(
unregisteredName,
);
expect(tokenAddress).to.be.undefined();
});
});
describe('#getTokenBySymbol', () => {
it('should return correct token for a token in the registry', async () => {
const token = await contractWrappers.tokenRegistry.getTokenBySymbolIfExistsAsync(registeredSymbol);
expect(token).to.be.deep.equal(tokenBySymbol[registeredSymbol]);
});
it('should return undefined for a token out of registry', async () => {
const token = await contractWrappers.tokenRegistry.getTokenBySymbolIfExistsAsync(unregisteredSymbol);
expect(token).to.be.undefined();
});
});
describe('#getTokenByName', () => {
it('should return correct token for a token in the registry', async () => {
const token = await contractWrappers.tokenRegistry.getTokenByNameIfExistsAsync(registeredName);
expect(token).to.be.deep.equal(tokenByName[registeredName]);
});
it('should return undefined for a token out of registry', async () => {
const token = await contractWrappers.tokenRegistry.getTokenByNameIfExistsAsync(unregisteredName);
expect(token).to.be.undefined();
});
});
describe('#getTokenIfExistsAsync', () => {
it('should return the token added to the tokenRegistry during the migration', async () => {
const aToken = tokens[0];
const token = await contractWrappers.tokenRegistry.getTokenIfExistsAsync(aToken.address);
const schemaValidator = new SchemaValidator();
const validationResult = schemaValidator.validate(token, schemas.tokenSchema);
expect(validationResult.errors).to.have.lengthOf(0);
});
it('should return return undefined when passed a token address not in the tokenRegistry', async () => {
const unregisteredTokenAddress = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
const tokenIfExists = await contractWrappers.tokenRegistry.getTokenIfExistsAsync(unregisteredTokenAddress);
expect(tokenIfExists).to.be.undefined();
});
});
});

View File

@@ -1,9 +1,18 @@
import { BigNumber } from '@0xproject/utils';
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
ROPSTEN_NETWORK_ID: 3,
KOVAN_NETWORK_ID: 42,
TESTRPC_NETWORK_ID: 50,
AWAIT_TRANSACTION_MINED_MS: 0,
KOVAN_RPC_URL: 'https://kovan.infura.io/',
ROPSTEN_RPC_URL: 'https://ropsten.infura.io/',
ZRX_DECIMALS: 18,
DUMMY_TOKEN_NAME: '',
DUMMY_TOKEN_SYMBOL: '',
DUMMY_TOKEN_DECIMALS: 18,
DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(10 ** 27), // tslint:disable-line:custom-no-magic-numbers
NUM_DUMMY_ERC20_TO_DEPLOY: 3,
NUM_DUMMY_ERC721_TO_DEPLOY: 1,
};

View File

@@ -1,33 +1,47 @@
import * as _ from 'lodash';
import { generatePseudoRandomSalt } from '@0xproject/order-utils';
import { BigNumber } from '@0xproject/utils';
import { InternalContractWrappersError, Token } from '../../src/types';
import { artifacts } from '../../src/artifacts';
import { DummyERC721TokenContract } from '../../src/contract_wrappers/generated/dummy_erc721_token';
const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
const WETH_TOKEN_SYMBOL = 'WETH';
import { constants } from './constants';
import { provider, txDefaults, web3Wrapper } from './web3_wrapper';
export class TokenUtils {
private _tokens: Token[];
constructor(tokens: Token[]) {
this._tokens = tokens;
}
public getProtocolTokenOrThrow(): Token {
const zrxToken = _.find(this._tokens, { symbol: PROTOCOL_TOKEN_SYMBOL });
if (_.isUndefined(zrxToken)) {
throw new Error(InternalContractWrappersError.ZrxNotInTokenRegistry);
}
return zrxToken;
}
public getWethTokenOrThrow(): Token {
const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL });
if (_.isUndefined(wethToken)) {
throw new Error(InternalContractWrappersError.WethNotInTokenRegistry);
}
return wethToken;
}
public getDummyTokens(): Token[] {
const dummyTokens = _.filter(this._tokens, token => {
return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol);
});
return dummyTokens;
}
}
// Those addresses come from migrations. They're deterministic so it's relatively safe to hard-code them here.
// Before we were fetching them from the TokenRegistry but now we can't as it's deprecated and removed.
const DUMMY_ERC_20_ADRESSES = [
'0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f',
'0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db',
'0xf22469f31527adc53284441bae1665a7b9214dba',
'0x10add991de718a69dec2117cb6aa28098836511b',
'0x8d61158a366019ac78db4149d75fff9dda51160d',
];
const DUMMY_ERC_721_ADRESSES = ['0x131855dda0aaff096f6854854c55a4debf61077a'];
export const tokenUtils = {
getProtocolTokenAddress(): string {
return artifacts.ZRXToken.networks[constants.TESTRPC_NETWORK_ID].address;
},
getWethTokenAddress(): string {
return artifacts.EtherToken.networks[constants.TESTRPC_NETWORK_ID].address;
},
getDummyERC20TokenAddresses(): string[] {
return DUMMY_ERC_20_ADRESSES;
},
getDummyERC721TokenAddresses(): string[] {
return DUMMY_ERC_721_ADRESSES;
},
async mintDummyERC721Async(address: string, tokenOwner: string): Promise<BigNumber> {
const erc721 = new DummyERC721TokenContract(
artifacts.DummyERC721Token.compilerOutput.abi,
address,
provider,
txDefaults,
);
const tokenId = generatePseudoRandomSalt();
const txHash = await erc721.mint.sendTransactionAsync(tokenOwner, tokenId);
web3Wrapper.awaitTransactionSuccessAsync(txHash);
return tokenId;
},
};

View File

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

View File

@@ -0,0 +1,17 @@
These templates are used with [abi-gen](https://github.com/0xProject/0x-monorepo/tree/development/packages/abi-gen).
To successfully compile the generated TypeScript contract wrappers, you must:
* Install the packages on which the main contract template directly depends: `yarn add @0xproject/base-contract @0xproject/sol-compiler @0xproject/utils @0xproject/web3-wrapper ethereum-types ethers lodash`
* Install the packages on which the main contract template *in*directly depends: `yarn add @types/lodash`
* Ensure that your TypeScript configuration includes the following:
```
"compilerOptions": {
"lib": ["ES2015"],
"typeRoots": [
"node_modules/@0xproject/typescript-typings/types",
"node_modules/@types"
]
}
```

View File

@@ -1,8 +1,4 @@
/**
* This file is auto-generated using abi-gen. Don't edit directly.
* Templates can be found at https://github.com/0xProject/0x-monorepo/tree/development/packages/contract_templates.
*/
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma whitespace
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma whitespace class-name
// tslint:disable:no-unused-variable
import { BaseContract } from '@0xproject/base-contract';
import { ContractArtifact } from '@0xproject/sol-compiler';
@@ -14,9 +10,9 @@ import * as _ from 'lodash';
// tslint:enable:no-unused-variable
{{#if events}}
export type {{contractName}}ContractEventArgs =
export type {{contractName}}EventArgs =
{{#each events}}
| {{name}}ContractEventArgs{{#if @last}};{{/if}}
| {{@root.contractName}}{{name}}EventArgs{{#if @last}};{{/if}}
{{/each}}
export enum {{contractName}}Events {
@@ -31,6 +27,7 @@ export enum {{contractName}}Events {
{{/each}}
{{/if}}
/* istanbul ignore next */
// tslint:disable:no-parameter-reassignment
// tslint:disable-next-line:class-name
export class {{contractName}}Contract extends BaseContract {

View File

@@ -1,3 +1,3 @@
public {{this.name}} = {
public {{this.tsName}} = {
{{> callAsync}}
};

View File

@@ -1,4 +1,3 @@
{{#hasReturnValue}}
async callAsync(
{{> typed_params inputs=inputs}}
callData: Partial<CallData> = {},
@@ -15,6 +14,7 @@ async callAsync(
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
{
to: self.address,
...callData,
data: encodedData,
},
self._web3Wrapper.getContractDefaults(),
@@ -26,4 +26,3 @@ async callAsync(
resultArray = BaseContract._formatABIDataItemList(outputAbi, resultArray, BaseContract._bnToBigNumber.bind(this));
return resultArray{{#singleReturnValue}}[0]{{/singleReturnValue}};
},
{{/hasReturnValue}}

View File

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

View File

@@ -1,3 +1,3 @@
{{#each inputs}}
{{name}},
{{name}}{{#if @last}}{{else}},{{/if}}
{{/each}}

View File

@@ -0,0 +1,20 @@
{
"extends": "default",
"rules": {
"avoid-low-level-calls": false,
"avoid-tx-origin": "warn",
"bracket-align": false,
"code-complexity": false,
"const-name-snakecase": "error",
"expression-indent": "error",
"function-max-lines": false,
"func-order": "error",
"indent": ["error", 4],
"max-line-length": ["warn", 160],
"no-inline-assembly": false,
"quotes": ["error", "double"],
"separate-by-one-line-in-contract": "error",
"space-after-comma": "error",
"statement-indent": "error"
}
}

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