Compare commits

..

337 Commits

Author SHA1 Message Date
Fabio Berger
1b35a6e3b5 Publish
- 0x.js@1.0.6
 - @0xproject/abi-gen@1.0.11
 - @0xproject/assert@1.0.11
 - @0xproject/asset-buyer@1.0.1
 - @0xproject/base-contract@2.0.5
 - @0xproject/connect@2.0.4
 - @0xproject/contract-wrappers@2.0.0
 - contracts@2.1.47
 - @0xproject/dev-utils@1.0.10
 - ethereum-types@1.0.8
 - @0xproject/fill-scenarios@1.0.5
 - @0xproject/json-schemas@1.0.4
 - @0xproject/metacoin@0.0.21
 - @0xproject/migrations@1.0.12
 - @0xproject/order-utils@1.0.5
 - @0xproject/order-watcher@2.0.0
 - @0xproject/react-docs@1.0.11
 - @0xproject/react-shared@1.0.12
 - @0xproject/sol-compiler@1.1.5
 - @0xproject/sol-cov@2.1.5
 - @0xproject/sol-resolver@1.0.11
 - @0xproject/sra-report@1.0.11
 - @0xproject/sra-spec@1.0.4
 - @0xproject/subproviders@2.0.5
 - @0xproject/testnet-faucets@1.0.49
 - @0xproject/types@1.1.1
 - @0xproject/typescript-typings@2.0.2
 - @0xproject/utils@1.0.11
 - @0xproject/web3-wrapper@3.0.1
 - @0xproject/website@0.0.52
2018-09-25 21:34:14 +01:00
Fabio Berger
900a8aee76 Updated CHANGELOGS 2018-09-25 21:33:55 +01:00
Fabio Berger
adf5acd5c4 Update yarn.lock 2018-09-25 21:23:06 +01:00
Fabio Berger
b40861747b Properly render function generic types that don't extend another type 2018-09-25 17:34:22 +01:00
Fabio Berger
b73df28454 Merge pull request #1087 from 0xProject/addTxHashToOrderState
Add transactionHash to OrderState and emit it from OrderWatcher
2018-09-25 16:37:24 +01:00
Fabio Berger
5afc739397 Add changelog entry 2018-09-25 16:37:08 +01:00
Fabio Berger
9eecf3683b Add transactionHash to OrderState and emit it from OrderWatcher subscription 2018-09-25 16:10:13 +01:00
Fabio Berger
7570f3db51 Merge pull request #1080 from 0xProject/upgradeBlockstream
Fix dropped events issue in Order-watcher and Contract-wrappers subscriptions
2018-09-25 14:59:37 +01:00
Fabio Berger
977d55c61b merge development 2018-09-25 13:07:14 +01:00
Leonid Logvinov
78ef98c27c Publish
- 0x.js@1.0.5
 - @0xproject/abi-gen@1.0.10
 - @0xproject/assert@1.0.10
 - @0xproject/asset-buyer@1.0.0
 - @0xproject/base-contract@2.0.4
 - @0xproject/connect@2.0.3
 - @0xproject/contract-wrappers@1.0.5
 - contracts@2.1.46
 - @0xproject/dev-utils@1.0.9
 - @0xproject/fill-scenarios@1.0.4
 - @0xproject/json-schemas@1.0.3
 - @0xproject/metacoin@0.0.20
 - @0xproject/migrations@1.0.11
 - @0xproject/order-utils@1.0.4
 - @0xproject/order-watcher@1.0.5
 - @0xproject/react-docs@1.0.10
 - @0xproject/react-shared@1.0.11
 - @0xproject/sol-compiler@1.1.4
 - @0xproject/sol-cov@2.1.4
 - @0xproject/sol-resolver@1.0.10
 - @0xproject/sra-report@1.0.10
 - @0xproject/sra-spec@1.0.3
 - @0xproject/subproviders@2.0.4
 - @0xproject/testnet-faucets@1.0.48
 - @0xproject/types@1.1.0
 - @0xproject/utils@1.0.10
 - @0xproject/web3-wrapper@3.0.0
 - @0xproject/website@0.0.51
2018-09-25 13:48:55 +02:00
Leonid Logvinov
411813d8d9 Updated CHANGELOGS 2018-09-25 13:48:44 +02:00
Leonid Logvinov
64f41259eb Merge pull request #1085 from 0xProject/feature/export-sra-types
[sra-types] Move SRA types from @0xproject/connect to @0xproject/types
2018-09-25 13:36:47 +02:00
Fabio Berger
fc3acec669 Fix lint issues 2018-09-25 12:32:20 +01:00
Leonid Logvinov
b85db17e75 Move SRA types from @0xproject/connect to @0xproject/sra-types 2018-09-25 13:12:12 +02:00
Fabio Berger
a05530f821 Fix prettier 2018-09-25 12:06:37 +01:00
Fabio Berger
173b36c54c Fix prettier 2018-09-25 12:06:28 +01:00
Fabio Berger
55ca971186 Decode logs received from blockstream 2018-09-25 12:05:44 +01:00
Fabio Berger
284930eb58 Add missing type 2018-09-25 11:30:27 +01:00
Fabio Berger
902691e289 Update changelogs 2018-09-25 11:29:36 +01:00
Fabio Berger
0afe55f2ff Refactor blockstream integration to use the proper callback method interface 2018-09-25 11:20:09 +01:00
Fabio Berger
21910a7129 Add entry about newly exposed method 2018-09-25 11:02:49 +01:00
Fabio Berger
9c89d1e99b Expose method to send raw JSON RPC payloads 2018-09-25 10:45:11 +01:00
Alex Browne
408f573188 Use the 0xorg DockerHub account instead of albrow (#1084) 2018-09-24 14:31:26 -07:00
Alex Browne
6f2ab23bd0 Feature/custom verdaccio dockerfile (#1083)
Create custom verdaccio docker image
2018-09-24 13:54:25 -07:00
Francesco Agosti
b830c28d83 Merge pull request #1037 from 0xProject/feature/forwarder-helper/sra-and-rpc
[asset-buyer] Create new AssetBuyer class
2018-09-24 17:47:59 +02:00
Francesco Agosti
4a316571ff Merge pull request #1073 from 0xProject/fix/website/signing-order-validation-bug
[website] Fix order creation and fill flow in Portal
2018-09-24 17:23:13 +02:00
Fabio Berger
5e1a2bd972 Merge development 2018-09-24 15:53:34 +01:00
Fabio Berger
fc33eacd2c Merge pull request #1082 from 0xProject/fixGetBlocks
Fix block fetch error if block not found
2018-09-24 15:49:58 +01:00
fragosti
748a8a8ae3 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into fix/website/signing-order-validation-bug 2018-09-24 16:48:47 +02:00
Fabio Berger
7516959c9f Add comments for clarity 2018-09-24 15:14:14 +01:00
Fabio Berger
311b925919 Add to doc comment why a block might not be returned to the caller 2018-09-24 15:14:07 +01:00
Fabio Berger
5d88a56452 Add PR nr 2018-09-24 15:11:29 +01:00
Fabio Berger
ebddf82819 Add CHANGELOG entry for change to getBlockAsync 2018-09-24 15:02:47 +01:00
Fabio Berger
d0448c2bbd Fix bug where if block wasn't found, getBlockAsync would throw. Now it returns undefined 2018-09-24 15:02:06 +01:00
fragosti
d8d1c98a40 Upgrade all deps 2018-09-24 15:53:34 +02:00
fragosti
f49b231e91 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/forwarder-helper/sra-and-rpc 2018-09-24 15:45:06 +02:00
fragosti
7a43e19116 Improve README 2018-09-24 15:43:02 +02:00
fragosti
e4b664bafa Add expiry buffer 2018-09-24 13:17:38 +02:00
Fabio Berger
8bce407aec Add order-utils to README list 2018-09-21 17:36:05 +01:00
fragosti
7a5376621f Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/forwarder-helper/sra-and-rpc 2018-09-21 17:20:48 +02:00
Leonid Logvinov
29f6adc2ed Publish
- 0x.js@1.0.4
 - @0xproject/abi-gen@1.0.9
 - @0xproject/assert@1.0.9
 - @0xproject/base-contract@2.0.3
 - @0xproject/connect@2.0.2
 - @0xproject/contract-wrappers@1.0.4
 - contracts@2.1.45
 - @0xproject/dev-utils@1.0.8
 - ethereum-types@1.0.7
 - @0xproject/fill-scenarios@1.0.3
 - @0xproject/forwarder-helper@1.0.4
 - @0xproject/json-schemas@1.0.2
 - @0xproject/metacoin@0.0.19
 - @0xproject/migrations@1.0.10
 - @0xproject/monorepo-scripts@1.0.9
 - @0xproject/order-utils@1.0.3
 - @0xproject/order-watcher@1.0.4
 - @0xproject/react-docs@1.0.9
 - @0xproject/react-shared@1.0.10
 - @0xproject/sol-compiler@1.1.3
 - @0xproject/sol-cov@2.1.3
 - @0xproject/sol-resolver@1.0.9
 - @0xproject/sra-report@1.0.9
 - @0xproject/sra-spec@1.0.2
 - @0xproject/subproviders@2.0.3
 - @0xproject/testnet-faucets@1.0.47
 - @0xproject/types@1.0.2
 - @0xproject/typescript-typings@2.0.1
 - @0xproject/utils@1.0.9
 - @0xproject/web3-wrapper@2.0.3
 - @0xproject/website@0.0.50
2018-09-21 16:59:27 +02:00
Leonid Logvinov
5446de6308 Updated CHANGELOGS 2018-09-21 16:59:16 +02:00
fragosti
5e84e9689f Small typos 2018-09-21 16:53:18 +02:00
Leonid Logvinov
9540db2aad Merge pull request #1081 from 0xProject/fix/node-types-unpin
Don't depend on a specific version of node types
2018-09-21 16:45:03 +02:00
Leonid Logvinov
7dd28d6fab Don't depend on a specific version of node types 2018-09-21 16:37:20 +02:00
fragosti
1bfaefb240 Add order provider response validation 2018-09-21 16:24:45 +02:00
fragosti
c48cf3ab3b Make asset buyer map private 2018-09-21 16:03:47 +02:00
fragosti
c64dcec772 More renaming 2018-09-21 15:58:04 +02:00
Fabio Berger
45dc2be083 Fix prettier 2018-09-21 14:53:25 +01:00
Fabio Berger
31f6fc065f Add changelog entries 2018-09-21 14:24:50 +01:00
fragosti
8dea48ebef Renamed orderFetcherResponseProcessor to orderProviderResponseProcessoer 2018-09-21 15:21:44 +02:00
fragosti
97150cf55f Add labels to TODOs 2018-09-21 14:56:54 +02:00
Fabio Berger
b0484eafe3 Upgrade blockstream to version that supports fetching logs by blockHash, fixing reliability issues 2018-09-21 13:46:10 +01:00
Fabio Berger
1b799e98e8 Add blockHash to FilterObject now that EIP234 is supported 2018-09-21 13:45:06 +01:00
Fabio Berger
e6840c60c7 Add assertion that one cannot specify both blockHash & fromBlock/toBlock to getLogsAsync 2018-09-21 13:43:06 +01:00
Fabio Berger
ba59879e7f Merge pull request #1079 from 0xProject/fixAwaitTxMined
Fix awaitTransactionMinedAsync for new Parity version
2018-09-21 11:36:58 +01:00
Fabio Berger
c10807c4e3 Add PR number 2018-09-21 11:04:30 +01:00
Fabio Berger
4e8ec2359d Also make sure the transactionReceipt contains a blockNumber when checking if a transaction has been mined. 2018-09-21 10:56:31 +01:00
Fabio Berger
cbd72b6e3d Merge pull request #1077 from PhABC/patch-1
[ethereum-types] Add BigNumber[] in ContractEventArg Type Definition
2018-09-21 00:01:25 +01:00
fragosti
fcca63a2dc Move some logic to order utils 2018-09-20 23:39:55 +02:00
Philippe Castonguay
90e28220fa Set ContractEventArg type definition to any 2018-09-20 16:19:08 -04:00
fragosti
35c324f67c Add utility to get assetDatas 2018-09-20 19:00:23 +02:00
fragosti
03e18ff7c6 Rename OrderFetcher to OrderProvider and other small improvements 2018-09-20 15:10:15 +02:00
fragosti
d23487bda9 Update descriptions for methods on AssetBuyer 2018-09-20 14:27:20 +02:00
fragosti
3238925aa4 Add better description to README 2018-09-20 14:09:11 +02:00
Philippe Castonguay
abd308455a Add BigNumber[] support in ContractEventArg
Currently, my contract has events that take a BigNumber array and typescript complains that ContractEventArg does not support this.
2018-09-19 20:17:00 -04:00
fragosti
a44f77a838 Implement StandardRelayerAPIAssetBuyerManager 2018-09-19 18:38:50 +02:00
Fabio Berger
3e70ab015b Publish
- 0x.js@1.0.3
 - @0xproject/connect@2.0.1
 - @0xproject/contract-wrappers@1.0.3
 - contracts@2.1.44
 - @0xproject/fill-scenarios@1.0.2
 - @0xproject/forwarder-helper@1.0.3
 - @0xproject/migrations@1.0.9
 - @0xproject/order-utils@1.0.2
 - @0xproject/order-watcher@1.0.3
 - @0xproject/testnet-faucets@1.0.46
 - @0xproject/website@0.0.49
2018-09-19 16:13:24 +01:00
Fabio Berger
dab7f1a739 Updated CHANGELOGS 2018-09-19 16:13:15 +01:00
Fabio Berger
f6438725eb Update changelog entries 2018-09-19 15:59:17 +01:00
fragosti
a03b1d4d6c Move ObjectMap to shared types 2018-09-19 16:48:57 +02:00
fragosti
14345ab24e Rename forceOrderRefresh to shouldForceOrderRefresh 2018-09-19 16:02:52 +02:00
fragosti
60e2dfdbda Calculate min and max rates in buy quote 2018-09-19 15:58:30 +02:00
Fabio Berger
83ffbd05be Merge pull request #1074 from 0xProject/reduceBundleSizes
Reduce published packages bundle sizes
2018-09-19 14:50:01 +01:00
Fabio Berger
88be6b5e0d Add back in evm.bytecode.object since it's needed to generate contract-wrappers 2018-09-19 13:55:09 +01:00
Fabio Berger
aa47f85f48 Make higher-order packages copy over trimmed down artifacts 2018-09-19 12:57:45 +01:00
Fabio Berger
fec9c8f1c6 Create trimmed artifacts of v2 contracts 2018-09-19 12:53:00 +01:00
fragosti
93f7e33f6a Add isValidPercentage assert 2018-09-19 00:57:05 +02:00
fragosti
fd4b4f8f82 Make ForwaderWrapper take in a number for feePercentage instead of BigNumber 2018-09-18 23:56:07 +02:00
fragosti
0003666050 make the slippage percentage customizable by integrator 2018-09-18 16:42:52 +02:00
fragosti
b947609ff1 Restrict orders field of AssetBuyerOrdersAndFillableAmounts to SignedOrder for consistency 2018-09-18 16:26:50 +02:00
fragosti
38afd108f8 Fix order expired bug 2018-09-18 16:07:47 +02:00
fragosti
65f709d50a Move all constants to own file 2018-09-18 16:07:08 +02:00
fragosti
f5dbf212e3 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/forwarder-helper/sra-and-rpc 2018-09-18 15:58:47 +02:00
fragosti
f6e1bf78c8 Add yarn.lock 2018-09-18 14:33:47 +02:00
fragosti
950f279508 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into fix/website/signing-order-validation-bug 2018-09-18 14:15:31 +02:00
fragosti
e46807c28b Fix order creation and fill flow in Portal 2018-09-18 13:55:31 +02:00
Fabio Berger
e2559798df Publish
- 0x.js@1.0.2
 - @0xproject/contract-wrappers@1.0.2
 - @0xproject/forwarder-helper@1.0.2
 - @0xproject/migrations@1.0.8
 - @0xproject/order-watcher@1.0.2
 - @0xproject/testnet-faucets@1.0.45
 - @0xproject/website@0.0.48
2018-09-18 11:18:28 +01:00
Fabio Berger
ccc18620bf Updated CHANGELOGS 2018-09-18 11:18:19 +01:00
Fabio Berger
febe00db4f Merge pull request #1072 from 0xProject/addMissingEtherTokenConfig
Add missing mainnet addresses to ZRXToken & WETH artifacts
2018-09-18 11:05:28 +01:00
Fabio Berger
6f36048a8e Add CHANGELOG entries about bug fix 2018-09-18 10:43:18 +01:00
Fabio Berger
2457ecb7e7 Add missing mainnet addresses to ZRXToken & WETH artifacts 2018-09-18 10:29:27 +01:00
Jacob Evans
2378747570 Merge pull request #1063 from 0xProject/feature/0x.js/update-readme-import
0xjs README/website docs update
2018-09-17 23:59:27 +02:00
Jacob Evans
2df569b727 Folder 1.0.0 -> 1.0.1 2018-09-17 21:33:50 +00:00
Jacob Evans
65aecc0024 Rename to v1->v0 v2->v1 2018-09-17 23:23:27 +02:00
Fabio Berger
074082ec94 Fix forwarder package.json 2018-09-17 12:53:05 +01:00
Fabio Berger
6b9f0af828 Add 0x.js 2.0.0 async and installation sections 2018-09-17 12:52:25 +01:00
Fabio Berger
bfabf765e3 Update decoration error 2018-09-17 12:52:12 +01:00
Fabio Berger
e74f736eff Update 0x.js README 2018-09-17 12:52:04 +01:00
Fabio Berger
45483557a5 Remove doc commands from forwarder-helper package for now 2018-09-17 12:45:27 +01:00
Brandon Millman
a22d2dc7ee Add factory method for specific assetData to buy and add comments 2018-09-15 15:05:27 +02:00
Brandon Millman
9ec2b5a2d5 Add factory method on AssetBuyer for specific token address 2018-09-15 14:53:04 +02:00
Brandon Millman
af40989f5f Add factory method on AssetBuyer for provided orders 2018-09-15 14:47:44 +02:00
Brandon Millman
d57619b5db Export the order fetchers 2018-09-15 14:16:08 +02:00
Brandon Millman
c692115cdc Fix lint errors 2018-09-15 14:14:55 +02:00
Brandon Millman
dfe58e4975 Delete old test 2018-09-15 14:14:55 +02:00
Brandon Millman
4e59be9afc Implement ProvidedOrderFetcher 2018-09-15 14:14:55 +02:00
Brandon Millman
190bf2599c Implement StandardRelayerAPIOrderFetcher 2018-09-15 14:14:55 +02:00
Brandon Millman
f1a22e9bd7 Flesh out the AssetBuyer class 2018-09-15 14:14:48 +02:00
Brandon Millman
7b46cef83d Create initial AssetBuyer class 2018-09-15 14:14:48 +02:00
Brandon Millman
8da7d39998 Update readme, changelog, and package.json with rename 2018-09-15 14:14:48 +02:00
Brandon Millman
91702bbae2 Move packages/forwarder-helper into packages/asset-buyer 2018-09-15 14:14:48 +02:00
Brandon Millman
90674d9038 Various clean up 2018-09-15 14:14:48 +02:00
Brandon Millman
c0a14a4a41 Catch standard relayer api errors 2018-09-15 14:14:48 +02:00
Brandon Millman
8d6132736b Remove taker address as param and filter out non-open orders 2018-09-15 14:14:48 +02:00
Brandon Millman
8687b9533c Add getForwarderHelperForMakerAssetDataAsync method to forwarderHelperFactory 2018-09-15 14:14:48 +02:00
Alex Browne
07942a7aec Merge pull request #1061 from 0xProject/feature/ci-resource-classes
Bump CircleCI resource class for build and test-publish
2018-09-13 14:49:11 +02:00
Jacob Evans
3d1b7c10e8 Remove note about RC versions 2018-09-13 14:32:46 +02:00
Jacob Evans
cf46d2c704 0xjs README/website docs update 2018-09-13 13:58:05 +02:00
Alex Browne
4434856add Bump CircleCI resource class for build and test-publish 2018-09-12 17:23:11 +02:00
fragosti
52d511df21 Change Davids description 2018-09-12 11:53:11 +02:00
fragosti
50f58f9121 Add images for David Sacks and Gene 2018-09-12 11:48:03 +02:00
fragosti
7a20c7b946 Fix David Sacks links 2018-09-12 11:46:42 +02:00
fragosti
ce0e60ed84 Merge branch 'feature/website/add-gene' into development 2018-09-12 11:43:16 +02:00
fragosti
4ad0a6c7b7 Add david sacks 2018-09-12 11:42:58 +02:00
fragosti
b8d8651e43 Add Gene info to website 2018-09-12 11:16:13 +02:00
Francesco Agosti
45b68832aa Merge pull request #1064 from 0xProject/patch/website/new-token-addresses
[website] Fix minting for new tokens on testnets
2018-09-07 16:12:50 +02:00
fragosti
6dfcaaf889 Clear localstorage 2018-09-07 13:12:53 +02:00
fragosti
8131c5d6bc Fix minting for new tokens on testnets 2018-09-07 13:05:11 +02:00
Amir Bandeali
df5779b6d1 Link bug bounty section to wiki 2018-09-05 12:10:39 -07:00
Amir Bandeali
4a5a0c8c78 Update README with directory structure and bug bounty 2018-09-05 11:37:48 -07:00
Jacob Evans
b3a17624c8 Merge pull request #1060 from 0xProject/feature/testnet-faucets/v2
[testnet-faucets] update to v2
2018-09-05 18:33:50 +01:00
Jacob Evans
e63841a604 Check token exists for network for user params 2018-09-05 18:11:57 +01:00
Jacob Evans
7ec95e8c29 Remove unused name and symbol 2018-09-05 16:04:52 +01:00
Jacob Evans
b217495465 Floor expiration time 2018-09-05 15:57:40 +01:00
Jacob Evans
db6ddc0c4b [testnet-faucets] update to v2 2018-09-05 15:13:21 +01:00
Fabio Berger
174b360593 Publish
- 0x.js@1.0.1
 - @0xproject/abi-gen@1.0.8
 - @0xproject/assert@1.0.8
 - @0xproject/base-contract@2.0.2
 - @0xproject/connect@2.0.0
 - @0xproject/contract-wrappers@1.0.1
 - contracts@2.1.43
 - @0xproject/dev-utils@1.0.7
 - ethereum-types@1.0.6
 - @0xproject/fill-scenarios@1.0.1
 - @0xproject/forwarder-helper@1.0.1
 - @0xproject/json-schemas@1.0.1
 - @0xproject/metacoin@0.0.18
 - @0xproject/migrations@1.0.7
 - @0xproject/monorepo-scripts@1.0.8
 - @0xproject/order-utils@1.0.1
 - @0xproject/order-watcher@1.0.1
 - @0xproject/react-docs@1.0.8
 - @0xproject/react-shared@1.0.9
 - @0xproject/sol-compiler@1.1.2
 - @0xproject/sol-cov@2.1.2
 - @0xproject/sol-resolver@1.0.8
 - @0xproject/sra-report@1.0.8
 - @0xproject/sra-spec@1.0.1
 - @0xproject/subproviders@2.0.2
 - @0xproject/testnet-faucets@1.0.44
 - @0xproject/tslint-config@1.0.7
 - @0xproject/types@1.0.1
 - @0xproject/typescript-typings@2.0.0
 - @0xproject/utils@1.0.8
 - @0xproject/web3-wrapper@2.0.2
 - @0xproject/website@0.0.47
2018-09-05 11:16:45 +01:00
Fabio Berger
481a752e70 Updated CHANGELOGS 2018-09-05 11:16:34 +01:00
Fabio Berger
38acdfd632 Update CHANGELOG's to publish non-RC versions 2018-09-05 11:06:11 +01:00
Francesco Agosti
561e525778 Merge pull request #1058 from 0xProject/fix/connect/use-big-number-in-requests
[connect] Use BigNumber instead of string where appropriate in OrderConfigRequest
2018-09-04 17:25:51 -07:00
fragosti
69eb820d0d Change orderConfig from POST to GET like in spec 2018-09-04 15:49:30 -07:00
Alex Browne
447f16fc4f Merge pull request #1057 from 0xProject/deployment/copy-testnet-artifacts
Remove/rename/update all artifacts in preparation for v2 launch
2018-09-04 18:31:48 -04:00
Alex Browne
1769609245 Update order-watcher/package.json 2018-09-04 18:17:51 -04:00
Alex Browne
e1dcdac1bb add packages/sol-cov/test/fixtures/artifacts to .prettierignore 2018-09-04 18:14:59 -04:00
Alex Browne
9d45d19c80 More small artifacts updates/changes 2018-09-04 18:10:23 -04:00
Alex Browne
9858bb0ce4 Fix bug in contracts tests 2018-09-04 18:10:13 -04:00
fragosti
a3527a77a6 Add to CHANGELOG 2018-09-04 14:49:39 -07:00
fragosti
33a45fa739 Use BigNumber instead of string where appropriate in OrderConfigRequest 2018-09-04 14:44:56 -07:00
Alex Browne
e70882a657 More small chnages/bug fixes 2018-09-04 17:22:22 -04:00
Alex Browne
e456332da7 Rename and update some artifact locations 2018-09-04 16:47:28 -04:00
Alex Browne
4ed84c5dc5 Rename 2.0.0-beta-testnet to 2.0.0-testnet 2018-09-04 16:11:17 -04:00
Alex Browne
2fe3f40be9 Add missing testnet addresses to 2.0.0-mainnet artifacts 2018-09-04 16:09:59 -04:00
Alex Browne
44bfdb718f Copy artifacts from 2.0.0-beta-testnet that do not appear in 2.0.0-mainnet 2018-09-04 16:09:44 -04:00
Alex Browne
3524efc41c Merge pull request #1055 from 0xProject/deployment/2.0.0-beta-testnet/ropsten
Ropsten/Kovan Contract deployment
2018-09-04 15:54:48 -04:00
Francesco Agosti
01210c291c Merge pull request #1044 from 0xProject/feature/website/update-portal-v2
[website] Update portal for v2
2018-09-04 12:37:53 -07:00
Jacob Evans
192d4b4dbf Merge branch 'deployment/2.0.0-beta-testnet/ropsten' of github.com:0xProject/0x-monorepo into deployment/2.0.0-beta-testnet/ropsten 2018-09-04 20:32:43 +01:00
Jacob Evans
68246fc335 Revert Forwarder address for Ganache 2018-09-04 20:29:01 +01:00
Fabio Berger
7ef86636aa merge development 2018-09-04 20:26:02 +01:00
Fabio Berger
a5859c6cee Merge pull request #1038 from 0xProject/feature/contracts/mainnetMigrations
Mainnet migrations
2018-09-04 20:23:48 +01:00
Fabio Berger
3463903d02 Merge branch 'deployment/2.0.0-beta-testnet/ropsten' of github.com:0xProject/0x-monorepo into deployment/2.0.0-beta-testnet/ropsten
* 'deployment/2.0.0-beta-testnet/ropsten' of github.com:0xProject/0x-monorepo:
  Revert the exchange address change
  Tslint magic-number
2018-09-04 20:22:32 +01:00
Jacob Evans
4b0f1a8431 Remove Rinkeby from Exchange.json 2018-09-04 20:21:50 +01:00
Jacob Evans
603e8aa671 Revert the exchange address change 2018-09-04 20:18:23 +01:00
fragosti
6eb980abe2 Add to changelog 2018-09-04 12:11:17 -07:00
fragosti
46b168e10f Run linter 2018-09-04 12:09:24 -07:00
Jacob Evans
508e6ccf89 Tslint magic-number 2018-09-04 19:57:05 +01:00
fragosti
a173c5fc38 Merge branch 'feature/website/update-portal-v2' of https://github.com/0xProject/0x-monorepo into feature/website/update-portal-v2 2018-09-04 11:55:42 -07:00
fragosti
f5237f7971 Use order parser utils from order utils 2018-09-04 11:55:08 -07:00
Amir Bandeali
6f7a5d00e6 Update prettierignore 2018-09-04 11:47:26 -07:00
Fabio Berger
4061723863 merge back weth9 2018-09-04 19:42:54 +01:00
Jacob Evans
ab1b52ba87 Ropsten/Kovan Contract deployment 2018-09-04 19:41:05 +01:00
Fabio Berger
16e94ecb40 Merge branch 'deployment/2.0.0-beta-testnet/ropsten' of github.com:0xProject/0x-monorepo into deployment/2.0.0-beta-testnet/ropsten
* 'deployment/2.0.0-beta-testnet/ropsten' of github.com:0xProject/0x-monorepo:
  Ropsten/Kovan Contract deployment
2018-09-04 19:35:48 +01:00
Jacob Evans
6bb2c5877c Ropsten/Kovan Contract deployment 2018-09-04 19:29:40 +01:00
fragosti
a14450f367 Add order parsers to order-util 2018-09-04 11:22:31 -07:00
Amir Bandeali
85df313a7a Update mainnet artifacts 2018-09-04 11:07:56 -07:00
Amir Bandeali
66ed6b9b88 Update mainnet configs 2018-09-04 11:07:56 -07:00
Amir Bandeali
9304d09da6 Add mainnet migrations 2018-09-04 11:07:56 -07:00
fragosti
e61dbbb6cf Merge https://github.com/0xProject/0x-monorepo into feature/website/update-portal-v2 2018-09-04 10:53:18 -07:00
Fabio Berger
1690f59857 Remove unused imports and console.log 2018-09-04 18:42:50 +01:00
Fabio Berger
c916dd6ebb Add back order validation logic 2018-09-04 18:39:53 +01:00
Fabio Berger
8a683b8541 Fix imports 2018-09-04 18:37:41 +01:00
Fabio Berger
4883b8be10 remove console log 2018-09-04 18:37:33 +01:00
Fabio Berger
51760f9bdd merge development 2018-09-04 18:37:24 +01:00
Fabio Berger
6a619a4084 Merge pull request #1054 from 0xProject/addValidationMethods
Temporarily Add Back Validation Methods
2018-09-04 18:04:03 +01:00
Jacob Evans
feeafa193a Ropsten/Kovan Contract deployment 2018-09-04 18:01:21 +01:00
Fabio Berger
8d8528996a Export abstract fetchers 2018-09-04 17:44:27 +01:00
Amir Bandeali
965d609829 Merge pull request #1050 from 0xProject/refactor/contracts/multisig
Update MultiSig and add more tests
2018-09-04 09:12:16 -07:00
Leonid Logvinov
a52714bcf3 Merge pull request #1052 from 0xProject/feature/remove-types
[typescript-typings] Remove types that were moved to DefinitelyTyped
2018-09-04 17:54:54 +02:00
Fabio Berger
bbfd7647a8 Export missing type 2018-09-04 16:52:21 +01:00
Fabio Berger
0aba5a3be4 Merge branch 'development' into addValidationMethods
* development:
  Remove unused imports
2018-09-04 16:51:27 +01:00
Fabio Berger
61bf5864a8 Merge branch 'development' of github.com:0xProject/0x-monorepo into development
* 'development' of github.com:0xProject/0x-monorepo:
  Remove unused imports
2018-09-04 16:51:15 +01:00
Fabio Berger
56847a53f4 Add PR nr 2018-09-04 16:41:43 +01:00
Fabio Berger
8324ab3af7 Update yarn.lock 2018-09-04 16:27:26 +01:00
Fabio Berger
d496a7585c Add validateFillOrderThrowIfInvalidAsync and validateOrderFillableOrThrowAsync to ExchangeWrapper 2018-09-04 16:27:16 +01:00
Fabio Berger
8d7f2a993a Import fetchers from contract-wrappers 2018-09-04 16:24:01 +01:00
Fabio Berger
ed786f3e8f Export fetchers from contract-wrappers 2018-09-04 16:23:29 +01:00
Fabio Berger
539c243733 Move fetchers to contract-wrappers 2018-09-04 16:23:02 +01:00
Leonid Logvinov
40e0c829b3 Fix the version 2018-09-04 17:06:09 +02:00
Amir Bandeali
e34b1f2f8b Remove TODOs that will not be addressed 2018-09-04 07:57:47 -07:00
Amir Bandeali
f6b6619c08 Fix geth tests 2018-09-04 07:57:47 -07:00
Amir Bandeali
e480e08aa4 Add test for external_call visibility 2018-09-04 07:57:47 -07:00
Amir Bandeali
652cf7a976 Add MultiSigWalletWithTimeLock revert reasons to tests 2018-09-04 07:57:47 -07:00
Amir Bandeali
7a8ab6fbe8 Update MultiSigWalletWithTimeLock to 0.4.24 2018-09-04 07:57:47 -07:00
Amir Bandeali
9deec8ec35 Add more tests for MultiSigWalletWithTimeLock 2018-09-04 07:57:47 -07:00
Amir Bandeali
3f1586045c Add test for executeRemoveAuthorizedAddressAtIndex when called by non-owner 2018-09-04 07:57:47 -07:00
Amir Bandeali
ada5563b1f Update to most recent multisig 2018-09-04 07:57:47 -07:00
Leonid Logvinov
6b41a570a5 Change doc gen configs 2018-09-04 16:36:18 +02:00
Leonid Logvinov
cebf6bfb34 Move types used in public interfaces to dependencies 2018-09-04 16:36:18 +02:00
Leonid Logvinov
47a1b48ad8 Add temporarily missing web3-provider-engine types in website 2018-09-04 16:36:18 +02:00
Leonid Logvinov
ef82a9d2a6 Add CHANGELOG entry 2018-09-04 16:36:18 +02:00
Leonid Logvinov
ba6351841d Add temporarily missing web3-provider-engine types in subproviders 2018-09-04 16:36:18 +02:00
Leonid Logvinov
cdc786a1e3 Remove types for web3-provider-engine from typescript-typings 2018-09-04 16:36:18 +02:00
Leonid Logvinov
3ea137a78f Remove types for eth-lightwallet from typescript-typings 2018-09-04 16:36:18 +02:00
Leonid Logvinov
b525ccc825 Remove types for detect-node from typescript-typings 2018-09-04 16:36:18 +02:00
Leonid Logvinov
77acbdd3ea Remove types for ganache-core from typescript-typings 2018-09-04 16:36:18 +02:00
Leonid Logvinov
c13190ceab Remove types for newman from typescript-typings 2018-09-04 16:36:18 +02:00
Leonid Logvinov
78d4fc59a5 Merge pull request #1053 from 0xProject/fix/linter_issues
[website] Remove unused imports
2018-09-04 16:35:54 +02:00
Leonid Logvinov
f9e86c057d Remove unused imports 2018-09-04 16:08:35 +02:00
Amir Bandeali
1d8e133a30 Merge pull request #1051 from 0xProject/fix/contracts/style
Apply styling fixes to contracts
2018-09-03 21:22:03 -07:00
Amir Bandeali
99fbf384fd Apply styling fixes 2018-09-03 20:55:37 -07:00
Amir Bandeali
cb4fcf4de7 Revert in Forwarder constructor if ERC20 proxy isn't registered 2018-09-03 20:35:00 -07:00
Brandon Millman
675964dc5c Merge pull request #1048 from 0xProject/feature/website/patch-v2-landing
[website] Final tweaks for landing page
2018-08-30 17:26:47 -07:00
Brandon Millman
6432f85eb0 Wording change for first benefit 2018-08-30 17:14:17 -07:00
Francesco Agosti
66eef758c6 Merge pull request #1047 from 0xProject/feature/re-add-no-unused-variables
Re-add no-unused-variable tslint rule
2018-08-30 15:38:21 -07:00
Brandon Millman
c64f0ba34b Tweaks to benefits and use cases 2018-08-30 15:26:03 -07:00
Brandon Millman
6deffb6b28 Update yarn lock 2018-08-30 15:19:33 -07:00
Greg Hysen
5802713801 Merge pull request #1046 from 0xProject/fix/contracts/roundingFeeTestsMatchOrders
Test cases for rounding fees in matchOrders
2018-08-30 14:27:01 -07:00
Brandon Millman
11df29fa8e Update exchange ABI for decoding logs 2018-08-30 14:23:09 -07:00
Brandon Millman
f4a41e80b8 Remove LogError legacy stuff 2018-08-30 14:04:55 -07:00
Brandon Millman
5c655b55d3 Update comment for validation 2018-08-30 14:01:04 -07:00
Brandon Millman
63c15b6f4f Remove commented out block 2018-08-30 14:00:10 -07:00
Brandon Millman
4f2bc29744 Remove cancel check 2018-08-30 13:59:42 -07:00
fragosti
2cac431c41 Final tweaks for landing page 2018-08-30 13:53:30 -07:00
fragosti
80b7a7842c run prettier 2018-08-30 13:47:33 -07:00
Brandon Millman
8c7cec9822 Merge pull request #1040 from 0xProject/feature/website/v2-tweaks
[website] Landing page tweaks for v2 launch
2018-08-30 13:46:37 -07:00
Brandon Millman
971a4087d2 Update yarn lock 2018-08-30 13:36:44 -07:00
Brandon Millman
660e670d38 Update generate and fill order flows 2018-08-30 13:36:44 -07:00
Brandon Millman
052824f4e3 Token registry from old 0x version 2018-08-30 13:36:44 -07:00
fragosti
1d5ef4d0ca Fix unused vars for react-shared and website 2018-08-30 13:28:07 -07:00
Brandon Millman
a6440b94f4 Fix import 2018-08-30 13:24:24 -07:00
Brandon Millman
01685b7622 Fix contract not deployed on network bug in ContractWrapper class 2018-08-30 13:24:24 -07:00
Brandon Millman
397fefa8d7 Update typings version 2018-08-30 13:24:24 -07:00
Brandon Millman
82a01ef020 Initial changes for v2 portal 2018-08-30 13:24:24 -07:00
Brandon Millman
a224ce347e Revert whats new text 2018-08-30 13:21:07 -07:00
Amir Bandeali
81ba2a8411 Merge pull request #1045 from 0xProject/feature/contracts/cancelOrderInternal
Add cancelOrderInternal, use within batchCancelOrders
2018-08-30 13:07:51 -07:00
Amir Bandeali
a6e8b28da5 Merge pull request #1043 from 0xProject/feature/contracts/edgeCaseTests
Add edge case tests
2018-08-30 13:07:19 -07:00
Brandon Millman
e90dbf66f3 Add new exchange everywhere graphic 2018-08-30 12:29:47 -07:00
Greg Hysen
0be2219beb Test cases for rounding fees in matchOrders 2018-08-30 12:23:11 -07:00
Amir Bandeali
09b4d5e0e4 Add cancelOrderInternal, use within batchCancelOrders 2018-08-30 12:10:24 -07:00
Brandon Millman
60f1bcf51f Remove unused render methods in landing page 2018-08-30 12:09:54 -07:00
Brandon Millman
431ac3b401 Update yarn lock 2018-08-30 12:05:29 -07:00
Francesco Agosti
50781bd77a Merge pull request #1042 from 0xProject/feature/website/v2-tweaks-fra
[website] Add rotating text to landing header and careers button to topbar
2018-08-30 11:55:28 -07:00
fragosti
c3361bb86e Remove conflict strings 2018-08-30 11:52:08 -07:00
fragosti
fd5ad69c26 Add careers page to top bar 2018-08-30 11:49:27 -07:00
fragosti
b1f97a27f3 Final tweaks 2018-08-30 11:49:27 -07:00
fragosti
febddcb356 Remove redundant import 2018-08-30 11:49:27 -07:00
fragosti
74d5af34eb Add TypedText component and use it on landing page 2018-08-30 11:49:27 -07:00
fragosti
365890291f Add generic title changes 2018-08-30 11:48:49 -07:00
Brandon Millman
0368de701f Added todo comments for missing items 2018-08-30 11:44:09 -07:00
Brandon Millman
f5e7b7e7e0 Add title header to use cases section 2018-08-30 11:39:25 -07:00
Brandon Millman
038c21324e Make hero image responsive 2018-08-30 11:39:25 -07:00
Brandon Millman
5d008ee83e Update what's new styling 2018-08-30 11:39:25 -07:00
Amir Bandeali
d0f6933980 Add tests for token that returns >32 bytes 2018-08-30 09:27:28 -07:00
Amir Bandeali
14793f30b5 Add more proxy tests 2018-08-30 09:27:28 -07:00
Amir Bandeali
86319291e3 Update used addresses for authorizable tests 2018-08-30 09:27:28 -07:00
Amir Bandeali
afa2dd7374 Add test for fillOrder and dispatchTransferFrom where maker == taker 2018-08-30 09:26:44 -07:00
fragosti
1312e4caf2 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into feature/website/v2-tweaks 2018-08-29 16:39:25 -07:00
Amir Bandeali
eb4517d737 Merge pull request #1041 from 0xProject/refactor/contracts/assetProxyOwnerVersion
Update AssetProxyOwner to 0.4.24, remove redundant code
2018-08-29 15:57:53 -07:00
Amir Bandeali
d80701c277 Fix geth tests 2018-08-29 15:35:09 -07:00
Amir Bandeali
bf3ab1127d Remove unused imports 2018-08-29 14:42:42 -07:00
Amir Bandeali
dcb12b6ad6 Update AssetProxyOwner to 0.4.24 2018-08-29 14:12:10 -07:00
Francesco Agosti
f87420a776 Merge pull request #1023 from 0xProject/website/feature/react-16
[website] Upgrade all the things to React 16
2018-08-29 14:04:17 -07:00
Greg Hysen
6cedf5362b Merge pull request #1039 from 0xProject/fix/contracts/audit2Fixes
Fixes as-per Audit for LibBytes + ERC20 Proxy Comments
2018-08-29 13:53:49 -07:00
Greg Hysen
aa833ef074 Typos in LibBytes tests 2018-08-29 13:26:46 -07:00
Greg Hysen
5f1c9cfee5 Reverted syntax used by readBytes4 in AssetProxyOwner to be compatible with Solidity v0.4.10 2018-08-29 13:15:40 -07:00
Greg Hysen
62b93cf2eb More tests for LibBytes 2018-08-29 13:14:51 -07:00
Brandon Millman
b1c5f6e8f1 Update use cases section 2018-08-29 12:45:24 -07:00
Brandon Millman
3bc9b309f6 Update tokenization section 2018-08-29 12:45:24 -07:00
Brandon Millman
6924a2b681 Update benefits 2018-08-29 12:45:24 -07:00
Brandon Millman
d93d4c34f5 Update whats new 2018-08-29 12:45:24 -07:00
Brandon Millman
557267477e Add new header image 2018-08-29 12:45:16 -07:00
Brandon Millman
b9f7979e91 Replace projects section with relayers 2018-08-29 12:45:15 -07:00
Greg Hysen
8c803ab232 Updated comments for ERC20 proxy to clarify how we load the token address from calldata (3.18 from audit) 2018-08-29 12:25:06 -07:00
fragosti
422e5e4dd7 Apply prettier 2018-08-29 11:57:52 -07:00
fragosti
2aea820d89 Merge branch 'development' of https://github.com/0xProject/0x-monorepo into website/feature/react-16 2018-08-29 11:42:44 -07:00
Greg Hysen
1c3b2b7141 Updated readBytes4 to match spec + added unit tests. These are 3.5/3.6 from audit 2018-08-29 11:39:52 -07:00
Alex Browne
e7d5ceb9c5 feat: Add support for TypeScript project references (#991)
* Update all package.json and tsconfig.json

* fix(contracts): Make test/utils/web3_wrapper.ts compatible with project refs

* Fix webpack config for 0x.js

* Fix linter errors by adding rootDir to tsconfig.json as needed

* Add build:ts and watch:ts commands to package.json

* Update sra-spec to work with project references

* Update tsconfig.json with latest new/removed packages

* Add TypeScript as devDependency at root

* Add missing rootDir to forwarder-helper package

* Use a separate tsconfig file for typedoc

* Fix linter errors

* Apply PR feedback (add comments)

* Fix 0x.js tsconfig
2018-08-29 11:15:30 -07:00
fragosti
68af0e9eb7 Change VersionDropDown to use material-ui 3 2018-08-28 18:08:06 -07:00
fragosti
a18d0f6229 Upgrade version of react-shared in website 2018-08-28 17:49:15 -07:00
fragosti
031807df9c Upgrade react-copy-to-clipboard 2018-08-28 15:52:09 -07:00
fragosti
72710be04b Remove react-tap-event-plugin from react-shared 2018-08-28 15:37:20 -07:00
fragosti
ac135d55d3 Upgrade material ui in react-docs 2018-08-28 15:32:15 -07:00
fragosti
1d55e94659 Update lockfile 2018-08-28 15:27:24 -07:00
fragosti
86284f1c7e Merge branch 'development' of https://github.com/0xProject/0x-monorepo into website/feature/react-16 2018-08-28 15:25:08 -07:00
fragosti
61a4ae7fc4 Update material-ui in react-shared 2018-08-28 15:15:54 -07:00
fragosti
55fab3d98f Revert "Simplify dropdown component"
This reverts commit 91a9014a50.
2018-08-28 15:07:29 -07:00
fragosti
de11b62e30 Revert "Have new Popover component working in React 16"
This reverts commit 5785ec0713.
2018-08-28 15:07:28 -07:00
fragosti
8e14e65b60 Revert "Enable hovering state for dropdown"
This reverts commit ac1640140c.
2018-08-28 15:07:24 -07:00
fragosti
2d1d14d2e4 Upgrade material ui to 0.20.0 2018-08-28 15:04:34 -07:00
Brandon Millman
f44644ad90 Merge pull request #1022 from 0xProject/feature/contract-wrappers/order-validator
[contract-wrappers] Write wrapper for OrderValidator contract
2018-08-28 14:20:57 -07:00
fragosti
ac1640140c Enable hovering state for dropdown 2018-08-28 13:53:49 -07:00
Greg Hysen
1402a0aa22 Merge pull request #1036 from 0xProject/fix/contracts/calculateFillResults
Making rounding consistent in calculateFillResults
2018-08-28 13:51:38 -07:00
Amir Bandeali
f225f9e7c8 Making rounding consistent in calculateFillResults 2018-08-28 13:25:05 -07:00
Amir Bandeali
14fdb71a71 safeGetPartialAmount (#1035)
* Added Test "Should transfer correct amounts when left order is fully filled and values pass isRoundingErrorCeil but fail isRoundingErrorFloor"

* Added RoundingError exception to reference function for getPartialAmount

* Added RoundingError exception to reference function for getPartialAmount

* Added isRoundingErrorCeil to getPartialAmountCeil reference funtion

* Computed new values  for "Should give right maker a better buy price when correct price is not integral" that does not have a rounding error

* Almost all tests for match orders are passing after adding isRoundingErrorCeil check

* WIP commit: Added rounding error checks to getPartialAmount

* WIP commit: Added rounding error checks to getPartialAmount

* Use safe versions of getPartialAmount

* Update Exchange internals tests

* Run linter

* Found new values for "Should transfer correct amounts when right order fill amount deviates from amount derived by `Exchange.fillOrder`"

* Fixed merge conflicts

* Run all tests

* Cleaned up some comments on match Orders tests

* Fix tests for geth
2018-08-28 13:00:49 -07:00
Brandon Millman
9c4c4fb19a Export missing types and add OrderValidatorWrapper to hidden constructors 2018-08-28 12:03:21 -07:00
fragosti
5785ec0713 Have new Popover component working in React 16 2018-08-27 18:29:35 -07:00
Alex Browne
2eab0e30b7 fix(contracts): Catch cases where the actual error differs from the expected error (#1032)
* Catch cases where the actual error differs from the expected error

* Add tests for testWithReferenceFuncAsync

* Small style and comment fixes
2018-08-27 16:07:38 -07:00
Brandon Millman
2c846ff145 Add OrderValidatorWrapper to public interface 2018-08-27 16:06:34 -07:00
Brandon Millman
ca0dfc6610 Add contract-wrappers changelog entry for OrderValidatorWrapper 2018-08-27 13:57:48 -07:00
Brandon Millman
0fd44ee2c1 Fix broken test 2018-08-27 13:53:51 -07:00
Brandon Millman
7271fc0bab Add getBalancesAndAllowances to wrapper 2018-08-27 13:49:44 -07:00
Brandon Millman
6c039bbeb1 Update OrderValidator artifact to include getBalancesAndAllowances function 2018-08-27 13:43:19 -07:00
Brandon Millman
38e6d26145 Add params to all function comments 2018-08-27 13:31:12 -07:00
Brandon Millman
b0f210dea9 Add getERC721Owner to wrapper 2018-08-27 13:21:14 -07:00
Brandon Millman
f7469080f9 Update getOrdersAndTradersInfo to return an array instead 2018-08-27 13:21:10 -07:00
Amir Bandeali
fb5ea5d99f Merge pull request #1030 from 0xProject/fix/contracts/forwarderFillOrderNoThrow
Remove redundant mstores from fillOrderNoThrow
2018-08-27 13:07:57 -07:00
Brandon Millman
be2f4cbdca Add getBalanceAndAllowance to wrapper 2018-08-27 13:04:54 -07:00
Brandon Millman
68f2dc11b4 Add getTraderInfo and getTradersInfo to wrapper 2018-08-27 13:04:54 -07:00
Brandon Millman
d6c670dfcb Add getOrderAndTraderInfoAsync to wrapper 2018-08-27 13:04:54 -07:00
Brandon Millman
0736c41357 Add test for order validator 2018-08-27 13:04:54 -07:00
Brandon Millman
898bd75a18 Remove some unused variables in forwarder wrapper test 2018-08-27 13:04:54 -07:00
Brandon Millman
260313a6ae Initial OrderValidator wrapper 2018-08-27 13:04:54 -07:00
Amir Bandeali
6a99bfa68e Add clarifying comments 2018-08-27 12:01:58 -07:00
Amir Bandeali
f60adbdd72 Remove redundant mstores from fillOrderNoThrow 2018-08-27 11:54:20 -07:00
Alex Browne
1be310cef4 Merge pull request #1031 from 0xProject/fix/internal-tests-division-by-zero-assertion
Use correct error message for division by zero
2018-08-27 11:48:47 -07:00
Alex Browne
ff4f86f1d6 fix(contracts): Use correct error message for division by zero 2018-08-27 11:19:25 -07:00
Fabio Berger
f4a4fefe42 Exit with non-error code at end of publishRelease 2018-08-27 15:02:12 +01:00
fragosti
91a9014a50 Simplify dropdown component 2018-08-24 16:48:48 -07:00
fragosti
ad161a973e Change all onTouchTap to onClick 2018-08-24 15:59:14 -07:00
fragosti
103e1aa250 Upgrade typescript version used by sra-spec 2018-08-24 15:45:43 -07:00
fragosti
641d86cb98 Add typescript dependency to typescript-typings (no idea how it was working) 2018-08-24 15:40:04 -07:00
fragosti
813b2ca1fb Bump react-highlight in react-shared once more 2018-08-24 15:29:22 -07:00
fragosti
ec96c3bb77 Upgrade react-shared used by website to one that depends on react 16 2018-08-24 15:15:55 -07:00
fragosti
65120e84e2 Upgrade react-highlight to version that depends on React 16 2018-08-24 15:11:14 -07:00
fragosti
374ee2db32 Upgrade react in react-docs 2018-08-24 15:05:46 -07:00
fragosti
48ab151ec2 Update react and remove tap event plugin [deprecated] 2018-08-24 14:20:55 -07:00
fragosti
44a430802e Merge branch 'development' of https://github.com/0xProject/0x-monorepo into website/feature/react-16 2018-08-24 13:38:30 -07:00
fragosti
6b03cfd40d Add new react and types 2018-08-24 12:05:54 -07:00
457 changed files with 42528 additions and 110476 deletions

View File

@@ -2,6 +2,7 @@ version: 2
jobs:
build:
resource_class: medium+
docker:
- image: circleci/node:9
environment:
@@ -50,7 +51,7 @@ jobs:
test-contracts-geth:
docker:
- image: circleci/node:9
- image: albrow/0x-devnet
- image: 0xorg/devnet
working_directory: ~/repo
steps:
- restore_cache:
@@ -60,9 +61,10 @@ jobs:
# initialized
- run: sleep 10 && TEST_PROVIDER=geth yarn wsrun test contracts
test-publish:
resource_class: medium+
docker:
- image: circleci/node:9
- image: verdaccio/verdaccio
- image: 0xorg/verdaccio
working_directory: ~/repo
steps:
- restore_cache:

5
.gitignore vendored
View File

@@ -88,7 +88,7 @@ packages/0x.js/src/artifacts/
packages/order-utils/src/artifacts/
# unstable generated contract artifacts:
packages/migrations/artifacts/2.0.0/
packages/migrations/artifacts/development/
# generated contract watcher
packages/0x.js/src/generated_contract_wrappers/
@@ -99,8 +99,9 @@ packages/fill-scenarios/src/generated_contract_wrappers/
packages/order-watcher/src/generated_contract_wrappers/
packages/order-utils/src/generated_contract_wrappers/
packages/migrations/src/1.0.0/contract_wrappers
packages/migrations/src/2.0.0-testnet/contract_wrappers
packages/migrations/src/2.0.0/contract_wrappers
packages/migrations/src/2.0.0-beta-testnet/contract_wrappers
packages/migrations/src/development/contract_wrappers
# solc-bin in sol-compiler
packages/sol-compiler/solc_bin/

View File

@@ -8,8 +8,8 @@ lib
/packages/order-watcher/src/generated_contract_wrappers/
/packages/order-utils/src/generated_contract_wrappers/
/packages/migrations/src/1.0.0/contract_wrappers
/packages/migrations/src/2.0.0-testnet/contract_wrappers
/packages/migrations/src/2.0.0/contract_wrappers
/packages/migrations/src/2.0.0-beta-testnet/contract_wrappers
/packages/0x.js/src/artifacts
/packages/contracts/src/artifacts
/packages/contract-wrappers/src/artifacts
@@ -19,7 +19,9 @@ lib
/packages/contract-wrappers/test/artifacts
/packages/order-watcher/test/artifacts
/packages/migrations/artifacts/1.0.0
/packages/migrations/artifacts/2.0.0-testnet
/packages/migrations/artifacts/2.0.0
/packages/migrations/artifacts/2.0.0-beta-testnet
/packages/migrations/artifacts/development
package.json
scripts/postpublish_utils.js
packages/sol-cov/test/fixtures/artifacts

View File

@@ -27,15 +27,16 @@ If you're developing on 0x now or are interested in using 0x infrastructure in t
| [`@0xproject/assert`](/packages/assert) | [![npm](https://img.shields.io/npm/v/@0xproject/assert.svg)](https://www.npmjs.com/package/@0xproject/assert) | Type and schema assertions used by our packages |
| [`@0xproject/base-contract`](/packages/base-contract) | [![npm](https://img.shields.io/npm/v/@0xproject/base-contract.svg)](https://www.npmjs.com/package/@0xproject/base-contract) | BaseContract used by auto-generated `abi-gen` wrapper contracts |
| [`@0xproject/connect`](/packages/connect) | [![npm](https://img.shields.io/npm/v/@0xproject/connect.svg)](https://www.npmjs.com/package/@0xproject/connect) | A Javascript library for interacting with the Standard Relayer API |
| [`@0xproject/sol-compiler`](/packages/sol-compiler) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-compiler.svg)](https://www.npmjs.com/package/@0xproject/sol-compiler) | A thin wrapper around Solc.js that outputs artifacts, resolves imports, only re-compiles when needed, and other niceties. |
| [`@0xproject/dev-utils`](/packages/dev-utils) | [![npm](https://img.shields.io/npm/v/@0xproject/dev-utils.svg)](https://www.npmjs.com/package/@0xproject/dev-utils) | Dev utils to be shared across 0x projects and packages |
| [`@0xproject/json-schemas`](/packages/json-schemas) | [![npm](https://img.shields.io/npm/v/@0xproject/json-schemas.svg)](https://www.npmjs.com/package/@0xproject/json-schemas) | 0x-related json schemas |
| [`@0xproject/monorepo-scripts`](/packages/monorepo-scripts) | [![npm](https://img.shields.io/npm/v/@0xproject/monorepo-scripts.svg)](https://www.npmjs.com/package/@0xproject/monorepo-scripts) | Monorepo scripts |
| [`@0xproject/order-utils`](/packages/order-utils) | [![npm](https://img.shields.io/npm/v/@0xproject/order-utils.svg)](https://www.npmjs.com/package/@0xproject/order-utils) | A set of utilities for generating, parsing, signing and validating 0x orders. |
| [`@0xproject/react-docs`](/packages/react-docs) | [![npm](https://img.shields.io/npm/v/@0xproject/react-docs.svg)](https://www.npmjs.com/package/@0xproject/react-docs) | React documentation component for rendering TypeDoc & Doxity generated JSON |
| [`@0xproject/react-shared`](/packages/react-shared) | [![npm](https://img.shields.io/npm/v/@0xproject/react-shared.svg)](https://www.npmjs.com/package/@0xproject/react-shared) | 0x shared react components |
| [`@0xproject/sol-compiler`](/packages/sol-compiler) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-compiler.svg)](https://www.npmjs.com/package/@0xproject/sol-compiler) | A thin wrapper around Solc.js that outputs artifacts, resolves imports, only re-compiles when needed, and other niceties. |
| [`@0xproject/sol-cov`](/packages/sol-cov) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-cov.svg)](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
| [`@0xproject/sra-spec`](/packages/sra-spec) | [![npm](https://img.shields.io/npm/v/@0xproject/sra-spec.svg)](https://www.npmjs.com/package/@0xproject/sra-spec) | OpenAPI specification for the standard relayer API |
| [`@0xproject/sra-report`](/packages/sra-report) | [![npm](https://img.shields.io/npm/v/@0xproject/sra-report.svg)](https://www.npmjs.com/package/@0xproject/sra-report) | Generate reports for standard relayer API compliance |
| [`@0xproject/sol-cov`](/packages/sol-cov) | [![npm](https://img.shields.io/npm/v/@0xproject/sol-cov.svg)](https://www.npmjs.com/package/@0xproject/sol-cov) | Solidity test coverage tool |
| [`@0xproject/subproviders`](/packages/subproviders) | [![npm](https://img.shields.io/npm/v/@0xproject/subproviders.svg)](https://www.npmjs.com/package/@0xproject/subproviders) | Useful web3 subproviders (e.g LedgerSubprovider) |
| [`@0xproject/tslint-config`](/packages/tslint-config) | [![npm](https://img.shields.io/npm/v/@0xproject/tslint-config.svg)](https://www.npmjs.com/package/@0xproject/tslint-config) | Custom 0x development TSLint rules |
| [`@0xproject/types`](/packages/types) | [![npm](https://img.shields.io/npm/v/@0xproject/types.svg)](https://www.npmjs.com/package/@0xproject/types) | Shared type declarations |

View File

@@ -23,10 +23,11 @@
"install:all": "yarn install",
"wsrun": "wsrun",
"lerna": "lerna",
"watch": "wsrun watch_without_deps $PKG --fast-exit -r --stages --done-criteria='complete|successfully'",
"build": "wsrun build $PKG --fast-exit -r --stages",
"build:no_website": "wsrun build $PKG --fast-exit -r --stages --exclude @0xproject/website",
"build:monorepo_scripts": "PKG=@0xproject/monorepo-scripts yarn build",
"build:ts": "tsc -b",
"watch:ts": "tsc -b -w",
"clean": "wsrun clean $PKG --fast-exit -r --parallel",
"remove_node_modules": "lerna clean --yes; rm -rf node_modules",
"rebuild": "run-s clean build",
@@ -51,6 +52,7 @@
"npm-run-all": "^4.1.2",
"prettier": "^1.11.1",
"source-map-support": "^0.5.6",
"typescript": "3.0.1",
"wsrun": "^2.2.0"
},
"resolutions": {

View File

@@ -1,4 +1,58 @@
[
{
"timestamp": 1537907159,
"version": "1.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537875740,
"version": "1.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537541580,
"version": "1.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.3",
"changes": [
{
"note": "Drastically reduce the bundle size by removing unused parts of included contract artifacts."
}
],
"timestamp": 1537369748
},
{
"version": "1.0.2",
"changes": [
{
"note": "Add ZRX & WETH mainnet contract addresses into the included artifacts"
}
],
"timestamp": 1537265493
},
{
"timestamp": 1536142250,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.1-rc.6",
"changes": [

View File

@@ -5,6 +5,30 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.6 - _September 25, 2018_
* Dependencies updated
## v1.0.5 - _September 25, 2018_
* Dependencies updated
## v1.0.4 - _September 21, 2018_
* Dependencies updated
## v1.0.3 - _September 19, 2018_
* Drastically reduce the bundle size by removing unused parts of included contract artifacts.
## v1.0.2 - _September 18, 2018_
* Add ZRX & WETH mainnet contract addresses into the included artifacts
## v1.0.1 - _September 5, 2018_
* Dependencies updated
## v1.0.1-rc.6 - _August 27, 2018_
* Fix missing `BlockParamLiteral` type import issue

View File

@@ -1,6 +1,6 @@
## 0x.js
A TypeScript/Javascript library for interacting with the 0x protocol.
A TypeScript/Javascript library for interacting with the 0x protocol. It is a high level package which combines a number of underlying packages such as order-utils and order-watcher.
### Read the [Documentation](https://0xproject.com/docs/0x.js).
@@ -19,7 +19,14 @@ npm install 0x.js --save
**Import**
```javascript
import { ZeroEx } from '0x.js';
import {
assetDataUtils,
BigNumber,
ContractWrappers,
generatePseudoRandomSalt,
orderHashUtils,
signatureUtils,
} from '0x.js';
```
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:

View File

@@ -1,6 +1,6 @@
{
"name": "0x.js",
"version": "1.0.1-rc.6",
"version": "1.0.6",
"engines": {
"node": ">=6.12"
},
@@ -15,7 +15,6 @@
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"build": "yarn build:all",
"build:all": "run-p build:umd:prod build:commonjs",
"lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
@@ -25,8 +24,8 @@
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"clean": "shx rm -rf _bundles lib test_temp src/generated_contract_wrappers generated_docs",
"build:umd:prod": "NODE_ENV=production webpack",
"build:commonjs": "tsc",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES"
"build:commonjs": "tsc -b",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"postpublish": {
@@ -42,15 +41,16 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@0xproject/abi-gen": "^1.0.7",
"@0xproject/dev-utils": "^1.0.6",
"@0xproject/migrations": "^1.0.6",
"@0xproject/monorepo-scripts": "^1.0.7",
"@0xproject/tslint-config": "^1.0.6",
"@0xproject/abi-gen": "^1.0.11",
"@0xproject/dev-utils": "^1.0.10",
"@0xproject/migrations": "^1.0.12",
"@0xproject/monorepo-scripts": "^1.0.9",
"@0xproject/tslint-config": "^1.0.7",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",
"@types/node": "*",
"@types/sinon": "^2.2.2",
"@types/web3-provider-engine": "^14.0.0",
"awesome-typescript-loader": "^3.1.3",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
@@ -73,17 +73,17 @@
"webpack": "^3.1.0"
},
"dependencies": {
"@0xproject/assert": "^1.0.7",
"@0xproject/base-contract": "^2.0.1",
"@0xproject/contract-wrappers": "^1.0.1-rc.5",
"@0xproject/order-utils": "^1.0.1-rc.6",
"@0xproject/order-watcher": "^1.0.1-rc.5",
"@0xproject/subproviders": "^2.0.1",
"@0xproject/types": "^1.0.1-rc.6",
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@0xproject/web3-wrapper": "^2.0.1",
"ethereum-types": "^1.0.5",
"@0xproject/assert": "^1.0.11",
"@0xproject/base-contract": "^2.0.5",
"@0xproject/contract-wrappers": "^2.0.0",
"@0xproject/order-utils": "^1.0.5",
"@0xproject/order-watcher": "^2.0.0",
"@0xproject/subproviders": "^2.0.5",
"@0xproject/types": "^1.1.1",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"@0xproject/web3-wrapper": "^3.0.1",
"ethereum-types": "^1.0.8",
"ethers": "3.0.22",
"lodash": "^4.17.5",
"web3-provider-engine": "14.0.6"

View File

@@ -9,6 +9,7 @@ export {
ERC20ProxyWrapper,
ERC721ProxyWrapper,
ForwarderWrapper,
OrderValidatorWrapper,
IndexedFilterValues,
BlockRange,
ContractWrappersConfig,
@@ -42,6 +43,10 @@ export {
DecodedLogEvent,
ExchangeEventArgs,
TransactionEncoder,
BalanceAndAllowance,
OrderAndTraderInfo,
TraderInfo,
ValidateOrderFillableOpts,
} from '@0xproject/contract-wrappers';
export { OrderWatcher, OnOrderStateChangeCallback, OrderWatcherConfig } from '@0xproject/order-watcher';

View File

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
"outDir": "lib",
"rootDir": "src"
},
"include": ["./src/**/*", "./test/**/*"]
"include": ["./src/**/*"]
}

View File

@@ -1,5 +1,5 @@
{
"extends": "../../tsconfig",
"extends": "../../typedoc-tsconfig",
"compilerOptions": {
"outDir": "lib"
},

View File

@@ -47,8 +47,13 @@ module.exports = {
use: [
{
loader: 'awesome-typescript-loader',
// tsconfig.json contains some options required for
// project references which do not work with webback.
// We override those options here.
query: {
declaration: false,
declarationMap: false,
composite: false,
},
},
],

View File

@@ -1,4 +1,40 @@
[
{
"timestamp": 1537907159,
"version": "1.0.11",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537875740,
"version": "1.0.10",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537541580,
"version": "1.0.9",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1536142250,
"version": "1.0.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1535377027,
"version": "1.0.7",

View File

@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.11 - _September 25, 2018_
* Dependencies updated
## v1.0.10 - _September 25, 2018_
* Dependencies updated
## v1.0.9 - _September 21, 2018_
* Dependencies updated
## v1.0.8 - _September 5, 2018_
* Dependencies updated
## v1.0.7 - _August 27, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/abi-gen",
"version": "1.0.7",
"version": "1.0.11",
"engines": {
"node": ">=6.12"
},
@@ -8,10 +8,9 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"lint": "tslint --project .",
"clean": "shx rm -rf lib",
"build": "tsc",
"build": "tsc -b",
"test": "yarn run_mocha",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit",
"test:circleci": "yarn test:coverage",
@@ -31,10 +30,10 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
"dependencies": {
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"chalk": "^2.3.0",
"ethereum-types": "^1.0.5",
"ethereum-types": "^1.0.8",
"glob": "^7.1.2",
"handlebars": "^4.0.11",
"lodash": "^4.17.5",
@@ -45,11 +44,11 @@
"yargs": "^10.0.3"
},
"devDependencies": {
"@0xproject/tslint-config": "^1.0.6",
"@0xproject/tslint-config": "^1.0.7",
"@types/glob": "5.0.35",
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",
"@types/node": "^8.0.53",
"@types/node": "*",
"@types/sleep": "^0.0.7",
"@types/tmp": "^0.0.33",
"@types/yargs": "^10.0.0",

View File

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
"outDir": "lib",
"rootDir": "."
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@@ -1,4 +1,40 @@
[
{
"timestamp": 1537907159,
"version": "1.0.11",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537875740,
"version": "1.0.10",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537541580,
"version": "1.0.9",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1536142250,
"version": "1.0.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1535377027,
"version": "1.0.7",

View File

@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.11 - _September 25, 2018_
* Dependencies updated
## v1.0.10 - _September 25, 2018_
* Dependencies updated
## v1.0.9 - _September 21, 2018_
* Dependencies updated
## v1.0.8 - _September 5, 2018_
* Dependencies updated
## v1.0.7 - _August 27, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/assert",
"version": "1.0.7",
"version": "1.0.11",
"engines": {
"node": ">=6.12"
},
@@ -8,8 +8,7 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"build": "tsc",
"build": "tsc -b",
"clean": "shx rm -rf lib test_temp",
"lint": "tslint --project .",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
@@ -29,7 +28,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/assert/README.md",
"devDependencies": {
"@0xproject/tslint-config": "^1.0.6",
"@0xproject/tslint-config": "^1.0.7",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/valid-url": "^1.0.2",
@@ -45,9 +44,9 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0xproject/json-schemas": "^1.0.1-rc.6",
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@0xproject/json-schemas": "^1.0.4",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"lodash": "^4.17.5",
"valid-url": "^1.0.9"
},

View File

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
"outDir": "lib",
"rootDir": "."
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@@ -0,0 +1,28 @@
[
{
"timestamp": 1537907159,
"version": "1.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537875740,
"version": "1.0.0",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.0-rc.1",
"changes": [
{
"note": "Init"
}
]
}
]

View File

@@ -5,10 +5,14 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.1-rc.2 - _August 27, 2018_
## v1.0.1 - _September 25, 2018_
* Dependencies updated
## v1.0.1-rc.1 - _August 24, 2018_
## v1.0.0 - _September 25, 2018_
* Add initial forwarderHelperFactory (#997)
* Dependencies updated
## v1.0.0-rc.1 - _Invalid date_
* Init

View File

@@ -0,0 +1,83 @@
## @0xproject/asset-buyer
Convenience package for buying assets represented on the Ethereum blockchain using 0x. In its simplest form, the package helps in the usage of the [0x forwarder contract](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md), which allows users to execute [Wrapped Ether](https://weth.io/) based 0x orders without having to set allowances, wrap Ether or buy ZRX, meaning they can buy tokens with Ether alone. Given some liquidity (0x signed orders), it helps estimate the Ether cost of buying a certain asset (giving a range) and then buying that asset.
In its more advanced and useful form, it integrates with the [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) and takes care of sourcing liquidity for you given an SRA compliant endpoint. The final result is a library that tells you what assets are available, provides an Ether based quote for any asset desired, and allows you to buy that asset using Ether alone.
## Installation
```bash
yarn add @0xproject/asset-buyer
```
**Import**
```typescript
import { AssetBuyer } from '@0xproject/asset-buyer';
```
or
```javascript
var AssetBuyer = require('@0xproject/asset-buyer').AssetBuyer;
```
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
```json
"compilerOptions": {
"typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"],
}
```
## Contributing
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
### Install dependencies
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
```bash
yarn config set workspaces-experimental true
```
Then install dependencies
```bash
yarn install
```
### Build
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
```bash
PKG=@0xproject/asset-buyer yarn build
```
Or continuously rebuild on change:
```bash
PKG=@0xproject/asset-buyer yarn watch
```
### Clean
```bash
yarn clean
```
### Lint
```bash
yarn lint
```
### Run Tests
```bash
yarn test
```

View File

@@ -1,10 +1,10 @@
{
"name": "@0xproject/forwarder-helper",
"version": "1.0.1-rc.2",
"name": "@0xproject/asset-buyer",
"version": "1.0.1",
"engines": {
"node": ">=6.12"
},
"description": "Convenience object for working with the forwarder contract",
"description": "Convenience package for buying assets",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
@@ -18,10 +18,7 @@
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
"clean": "shx rm -rf lib test_temp scripts",
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "node scripts/stage_docs.js",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"config": {
"postpublish": {
@@ -37,21 +34,26 @@
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/forwarder-helper/README.md",
"homepage": "https://github.com/0xProject/0x-monorepo/packages/asset-buyer/README.md",
"dependencies": {
"@0xproject/assert": "^1.0.7",
"@0xproject/json-schemas": "^1.0.1-rc.6",
"@0xproject/order-utils": "^1.0.1-rc.6",
"@0xproject/types": "^1.0.1-rc.6",
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@types/node": "^8.0.53",
"@0xproject/assert": "^1.0.11",
"@0xproject/connect": "^2.0.4",
"@0xproject/contract-wrappers": "^2.0.0",
"@0xproject/json-schemas": "^1.0.4",
"@0xproject/order-utils": "^1.0.5",
"@0xproject/subproviders": "^2.0.5",
"@0xproject/types": "^1.1.1",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"@0xproject/web3-wrapper": "^3.0.1",
"ethereum-types": "^1.0.8",
"lodash": "^4.17.10"
},
"devDependencies": {
"@0xproject/tslint-config": "^1.0.6",
"@0xproject/tslint-config": "^1.0.7",
"@types/lodash": "^4.14.116",
"@types/mocha": "^2.2.42",
"@types/node": "*",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
@@ -63,7 +65,7 @@
"nyc": "^11.0.1",
"shx": "^0.2.2",
"tslint": "5.11.0",
"typedoc": "0xProject/typedoc",
"typedoc": "0.12.0",
"typescript": "3.0.1"
},
"publishConfig": {

View File

@@ -0,0 +1,324 @@
import { ContractWrappers } from '@0xproject/contract-wrappers';
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/order-utils';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
import { constants } from './constants';
import { BasicOrderProvider } from './order_providers/basic_order_provider';
import { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
import {
AssetBuyerError,
AssetBuyerOrdersAndFillableAmounts,
BuyQuote,
BuyQuoteRequestOpts,
OrderProvider,
OrderProviderResponse,
} from './types';
import { assert } from './utils/assert';
import { assetDataUtils } from './utils/asset_data_utils';
import { buyQuoteCalculator } from './utils/buy_quote_calculator';
import { orderProviderResponseProcessor } from './utils/order_provider_response_processor';
export class AssetBuyer {
public readonly provider: Provider;
public readonly assetData: string;
public readonly orderProvider: OrderProvider;
public readonly networkId: number;
public readonly orderRefreshIntervalMs: number;
public readonly expiryBufferSeconds: number;
private readonly _contractWrappers: ContractWrappers;
private _lastRefreshTimeIfExists?: number;
private _currentOrdersAndFillableAmountsIfExists?: AssetBuyerOrdersAndFillableAmounts;
/**
* Instantiates a new AssetBuyer instance given existing liquidity in the form of orders and feeOrders.
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param orders A non-empty array of objects that conform to SignedOrder. All orders must have the same makerAssetData and takerAssetData (WETH).
* @param feeOrders A array of objects that conform to SignedOrder. All orders must have the same makerAssetData (ZRX) and takerAssetData (WETH). Defaults to an empty array.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
*
* @return An instance of AssetBuyer
*/
public static getAssetBuyerForProvidedOrders(
provider: Provider,
orders: SignedOrder[],
feeOrders: SignedOrder[] = [],
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
assert.doesConformToSchema('feeOrders', feeOrders, schemas.signedOrdersSchema);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
assert.areValidProvidedOrders('orders', orders);
assert.areValidProvidedOrders('feeOrders', feeOrders);
assert.assert(orders.length !== 0, `Expected orders to contain at least one order`);
const assetData = orders[0].makerAssetData;
const orderProvider = new BasicOrderProvider(_.concat(orders, feeOrders));
const assetBuyer = new AssetBuyer(
provider,
assetData,
orderProvider,
networkId,
orderRefreshIntervalMs,
expiryBufferSeconds,
);
return assetBuyer;
}
/**
* Instantiates a new AssetBuyer instance given the desired assetData and a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) endpoint
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param assetData The assetData that identifies the desired asset to buy.
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
*
* @return An instance of AssetBuyer
*/
public static getAssetBuyerForAssetData(
provider: Provider,
assetData: string,
sraApiUrl: string,
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.isHexString('assetData', assetData);
assert.isWebUri('sraApiUrl', sraApiUrl);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
const orderProvider = new StandardRelayerAPIOrderProvider(sraApiUrl);
const assetBuyer = new AssetBuyer(
provider,
assetData,
orderProvider,
networkId,
orderRefreshIntervalMs,
expiryBufferSeconds,
);
return assetBuyer;
}
/**
* Instantiates a new AssetBuyer instance given the desired ERC20 token address and a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) endpoint
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param tokenAddress The ERC20 token address that identifies the desired asset to buy.
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
* @return An instance of AssetBuyer
*/
public static getAssetBuyerForERC20TokenAddress(
provider: Provider,
tokenAddress: string,
sraApiUrl: string,
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isWebUri('sraApiUrl', sraApiUrl);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
const assetBuyer = AssetBuyer.getAssetBuyerForAssetData(
provider,
assetData,
sraApiUrl,
networkId,
orderRefreshIntervalMs,
expiryBufferSeconds,
);
return assetBuyer;
}
/**
* Instantiates a new AssetBuyer instance
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* @param orderProvider An object that conforms to OrderProvider, see type for definition.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
*
* @return An instance of AssetBuyer
*/
constructor(
provider: Provider,
assetData: string,
orderProvider: OrderProvider,
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
) {
assert.isWeb3Provider('provider', provider);
assert.isString('assetData', assetData);
assert.isValidOrderProvider('orderProvider', orderProvider);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
this.provider = provider;
this.assetData = assetData;
this.orderProvider = orderProvider;
this.networkId = networkId;
this.expiryBufferSeconds = expiryBufferSeconds;
this.orderRefreshIntervalMs = orderRefreshIntervalMs;
this._contractWrappers = new ContractWrappers(this.provider, {
networkId,
});
}
/**
* Get a `BuyQuote` containing all information relevant to fulfilling a buy.
* You can then pass the `BuyQuote` to `executeBuyQuoteAsync` to execute the buy.
* @param assetBuyAmount The amount of asset to buy.
* @param feePercentage The affiliate fee percentage. Defaults to 0.
* @param forceOrderRefresh If set to true, new orders and state will be fetched instead of waiting for
* the next orderRefreshIntervalMs. Defaults to false.
* @return An object that conforms to BuyQuote that satisfies the request. See type definition for more information.
*/
public async getBuyQuoteAsync(assetBuyAmount: BigNumber, options: Partial<BuyQuoteRequestOpts>): Promise<BuyQuote> {
const { feePercentage, shouldForceOrderRefresh, slippagePercentage } = {
...options,
...constants.DEFAULT_BUY_QUOTE_REQUEST_OPTS,
};
assert.isBigNumber('assetBuyAmount', assetBuyAmount);
assert.isValidPercentage('feePercentage', feePercentage);
assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh);
// we should refresh if:
// we do not have any orders OR
// we are forced to OR
// we have some last refresh time AND that time was sufficiently long ago
const shouldRefresh =
_.isUndefined(this._currentOrdersAndFillableAmountsIfExists) ||
shouldForceOrderRefresh ||
(!_.isUndefined(this._lastRefreshTimeIfExists) &&
this._lastRefreshTimeIfExists + this.orderRefreshIntervalMs < Date.now());
let ordersAndFillableAmounts: AssetBuyerOrdersAndFillableAmounts;
if (shouldRefresh) {
ordersAndFillableAmounts = await this._getLatestOrdersAndFillableAmountsAsync();
this._lastRefreshTimeIfExists = Date.now();
this._currentOrdersAndFillableAmountsIfExists = ordersAndFillableAmounts;
} else {
// it is safe to cast to AssetBuyerOrdersAndFillableAmounts because shouldRefresh catches the undefined case above
ordersAndFillableAmounts = this
._currentOrdersAndFillableAmountsIfExists as AssetBuyerOrdersAndFillableAmounts;
}
const buyQuote = buyQuoteCalculator.calculate(
ordersAndFillableAmounts,
assetBuyAmount,
feePercentage,
slippagePercentage,
);
return buyQuote;
}
/**
* Given a BuyQuote and desired rate, attempt to execute the buy.
* @param buyQuote An object that conforms to BuyQuote. See type definition for more information.
* @param rate The desired rate to execute the buy at. Affects the amount of ETH sent with the transaction, defaults to buyQuote.maxRate.
* @param takerAddress The address to perform the buy. Defaults to the first available address from the provider.
* @param feeRecipient The address where affiliate fees are sent. Defaults to null address (0x000...000).
* @return A promise of the txHash.
*/
public async executeBuyQuoteAsync(
buyQuote: BuyQuote,
rate?: BigNumber,
takerAddress?: string,
feeRecipient: string = constants.NULL_ADDRESS,
): Promise<string> {
assert.isValidBuyQuote('buyQuote', buyQuote);
if (!_.isUndefined(rate)) {
assert.isBigNumber('rate', rate);
}
if (!_.isUndefined(takerAddress)) {
assert.isETHAddressHex('takerAddress', takerAddress);
}
assert.isETHAddressHex('feeRecipient', feeRecipient);
const { orders, feeOrders, feePercentage, assetBuyAmount, maxRate } = buyQuote;
// if no takerAddress is provided, try to get one from the provider
let finalTakerAddress;
if (!_.isUndefined(takerAddress)) {
finalTakerAddress = takerAddress;
} else {
const web3Wrapper = new Web3Wrapper(this.provider);
const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
const firstAvailableAddress = _.head(availableAddresses);
if (!_.isUndefined(firstAvailableAddress)) {
finalTakerAddress = firstAvailableAddress;
} else {
throw new Error(AssetBuyerError.NoAddressAvailable);
}
}
// if no rate is provided, default to the maxRate from buyQuote
const desiredRate = rate || maxRate;
// calculate how much eth is required to buy assetBuyAmount at the desired rate
const ethAmount = assetBuyAmount.dividedToIntegerBy(desiredRate);
const txHash = await this._contractWrappers.forwarder.marketBuyOrdersWithEthAsync(
orders,
assetBuyAmount,
finalTakerAddress,
ethAmount,
feeOrders,
feePercentage,
feeRecipient,
);
return txHash;
}
/**
* Ask the order Provider for orders and process them.
*/
private async _getLatestOrdersAndFillableAmountsAsync(): Promise<AssetBuyerOrdersAndFillableAmounts> {
const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow();
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
// construct order Provider requests
const targetOrderProviderRequest = {
makerAssetData: this.assetData,
takerAssetData: etherTokenAssetData,
networkId: this.networkId,
};
const feeOrderProviderRequest = {
makerAssetData: zrxTokenAssetData,
takerAssetData: etherTokenAssetData,
networkId: this.networkId,
};
const requests = [targetOrderProviderRequest, feeOrderProviderRequest];
// fetch orders and possible fillable amounts
const [targetOrderProviderResponse, feeOrderProviderResponse] = await Promise.all(
_.map(requests, async request => this.orderProvider.getOrdersAsync(request)),
);
// since the order provider is an injected dependency, validate that it respects the API
// ie. it should only return maker/taker assetDatas that are specified
orderProviderResponseProcessor.throwIfInvalidResponse(targetOrderProviderResponse, targetOrderProviderRequest);
orderProviderResponseProcessor.throwIfInvalidResponse(feeOrderProviderResponse, feeOrderProviderRequest);
// process the responses into one object
const ordersAndFillableAmounts = await orderProviderResponseProcessor.processAsync(
targetOrderProviderResponse,
feeOrderProviderResponse,
zrxTokenAssetData,
this.expiryBufferSeconds,
this._contractWrappers.orderValidator,
);
return ordersAndFillableAmounts;
}
/**
* Get the assetData that represents the WETH token.
* Will throw if WETH does not exist for the current network.
*/
private _getEtherTokenAssetDataOrThrow(): string {
return assetDataUtils.getEtherTokenAssetDataOrThrow(this._contractWrappers);
}
/**
* Get the assetData that represents the ZRX token.
* Will throw if ZRX does not exist for the current network.
*/
private _getZrxTokenAssetDataOrThrow(): string {
return assetDataUtils.getZrxTokenAssetDataOrThrow(this._contractWrappers);
}
}

View File

@@ -0,0 +1,20 @@
import { BigNumber } from '@0xproject/utils';
import { BuyQuoteRequestOpts } from './types';
const DEFAULT_BUY_QUOTE_REQUEST_OPTS: BuyQuoteRequestOpts = {
feePercentage: 0,
shouldForceOrderRefresh: false,
slippagePercentage: 0.2, // 20% slippage protection
};
export const constants = {
ZERO_AMOUNT: new BigNumber(0),
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
MAINNET_NETWORK_ID: 1,
DEFAULT_ORDER_REFRESH_INTERVAL_MS: 10000, // 10 seconds
ETHER_TOKEN_DECIMALS: 18,
DEFAULT_BUY_QUOTE_REQUEST_OPTS,
MAX_PER_PAGE: 10000,
DEFAULT_EXPIRY_BUFFER_SECONDS: 15,
};

View File

@@ -0,0 +1,17 @@
export { Provider } from 'ethereum-types';
export { SignedOrder } from '@0xproject/types';
export { BigNumber } from '@0xproject/utils';
export { AssetBuyer } from './asset_buyer';
export { BasicOrderProvider } from './order_providers/basic_order_provider';
export { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
export { StandardRelayerAPIAssetBuyerManager } from './standard_relayer_api_asset_buyer_manager';
export {
AssetBuyerError,
BuyQuote,
OrderProvider,
OrderProviderRequest,
OrderProviderResponse,
SignedOrderWithRemainingFillableMakerAssetAmount,
StandardRelayerApiAssetBuyerManagerError,
} from './types';

View File

@@ -0,0 +1,32 @@
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types';
import * as _ from 'lodash';
import { OrderProvider, OrderProviderRequest, OrderProviderResponse } from '../types';
import { assert } from '../utils/assert';
export class BasicOrderProvider implements OrderProvider {
public readonly orders: SignedOrder[];
/**
* Instantiates a new BasicOrderProvider instance
* @param orders An array of objects that conform to SignedOrder to fetch from.
* @return An instance of BasicOrderProvider
*/
constructor(orders: SignedOrder[]) {
assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
this.orders = orders;
}
/**
* Given an object that conforms to OrderFetcherRequest, return the corresponding OrderProviderResponse that satisfies the request.
* @param orderProviderRequest An instance of OrderFetcherRequest. See type for more information.
* @return An instance of OrderProviderResponse. See type for more information.
*/
public async getOrdersAsync(orderProviderRequest: OrderProviderRequest): Promise<OrderProviderResponse> {
assert.isValidOrderProviderRequest('orderProviderRequest', orderProviderRequest);
const { makerAssetData, takerAssetData } = orderProviderRequest;
const orders = _.filter(this.orders, order => {
return order.makerAssetData === makerAssetData && order.takerAssetData === takerAssetData;
});
return { orders };
}
}

View File

@@ -0,0 +1,79 @@
import { HttpClient } from '@0xproject/connect';
import { APIOrder, OrderbookResponse } from '@0xproject/types';
import * as _ from 'lodash';
import {
AssetBuyerError,
OrderProvider,
OrderProviderRequest,
OrderProviderResponse,
SignedOrderWithRemainingFillableMakerAssetAmount,
} from '../types';
import { assert } from '../utils/assert';
import { orderUtils } from '../utils/order_utils';
export class StandardRelayerAPIOrderProvider implements OrderProvider {
public readonly apiUrl: string;
private readonly _sraClient: HttpClient;
/**
* Given an array of APIOrder objects from a standard relayer api, return an array
* of SignedOrderWithRemainingFillableMakerAssetAmounts
*/
private static _getSignedOrderWithRemainingFillableMakerAssetAmountFromApi(
apiOrders: APIOrder[],
): SignedOrderWithRemainingFillableMakerAssetAmount[] {
const result = _.map(apiOrders, apiOrder => {
const { order, metaData } = apiOrder;
// calculate remainingFillableMakerAssetAmount from api metadata, else assume order is completely fillable
const remainingFillableTakerAssetAmount = _.get(
metaData,
'remainingTakerAssetAmount',
order.takerAssetAmount,
);
const remainingFillableMakerAssetAmount = orderUtils.calculateRemainingMakerAssetAmount(
order,
remainingFillableTakerAssetAmount,
);
const newOrder = {
...order,
remainingFillableMakerAssetAmount,
};
return newOrder;
});
return result;
}
/**
* Instantiates a new StandardRelayerAPIOrderProvider instance
* @param apiUrl The standard relayer API base HTTP url you would like to source orders from.
* @return An instance of StandardRelayerAPIOrderProvider
*/
constructor(apiUrl: string) {
assert.isWebUri('apiUrl', apiUrl);
this.apiUrl = apiUrl;
this._sraClient = new HttpClient(apiUrl);
}
/**
* Given an object that conforms to OrderProviderRequest, return the corresponding OrderProviderResponse that satisfies the request.
* @param orderProviderRequest An instance of OrderProviderRequest. See type for more information.
* @return An instance of OrderProviderResponse. See type for more information.
*/
public async getOrdersAsync(orderProviderRequest: OrderProviderRequest): Promise<OrderProviderResponse> {
assert.isValidOrderProviderRequest('orderProviderRequest', orderProviderRequest);
const { makerAssetData, takerAssetData, networkId } = orderProviderRequest;
const orderbookRequest = { baseAssetData: makerAssetData, quoteAssetData: takerAssetData };
const requestOpts = { networkId };
let orderbook: OrderbookResponse;
try {
orderbook = await this._sraClient.getOrderbookAsync(orderbookRequest, requestOpts);
} catch (err) {
throw new Error(AssetBuyerError.StandardRelayerApiError);
}
const apiOrders = orderbook.asks.records;
const orders = StandardRelayerAPIOrderProvider._getSignedOrderWithRemainingFillableMakerAssetAmountFromApi(
apiOrders,
);
return {
orders,
};
}
}

View File

@@ -0,0 +1,133 @@
import { HttpClient } from '@0xproject/connect';
import { ContractWrappers } from '@0xproject/contract-wrappers';
import { ObjectMap } from '@0xproject/types';
import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
import { AssetBuyer } from './asset_buyer';
import { constants } from './constants';
import { assert } from './utils/assert';
import { assetDataUtils } from './utils/asset_data_utils';
import { OrderProvider, StandardRelayerApiAssetBuyerManagerError } from './types';
export class StandardRelayerAPIAssetBuyerManager {
// Map of assetData to AssetBuyer for that assetData
private readonly _assetBuyerMap: ObjectMap<AssetBuyer>;
/**
* Returns an array of all assetDatas available at the provided sraApiUrl
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
* @param pairedWithAssetData Optional filter argument to return assetDatas that only pair with this assetData value.
*
* @return An array of all assetDatas available at the provider sraApiUrl
*/
public static async getAllAvailableAssetDatasAsync(
sraApiUrl: string,
pairedWithAssetData?: string,
): Promise<string[]> {
const client = new HttpClient(sraApiUrl);
const params = {
assetDataA: pairedWithAssetData,
perPage: constants.MAX_PER_PAGE,
};
const assetPairsResponse = await client.getAssetPairsAsync(params);
return _.uniq(_.map(assetPairsResponse.records, pairsItem => pairsItem.assetDataB.assetData));
}
/**
* Instantiates a new StandardRelayerAPIAssetBuyerManager instance with all available assetDatas at the provided sraApiUrl
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
* @param orderProvider An object that conforms to OrderProvider, see type for definition.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states.
* Defaults to 10000ms (10s).
* @return An promise of an instance of StandardRelayerAPIAssetBuyerManager
*/
public static async getAssetBuyerManagerWithAllAvailableAssetDatasAsync(
provider: Provider,
sraApiUrl: string,
orderProvider: OrderProvider,
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs?: number,
): Promise<StandardRelayerAPIAssetBuyerManager> {
const contractWrappers = new ContractWrappers(provider, { networkId });
const etherTokenAssetData = assetDataUtils.getEtherTokenAssetDataOrThrow(contractWrappers);
const assetDatas = await StandardRelayerAPIAssetBuyerManager.getAllAvailableAssetDatasAsync(
sraApiUrl,
etherTokenAssetData,
);
return new StandardRelayerAPIAssetBuyerManager(
provider,
assetDatas,
orderProvider,
networkId,
orderRefreshIntervalMs,
);
}
/**
* Instantiates a new StandardRelayerAPIAssetBuyerManager instance
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param assetDatas The assetDatas of the desired assets to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* @param orderProvider An object that conforms to OrderProvider, see type for definition.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states.
* Defaults to 10000ms (10s).
* @return An instance of StandardRelayerAPIAssetBuyerManager
*/
constructor(
provider: Provider,
assetDatas: string[],
orderProvider: OrderProvider,
networkId?: number,
orderRefreshIntervalMs?: number,
) {
assert.assert(assetDatas.length > 0, `Expected 'assetDatas' to be a non-empty array.`);
this._assetBuyerMap = _.reduce(
assetDatas,
(accAssetBuyerMap: ObjectMap<AssetBuyer>, assetData: string) => {
accAssetBuyerMap[assetData] = new AssetBuyer(
provider,
assetData,
orderProvider,
networkId,
orderRefreshIntervalMs,
);
return accAssetBuyerMap;
},
{},
);
}
/**
* Get an AssetBuyer for the provided assetData
* @param assetData The desired assetData.
*
* @return An instance of AssetBuyer
*/
public getAssetBuyerFromAssetData(assetData: string): AssetBuyer {
const assetBuyer = this._assetBuyerMap[assetData];
if (_.isUndefined(assetBuyer)) {
throw new Error(
`${StandardRelayerApiAssetBuyerManagerError.AssetBuyerNotFound}: For assetData ${assetData}`,
);
}
return assetBuyer;
}
/**
* Get an AssetBuyer for the provided ERC20 tokenAddress
* @param tokenAddress The desired tokenAddress.
*
* @return An instance of AssetBuyer
*/
public getAssetBuyerFromERC20TokenAddress(tokenAddress: string): AssetBuyer {
const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
return this.getAssetBuyerFromAssetData(assetData);
}
/**
* Get a list of all the assetDatas that the instance supports
*
* @return An array of assetData strings
*/
public getAssetDatas(): string[] {
return _.keys(this._assetBuyerMap);
}
}

View File

@@ -0,0 +1,86 @@
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
/**
* makerAssetData: The assetData representing the desired makerAsset.
* takerAssetData: The assetData representing the desired takerAsset.
* networkId: The networkId that the desired orders should be for.
*/
export interface OrderProviderRequest {
makerAssetData: string;
takerAssetData: string;
networkId: number;
}
/**
* orders: An array of orders with optional remaining fillable makerAsset amounts. See type for more info.
*/
export interface OrderProviderResponse {
orders: SignedOrderWithRemainingFillableMakerAssetAmount[];
}
/**
* A normal SignedOrder with one extra optional property `remainingFillableMakerAssetAmount`
* remainingFillableMakerAssetAmount: The amount of the makerAsset that is available to be filled
*/
export interface SignedOrderWithRemainingFillableMakerAssetAmount extends SignedOrder {
remainingFillableMakerAssetAmount?: BigNumber;
}
/**
* Given an OrderProviderRequest, get an OrderProviderResponse.
*/
export interface OrderProvider {
getOrdersAsync: (orderProviderRequest: OrderProviderRequest) => Promise<OrderProviderResponse>;
}
/**
* assetData: String that represents a specific asset (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* orders: An array of objects conforming to SignedOrder. These orders can be used to cover the requested assetBuyAmount plus slippage.
* feeOrders: An array of objects conforming to SignedOrder. These orders can be used to cover the fees for the orders param above.
* minRate: Min rate that needs to be paid in order to execute the buy.
* maxRate: Max rate that can be paid in order to execute the buy.
* assetBuyAmount: The amount of asset to buy.
* feePercentage: Optional affiliate fee percentage used to calculate the eth amounts above.
*/
export interface BuyQuote {
assetData: string;
orders: SignedOrder[];
feeOrders: SignedOrder[];
minRate: BigNumber;
maxRate: BigNumber;
assetBuyAmount: BigNumber;
feePercentage?: number;
}
export interface BuyQuoteRequestOpts {
feePercentage: number;
shouldForceOrderRefresh: boolean;
slippagePercentage: number;
}
/**
* Possible errors thrown by an AssetBuyer instance or associated static methods.
*/
export enum AssetBuyerError {
NoEtherTokenContractFound = 'NO_ETHER_TOKEN_CONTRACT_FOUND',
NoZrxTokenContractFound = 'NO_ZRX_TOKEN_CONTRACT_FOUND',
StandardRelayerApiError = 'STANDARD_RELAYER_API_ERROR',
InsufficientAssetLiquidity = 'INSUFFICIENT_ASSET_LIQUIDITY',
InsufficientZrxLiquidity = 'INSUFFICIENT_ZRX_LIQUIDITY',
NoAddressAvailable = 'NO_ADDRESS_AVAILABLE',
InvalidOrderProviderResponse = 'INVALID_ORDER_PROVIDER_RESPONSE',
}
/**
* Possible errors thrown by an StandardRelayerApiAssetBuyerManager instance or associated static methods.
*/
export enum StandardRelayerApiAssetBuyerManagerError {
AssetBuyerNotFound = 'ASSET_BUYER_NOT_FOUND',
}
export interface AssetBuyerOrdersAndFillableAmounts {
orders: SignedOrder[];
feeOrders: SignedOrder[];
remainingFillableMakerAssetAmounts: BigNumber[];
remainingFillableFeeAmounts: BigNumber[];
}

View File

@@ -0,0 +1,51 @@
import { assert as sharedAssert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types';
import * as _ from 'lodash';
import { BuyQuote, OrderProvider, OrderProviderRequest } from '../types';
export const assert = {
...sharedAssert,
isValidBuyQuote(variableName: string, buyQuote: BuyQuote): void {
sharedAssert.isHexString(`${variableName}.assetData`, buyQuote.assetData);
sharedAssert.doesConformToSchema(`${variableName}.orders`, buyQuote.orders, schemas.signedOrdersSchema);
sharedAssert.doesConformToSchema(`${variableName}.feeOrders`, buyQuote.feeOrders, schemas.signedOrdersSchema);
sharedAssert.isBigNumber(`${variableName}.minRate`, buyQuote.minRate);
sharedAssert.isBigNumber(`${variableName}.maxRate`, buyQuote.maxRate);
sharedAssert.isBigNumber(`${variableName}.assetBuyAmount`, buyQuote.assetBuyAmount);
if (!_.isUndefined(buyQuote.feePercentage)) {
sharedAssert.isNumber(`${variableName}.feePercentage`, buyQuote.feePercentage);
}
},
isValidOrderProvider(variableName: string, orderFetcher: OrderProvider): void {
sharedAssert.isFunction(`${variableName}.getOrdersAsync`, orderFetcher.getOrdersAsync);
},
isValidOrderProviderRequest(variableName: string, orderFetcherRequest: OrderProviderRequest): void {
sharedAssert.isHexString(`${variableName}.makerAssetData`, orderFetcherRequest.makerAssetData);
sharedAssert.isHexString(`${variableName}.takerAssetData`, orderFetcherRequest.takerAssetData);
sharedAssert.isNumber(`${variableName}.networkId`, orderFetcherRequest.networkId);
},
areValidProvidedOrders(variableName: string, orders: SignedOrder[]): void {
if (orders.length === 0) {
return;
}
const makerAssetData = orders[0].makerAssetData;
const takerAssetData = orders[0].takerAssetData;
const filteredOrders = _.filter(
orders,
order => order.makerAssetData === makerAssetData && order.takerAssetData === takerAssetData,
);
sharedAssert.assert(
orders.length === filteredOrders.length,
`Expected all orders in ${variableName} to have the same makerAssetData and takerAssetData.`,
);
},
isValidPercentage(variableName: string, percentage: number): void {
assert.isNumber(variableName, percentage);
assert.assert(
percentage >= 0 && percentage <= 1,
`Expected ${variableName} to be between 0 and 1, but is ${percentage}`,
);
},
};

View File

@@ -0,0 +1,26 @@
import { ContractWrappers } from '@0xproject/contract-wrappers';
import { assetDataUtils as sharedAssetDataUtils } from '@0xproject/order-utils';
import * as _ from 'lodash';
import { AssetBuyerError } from '../types';
export const assetDataUtils = {
...sharedAssetDataUtils,
getEtherTokenAssetDataOrThrow(contractWrappers: ContractWrappers): string {
const etherTokenAddressIfExists = contractWrappers.etherToken.getContractAddressIfExists();
if (_.isUndefined(etherTokenAddressIfExists)) {
throw new Error(AssetBuyerError.NoEtherTokenContractFound);
}
const etherTokenAssetData = sharedAssetDataUtils.encodeERC20AssetData(etherTokenAddressIfExists);
return etherTokenAssetData;
},
getZrxTokenAssetDataOrThrow(contractWrappers: ContractWrappers): string {
let zrxTokenAssetData: string;
try {
zrxTokenAssetData = contractWrappers.exchange.getZRXAssetData();
} catch (err) {
throw new Error(AssetBuyerError.NoZrxTokenContractFound);
}
return zrxTokenAssetData;
},
};

View File

@@ -0,0 +1,89 @@
import { marketUtils } from '@0xproject/order-utils';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { constants } from '../constants';
import { AssetBuyerError, AssetBuyerOrdersAndFillableAmounts, BuyQuote } from '../types';
import { orderUtils } from './order_utils';
// Calculates a buy quote for orders that have WETH as the takerAsset
export const buyQuoteCalculator = {
calculate(
ordersAndFillableAmounts: AssetBuyerOrdersAndFillableAmounts,
assetBuyAmount: BigNumber,
feePercentage: number,
slippagePercentage: number,
): BuyQuote {
const {
orders,
feeOrders,
remainingFillableMakerAssetAmounts,
remainingFillableFeeAmounts,
} = ordersAndFillableAmounts;
const slippageBufferAmount = assetBuyAmount.mul(slippagePercentage).round();
const {
resultOrders,
remainingFillAmount,
ordersRemainingFillableMakerAssetAmounts,
} = marketUtils.findOrdersThatCoverMakerAssetFillAmount(orders, assetBuyAmount, {
remainingFillableMakerAssetAmounts,
slippageBufferAmount,
});
if (remainingFillAmount.gt(constants.ZERO_AMOUNT)) {
throw new Error(AssetBuyerError.InsufficientAssetLiquidity);
}
// TODO(bmillman): optimization
// update this logic to find the minimum amount of feeOrders to cover the worst case as opposed to
// finding order that cover all fees, this will help with estimating ETH and minimizing gas usage
const {
resultFeeOrders,
remainingFeeAmount,
feeOrdersRemainingFillableMakerAssetAmounts,
} = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(resultOrders, feeOrders, {
remainingFillableMakerAssetAmounts,
remainingFillableFeeAmounts,
});
if (remainingFeeAmount.gt(constants.ZERO_AMOUNT)) {
throw new Error(AssetBuyerError.InsufficientZrxLiquidity);
}
const assetData = orders[0].makerAssetData;
// calculate minRate and maxRate by calculating min and max eth usage and then dividing into
// assetBuyAmount to get assetData / WETH, needs to take into account feePercentage as well
// minEthAmount = (sum(takerAssetAmount[i]) until sum(makerAssetAmount[i]) >= assetBuyAmount ) * (1 + feePercentage)
// maxEthAmount = (sum(takerAssetAmount[i]) until i == orders.length) * (1 + feePercentage)
const allOrders = _.concat(resultOrders, resultFeeOrders);
const allRemainingAmounts = _.concat(
ordersRemainingFillableMakerAssetAmounts,
feeOrdersRemainingFillableMakerAssetAmounts,
);
let minEthAmount = constants.ZERO_AMOUNT;
let maxEthAmount = constants.ZERO_AMOUNT;
let cumulativeMakerAmount = constants.ZERO_AMOUNT;
_.forEach(allOrders, (order, index) => {
const remainingFillableMakerAssetAmount = allRemainingAmounts[index];
const claimableTakerAssetAmount = orderUtils.calculateRemainingTakerAssetAmount(
order,
remainingFillableMakerAssetAmount,
);
// taker asset is always assumed to be WETH
maxEthAmount = maxEthAmount.plus(claimableTakerAssetAmount);
if (cumulativeMakerAmount.lessThan(assetBuyAmount)) {
minEthAmount = minEthAmount.plus(claimableTakerAssetAmount);
}
cumulativeMakerAmount = cumulativeMakerAmount.plus(remainingFillableMakerAssetAmount);
});
const feeAdjustedMinRate = minEthAmount.mul(feePercentage + 1).div(assetBuyAmount);
const feeAdjustedMaxRate = minEthAmount.mul(feePercentage + 1).div(assetBuyAmount);
return {
assetData,
orders: resultOrders,
feeOrders: resultFeeOrders,
minRate: feeAdjustedMinRate,
maxRate: feeAdjustedMaxRate,
assetBuyAmount,
feePercentage,
};
},
};

View File

@@ -0,0 +1,202 @@
import { OrderAndTraderInfo, OrderStatus, OrderValidatorWrapper } from '@0xproject/contract-wrappers';
import { sortingUtils } from '@0xproject/order-utils';
import { RemainingFillableCalculator } from '@0xproject/order-utils/lib/src/remaining_fillable_calculator';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { constants } from '../constants';
import {
AssetBuyerError,
AssetBuyerOrdersAndFillableAmounts,
OrderProviderRequest,
OrderProviderResponse,
SignedOrderWithRemainingFillableMakerAssetAmount,
} from '../types';
import { orderUtils } from './order_utils';
interface OrdersAndRemainingFillableMakerAssetAmounts {
orders: SignedOrder[];
remainingFillableMakerAssetAmounts: BigNumber[];
}
export const orderProviderResponseProcessor = {
throwIfInvalidResponse(response: OrderProviderResponse, request: OrderProviderRequest): void {
const { makerAssetData, takerAssetData } = request;
_.forEach(response.orders, order => {
if (order.makerAssetData !== makerAssetData || order.takerAssetData !== takerAssetData) {
throw new Error(AssetBuyerError.InvalidOrderProviderResponse);
}
});
},
/**
* Take the responses for the target orders to buy and fee orders and process them.
* Processing includes:
* - Drop orders that are expired or not open orders (null taker address)
* - If shouldValidateOnChain, attempt to grab fillable amounts from on-chain otherwise assume completely fillable
* - Sort by rate
*/
async processAsync(
targetOrderProviderResponse: OrderProviderResponse,
feeOrderProviderResponse: OrderProviderResponse,
zrxTokenAssetData: string,
expiryBufferSeconds: number,
orderValidator?: OrderValidatorWrapper,
): Promise<AssetBuyerOrdersAndFillableAmounts> {
// drop orders that are expired or not open
const filteredTargetOrders = filterOutExpiredAndNonOpenOrders(
targetOrderProviderResponse.orders,
expiryBufferSeconds,
);
const filteredFeeOrders = filterOutExpiredAndNonOpenOrders(
feeOrderProviderResponse.orders,
expiryBufferSeconds,
);
// set the orders to be sorted equal to the filtered orders
let unsortedTargetOrders = filteredTargetOrders;
let unsortedFeeOrders = filteredFeeOrders;
// if an orderValidator is provided, use on chain information to calculate remaining fillable makerAsset amounts
if (!_.isUndefined(orderValidator)) {
// TODO(bmillman): improvement
// try/catch these requests and throw a more domain specific error
// TODO(bmillman): optimization
// reduce this to once RPC call buy combining orders into one array and then splitting up the response
const [targetOrdersAndTradersInfo, feeOrdersAndTradersInfo] = await Promise.all(
_.map([filteredTargetOrders, filteredFeeOrders], ordersToBeValidated => {
const takerAddresses = _.map(ordersToBeValidated, () => constants.NULL_ADDRESS);
return orderValidator.getOrdersAndTradersInfoAsync(ordersToBeValidated, takerAddresses);
}),
);
// take orders + on chain information and find the valid orders and remaining fillable maker asset amounts
unsortedTargetOrders = getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
filteredTargetOrders,
targetOrdersAndTradersInfo,
zrxTokenAssetData,
);
// take orders + on chain information and find the valid orders and remaining fillable maker asset amounts
unsortedFeeOrders = getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
filteredFeeOrders,
feeOrdersAndTradersInfo,
zrxTokenAssetData,
);
}
// sort orders by rate
// TODO(bmillman): optimization
// provide a feeRate to the sorting function to more accurately sort based on the current market for ZRX tokens
const sortedTargetOrders = sortingUtils.sortOrdersByFeeAdjustedRate(unsortedTargetOrders);
const sortedFeeOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate(unsortedFeeOrders);
// unbundle orders and fillable amounts and compile final result
const targetOrdersAndRemainingFillableMakerAssetAmounts = unbundleOrdersWithAmounts(sortedTargetOrders);
const feeOrdersAndRemainingFillableMakerAssetAmounts = unbundleOrdersWithAmounts(sortedFeeOrders);
return {
orders: targetOrdersAndRemainingFillableMakerAssetAmounts.orders,
feeOrders: feeOrdersAndRemainingFillableMakerAssetAmounts.orders,
remainingFillableMakerAssetAmounts:
targetOrdersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
remainingFillableFeeAmounts:
feeOrdersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
};
},
};
/**
* Given an array of orders, return a new array with expired and non open orders filtered out.
*/
function filterOutExpiredAndNonOpenOrders(
orders: SignedOrderWithRemainingFillableMakerAssetAmount[],
expiryBufferSeconds: number,
): SignedOrderWithRemainingFillableMakerAssetAmount[] {
const result = _.filter(orders, order => {
return orderUtils.isOpenOrder(order) && !orderUtils.willOrderExpire(order, expiryBufferSeconds);
});
return result;
}
/**
* Given an array of orders and corresponding on-chain infos, return a subset of the orders
* that are still fillable orders with their corresponding remainingFillableMakerAssetAmounts.
*/
function getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
inputOrders: SignedOrder[],
ordersAndTradersInfo: OrderAndTraderInfo[],
zrxAssetData: string,
): SignedOrderWithRemainingFillableMakerAssetAmount[] {
// iterate through the input orders and find the ones that are still fillable
// for the orders that are still fillable, calculate the remaining fillable maker asset amount
const result = _.reduce(
inputOrders,
(accOrders, order, index) => {
// get corresponding on-chain state for the order
const { orderInfo, traderInfo } = ordersAndTradersInfo[index];
// if the order IS NOT fillable, do not add anything to the accumulations and continue iterating
if (orderInfo.orderStatus !== OrderStatus.FILLABLE) {
return accOrders;
}
// if the order IS fillable, add the order and calculate the remaining fillable amount
const transferrableAssetAmount = BigNumber.min([traderInfo.makerAllowance, traderInfo.makerBalance]);
const transferrableFeeAssetAmount = BigNumber.min([
traderInfo.makerZrxAllowance,
traderInfo.makerZrxBalance,
]);
const remainingTakerAssetAmount = order.takerAssetAmount.minus(orderInfo.orderTakerAssetFilledAmount);
const remainingMakerAssetAmount = orderUtils.calculateRemainingMakerAssetAmount(
order,
remainingTakerAssetAmount,
);
const remainingFillableCalculator = new RemainingFillableCalculator(
order.makerFee,
order.makerAssetAmount,
order.makerAssetData === zrxAssetData,
transferrableAssetAmount,
transferrableFeeAssetAmount,
remainingMakerAssetAmount,
);
const remainingFillableAmount = remainingFillableCalculator.computeRemainingFillable();
// if the order does not have any remaining fillable makerAsset, do not add anything to the accumulations and continue iterating
if (remainingFillableAmount.lte(constants.ZERO_AMOUNT)) {
return accOrders;
}
const orderWithRemainingFillableMakerAssetAmount = {
...order,
remainingFillableMakerAssetAmount: remainingFillableAmount,
};
const newAccOrders = _.concat(accOrders, orderWithRemainingFillableMakerAssetAmount);
return newAccOrders;
},
[] as SignedOrderWithRemainingFillableMakerAssetAmount[],
);
return result;
}
/**
* Given an array of orders with remaining fillable maker asset amounts. Unbundle into an instance of OrdersAndRemainingFillableMakerAssetAmounts.
* If an order is missing a corresponding remainingFillableMakerAssetAmount, assume it is completely fillable.
*/
function unbundleOrdersWithAmounts(
ordersWithAmounts: SignedOrderWithRemainingFillableMakerAssetAmount[],
): OrdersAndRemainingFillableMakerAssetAmounts {
const result = _.reduce(
ordersWithAmounts,
(acc, orderWithAmount) => {
const { orders, remainingFillableMakerAssetAmounts } = acc;
const { remainingFillableMakerAssetAmount, ...order } = orderWithAmount;
// if we are still missing a remainingFillableMakerAssetAmount, assume the order is completely fillable
const newRemainingAmount = remainingFillableMakerAssetAmount || order.makerAssetAmount;
// if remaining amount is less than or equal to zero, do not add it
if (newRemainingAmount.lte(constants.ZERO_AMOUNT)) {
return acc;
}
const newAcc = {
orders: _.concat(orders, order),
remainingFillableMakerAssetAmounts: _.concat(remainingFillableMakerAssetAmounts, newRemainingAmount),
};
return newAcc;
},
{
orders: [] as SignedOrder[],
remainingFillableMakerAssetAmounts: [] as BigNumber[],
},
);
return result;
}

View File

@@ -0,0 +1,30 @@
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { constants } from '../constants';
export const orderUtils = {
isOrderExpired(order: SignedOrder): boolean {
return orderUtils.willOrderExpire(order, 0);
},
willOrderExpire(order: SignedOrder, secondsFromNow: number): boolean {
const millisecondsInSecond = 1000;
const currentUnixTimestampSec = new BigNumber(Date.now() / millisecondsInSecond).round();
return order.expirationTimeSeconds.lessThan(currentUnixTimestampSec.minus(secondsFromNow));
},
calculateRemainingMakerAssetAmount(order: SignedOrder, remainingTakerAssetAmount: BigNumber): BigNumber {
if (remainingTakerAssetAmount.eq(0)) {
return constants.ZERO_AMOUNT;
}
return remainingTakerAssetAmount.times(order.makerAssetAmount).dividedToIntegerBy(order.takerAssetAmount);
},
calculateRemainingTakerAssetAmount(order: SignedOrder, remainingMakerAssetAmount: BigNumber): BigNumber {
if (remainingMakerAssetAmount.eq(0)) {
return constants.ZERO_AMOUNT;
}
return remainingMakerAssetAmount.times(order.takerAssetAmount).dividedToIntegerBy(order.makerAssetAmount);
},
isOpenOrder(order: SignedOrder): boolean {
return order.takerAddress === constants.NULL_ADDRESS;
},
};

View File

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

View File

@@ -0,0 +1,7 @@
{
"extends": "../../typedoc-tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@@ -1,4 +1,40 @@
[
{
"timestamp": 1537907159,
"version": "2.0.5",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537875740,
"version": "2.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537541580,
"version": "2.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1536142250,
"version": "2.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1535377027,
"version": "2.0.1",

View File

@@ -5,6 +5,22 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.0.5 - _September 25, 2018_
* Dependencies updated
## v2.0.4 - _September 25, 2018_
* Dependencies updated
## v2.0.3 - _September 21, 2018_
* Dependencies updated
## v2.0.2 - _September 5, 2018_
* Dependencies updated
## v2.0.1 - _August 27, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/base-contract",
"version": "2.0.1",
"version": "2.0.5",
"engines": {
"node": ">=6.12"
},
@@ -8,8 +8,7 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"build": "tsc",
"build": "tsc -b",
"clean": "shx rm -rf lib",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test",
@@ -29,7 +28,7 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/base-contract/README.md",
"devDependencies": {
"@0xproject/tslint-config": "^1.0.6",
"@0xproject/tslint-config": "^1.0.7",
"@types/lodash": "4.14.104",
"chai": "^4.0.1",
"copyfiles": "^2.0.0",
@@ -41,10 +40,10 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@0xproject/web3-wrapper": "^2.0.1",
"ethereum-types": "^1.0.5",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"@0xproject/web3-wrapper": "^3.0.1",
"ethereum-types": "^1.0.8",
"ethers": "3.0.22",
"lodash": "^4.17.5"
},

View File

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
"outDir": "lib",
"rootDir": "."
},
"include": ["src/**/*", "test/**/*"]
}

View File

@@ -1,4 +1,51 @@
[
{
"timestamp": 1537907159,
"version": "2.0.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.0.3",
"changes": [
{
"note": "Import SRA-related types from @0xproject/types",
"pr": 1085
}
],
"timestamp": 1537875740
},
{
"timestamp": 1537541580,
"version": "2.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1537369748,
"version": "2.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.0.0",
"changes": [
{
"note": "Change `OrderConfigRequest` to use BigNumber instead of string for relevant fields.",
"pr": 1058
}
],
"timestamp": 1536142250
},
{
"version": "2.0.0-rc.2",
"changes": [

View File

@@ -5,6 +5,26 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.0.4 - _September 25, 2018_
* Dependencies updated
## v2.0.3 - _September 25, 2018_
* Import SRA-related types from @0xproject/types (#1085)
## v2.0.2 - _September 21, 2018_
* Dependencies updated
## v2.0.1 - _September 19, 2018_
* Dependencies updated
## v2.0.0 - _September 5, 2018_
* Change `OrderConfigRequest` to use BigNumber instead of string for relevant fields. (#1058)
## v2.0.0-rc.2 - _August 27, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/connect",
"version": "2.0.0-rc.2",
"version": "2.0.4",
"engines": {
"node": ">=6.12"
},
@@ -15,8 +15,7 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "tsc -w",
"build": "tsc",
"build": "tsc -b",
"clean": "shx rm -rf lib test_temp generated_docs",
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
"lint": "tslint --project .",
@@ -26,7 +25,7 @@
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"test:circleci": "yarn test:coverage",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES"
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"postpublish": {
@@ -44,11 +43,12 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
"dependencies": {
"@0xproject/assert": "^1.0.7",
"@0xproject/json-schemas": "^1.0.1-rc.6",
"@0xproject/types": "^1.0.1-rc.6",
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@0xproject/assert": "^1.0.11",
"@0xproject/json-schemas": "^1.0.4",
"@0xproject/order-utils": "^1.0.5",
"@0xproject/types": "^1.1.1",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"lodash": "^4.17.5",
"query-string": "^5.0.1",
"sinon": "^4.0.0",
@@ -56,7 +56,7 @@
"websocket": "^1.0.25"
},
"devDependencies": {
"@0xproject/tslint-config": "^1.0.6",
"@0xproject/tslint-config": "^1.0.7",
"@types/fetch-mock": "^6.0.3",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",

View File

@@ -1,19 +1,10 @@
import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types';
import { fetchAsync } from '@0xproject/utils';
import * as _ from 'lodash';
import * as queryString from 'query-string';
import { schemas as clientSchemas } from './schemas/schemas';
import {
APIOrder,
AssetPairsRequestOpts,
AssetPairsResponse,
Client,
FeeRecipientsResponse,
HttpRequestOptions,
HttpRequestType,
OrderbookRequest,
OrderbookResponse,
OrderConfigRequest,
@@ -22,14 +13,21 @@ import {
OrdersResponse,
PagedRequestOpts,
RequestOpts,
} from './types';
SignedOrder,
} from '@0xproject/types';
import { fetchAsync } from '@0xproject/utils';
import * as _ from 'lodash';
import * as queryString from 'query-string';
import { schemas as clientSchemas } from './schemas/schemas';
import { Client, HttpRequestOptions, HttpRequestType } from './types';
import { relayerResponseJsonParsers } from './utils/relayer_response_json_parsers';
const TRAILING_SLASHES_REGEX = /\/+$/;
/**
* This class includes all the functionality related to interacting with a set of HTTP endpoints
* that implement the standard relayer API v0
* that implement the standard relayer API v2
*/
export class HttpClient implements Client {
private readonly _apiEndpointUrl: string;
@@ -151,7 +149,7 @@ export class HttpClient implements Client {
params: requestOpts,
payload: request,
};
const responseJson = await this._requestAsync('/order_config', HttpRequestType.Post, httpRequestOpts);
const responseJson = await this._requestAsync('/order_config', HttpRequestType.Get, httpRequestOpts);
const fees = relayerResponseJsonParsers.parseOrderConfigResponseJson(responseJson);
return fees;
}

View File

@@ -1,23 +1,20 @@
export { HttpClient } from './http_client';
export { ordersChannelFactory } from './orders_channel_factory';
export { Client, OrdersChannel, OrdersChannelHandler } from './types';
export {
Client,
OrderConfigRequest,
OrderConfigResponse,
OrdersChannel,
OrdersChannelHandler,
OrdersChannelSubscriptionOpts,
OrderbookRequest,
OrderbookResponse,
OrdersRequestOpts,
PagedRequestOpts,
APIOrder,
AssetPairsRequestOpts,
RequestOpts,
AssetPairsResponse,
FeeRecipientsResponse,
APIOrder,
OrderbookRequest,
OrderbookResponse,
OrderConfigRequest,
OrderConfigResponse,
OrdersChannelSubscriptionOpts,
OrdersRequestOpts,
OrdersResponse,
PagedRequestOpts,
PaginatedCollection,
} from './types';
export { SignedOrder } from '@0xproject/types';
RequestOpts,
SignedOrder,
} from '@0xproject/types';

View File

@@ -1,5 +1,18 @@
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import {
APIOrder,
AssetPairsItem,
AssetPairsRequestOpts,
FeeRecipientsResponse,
OrderbookRequest,
OrderbookResponse,
OrderConfigRequest,
OrderConfigResponse,
OrdersChannelSubscriptionOpts,
OrdersRequestOpts,
PagedRequestOpts,
PaginatedCollection,
SignedOrder,
} from '@0xproject/types';
export interface Client {
getAssetPairsAsync: (
@@ -18,140 +31,12 @@ export interface OrdersChannel {
close: () => void;
}
/**
* baseAssetData: The address of assetData designated as the baseToken in the currency pair calculation of price
* quoteAssetData: The address of assetData designated as the quoteToken in the currency pair calculation of price
* limit: Maximum number of bids and asks in orderbook snapshot
*/
export interface OrdersChannelSubscriptionOpts {
baseAssetData: string;
quoteAssetData: string;
limit: number;
}
export interface OrdersChannelHandler {
onUpdate: (channel: OrdersChannel, subscriptionOpts: OrdersChannelSubscriptionOpts, orders: APIOrder[]) => void;
onError: (channel: OrdersChannel, err: Error, subscriptionOpts?: OrdersChannelSubscriptionOpts) => void;
onClose: (channel: OrdersChannel) => void;
}
export type OrdersChannelMessage = UpdateOrdersChannelMessage | UnknownOrdersChannelMessage;
export enum OrdersChannelMessageTypes {
Update = 'update',
Unknown = 'unknown',
}
export interface UpdateOrdersChannelMessage {
type: OrdersChannelMessageTypes.Update;
requestId: string;
payload: APIOrder[];
}
export interface UnknownOrdersChannelMessage {
type: OrdersChannelMessageTypes.Unknown;
requestId: string;
payload: undefined;
}
export enum WebsocketConnectionEventType {
Close = 'close',
Error = 'error',
Message = 'message',
}
export enum WebsocketClientEventType {
Connect = 'connect',
ConnectFailed = 'connectFailed',
}
export type OrdersResponse = PaginatedCollection<APIOrder>;
export interface APIOrder {
order: SignedOrder;
metaData: object;
}
export interface AssetPairsRequestOpts {
assetDataA?: string;
assetDataB?: string;
}
export type AssetPairsResponse = PaginatedCollection<AssetPairsItem>;
export interface AssetPairsItem {
assetDataA: Asset;
assetDataB: Asset;
}
export interface Asset {
assetData: string;
minAmount: BigNumber;
maxAmount: BigNumber;
precision: number;
}
export interface OrdersRequestOpts {
makerAssetProxyId?: string;
takerAssetProxyId?: string;
makerAssetAddress?: string;
takerAssetAddress?: string;
exchangeAddress?: string;
senderAddress?: string;
makerAssetData?: string;
takerAssetData?: string;
makerAddress?: string;
takerAddress?: string;
traderAddress?: string;
feeRecipientAddress?: string;
}
export interface OrderbookRequest {
baseAssetData: string;
quoteAssetData: string;
}
export interface OrderbookResponse {
bids: PaginatedCollection<APIOrder>;
asks: PaginatedCollection<APIOrder>;
}
export interface PaginatedCollection<T> {
total: number;
page: number;
perPage: number;
records: T[];
}
export interface OrderConfigRequest {
makerAddress: string;
takerAddress: string;
makerAssetAmount: string;
takerAssetAmount: string;
makerAssetData: string;
takerAssetData: string;
exchangeAddress: string;
expirationTimeSeconds: string;
}
export interface OrderConfigResponse {
makerFee: BigNumber;
takerFee: BigNumber;
feeRecipientAddress: string;
senderAddress: string;
}
export type FeeRecipientsResponse = PaginatedCollection<string>;
export interface RequestOpts {
networkId?: number;
}
export interface PagedRequestOpts {
page?: number;
perPage?: number;
}
export interface HttpRequestOptions {
params?: object;
payload?: object;

View File

@@ -2,7 +2,7 @@ import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import * as _ from 'lodash';
import { OrdersChannelMessage, OrdersChannelMessageTypes } from '../types';
import { OrdersChannelMessage, OrdersChannelMessageTypes } from '@0xproject/types';
import { relayerResponseJsonParsers } from './relayer_response_json_parsers';

View File

@@ -1,5 +1,6 @@
import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import { orderParsingUtils } from '@0xproject/order-utils';
import {
APIOrder,
@@ -8,7 +9,7 @@ import {
OrderbookResponse,
OrderConfigResponse,
OrdersResponse,
} from '../types';
} from '@0xproject/types';
import { typeConverters } from './type_converters';
@@ -19,7 +20,7 @@ export const relayerResponseJsonParsers = {
},
parseAssetPairsItemsJson(json: any): AssetPairsItem[] {
return json.map((assetDataPair: any) => {
return typeConverters.convertStringsFieldsToBigNumbers(assetDataPair, [
return orderParsingUtils.convertStringsFieldsToBigNumbers(assetDataPair, [
'assetDataA.minAmount',
'assetDataA.maxAmount',
'assetDataB.minAmount',
@@ -44,6 +45,6 @@ export const relayerResponseJsonParsers = {
},
parseOrderConfigResponseJson(json: any): OrderConfigResponse {
assert.doesConformToSchema('orderConfigResponse', json, schemas.relayerApiOrderConfigResponseSchema);
return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']);
return orderParsingUtils.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']);
},
};

View File

@@ -1,7 +1,7 @@
import { BigNumber } from '@0xproject/utils';
import { orderParsingUtils } from '@0xproject/order-utils';
import * as _ from 'lodash';
import { APIOrder } from '../types';
import { APIOrder } from '@0xproject/types';
export const typeConverters = {
convertOrderbookStringFieldsToBigNumber(orderbook: any): any {
@@ -21,28 +21,6 @@ export const typeConverters = {
};
},
convertAPIOrderStringFieldsToBigNumber(apiOrder: any): APIOrder {
return { ...apiOrder, order: typeConverters.convertOrderStringFieldsToBigNumber(apiOrder.order) };
},
convertOrderStringFieldsToBigNumber(order: any): any {
return typeConverters.convertStringsFieldsToBigNumbers(order, [
'makerAssetAmount',
'takerAssetAmount',
'makerFee',
'takerFee',
'expirationTimeSeconds',
'salt',
]);
},
convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any {
const result = _.assign({}, obj);
_.each(fields, field => {
_.update(result, field, (value: string) => {
if (_.isUndefined(value)) {
throw new Error(`Could not find field '${field}' while converting string fields to BigNumber.`);
}
return new BigNumber(value);
});
});
return result;
return { ...apiOrder, order: orderParsingUtils.convertOrderStringFieldsToBigNumber(apiOrder.order) };
},
};

View File

@@ -1,8 +1,9 @@
import { OrdersChannelMessageTypes, OrdersChannelSubscriptionOpts } from '@0xproject/types';
import * as _ from 'lodash';
import { v4 as uuid } from 'uuid';
import * as WebSocket from 'websocket';
import { OrdersChannel, OrdersChannelHandler, OrdersChannelMessageTypes, OrdersChannelSubscriptionOpts } from './types';
import { OrdersChannel, OrdersChannelHandler } from './types';
import { assert } from './utils/assert';
import { ordersChannelMessageParser } from './utils/orders_channel_message_parser';

View File

@@ -1,6 +1,6 @@
import { BigNumber } from '@0xproject/utils';
import { AssetPairsResponse } from '../../../src/types';
import { AssetPairsResponse } from '@0xproject/types';
export const assetDataPairsResponse: AssetPairsResponse = {
total: 43,

View File

@@ -1,4 +1,4 @@
import { FeeRecipientsResponse } from '../../../src/types';
import { FeeRecipientsResponse } from '@0xproject/types';
export const feeRecipientsResponse: FeeRecipientsResponse = {
total: 3,

View File

@@ -1,6 +1,6 @@
import { BigNumber } from '@0xproject/utils';
import { OrderConfigResponse } from '../../../src/types';
import { OrderConfigResponse } from '@0xproject/types';
export const orderConfigResponse: OrderConfigResponse = {
senderAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',

View File

@@ -1,6 +1,6 @@
import { BigNumber } from '@0xproject/utils';
import { OrderbookResponse } from '../../../src/types';
import { OrderbookResponse } from '@0xproject/types';
export const orderbookResponse: OrderbookResponse = {
bids: {

View File

@@ -1,6 +1,6 @@
import { BigNumber } from '@0xproject/utils';
import { OrdersResponse } from '../../../src/types';
import { OrdersResponse } from '@0xproject/types';
export const ordersResponse: OrdersResponse = {
total: 984,

View File

@@ -1,3 +1,4 @@
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
import * as dirtyChai from 'dirty-chai';
@@ -138,21 +139,21 @@ describe('HttpClient', () => {
const request = {
makerAddress: '0x9e56625509c2f60af937f23b7b532600390e8c8b',
takerAddress: '0xa2b31dacf30a9c50ca473337c01d8a201ae33e32',
makerAssetAmount: '10000000000000000',
takerAssetAmount: '20000000000000000',
expirationTimeSeconds: '1532560590',
makerAssetAmount: new BigNumber('10000000000000000'),
takerAssetAmount: new BigNumber('20000000000000000'),
expirationTimeSeconds: new BigNumber('1532560590'),
makerAssetData: '0xf47261b04c32345ced77393b3530b1eed0f346429d',
takerAssetData: '0x0257179264389b814a946f3e92105513705ca6b990',
exchangeAddress: '0x12459c951127e0c374ff9105dda097662a027093',
};
const url = `${relayUrl}/order_config`;
it('gets order config', async () => {
fetchMock.post(url, orderConfigResponseJSON);
fetchMock.get(url, orderConfigResponseJSON);
const fees = await relayerClient.getOrderConfigAsync(request);
expect(fees).to.be.deep.equal(orderConfigResponse);
});
it('does not mutate input', async () => {
fetchMock.post(url, orderConfigResponseJSON);
fetchMock.get(url, orderConfigResponseJSON);
const makerAssetAmountBefore = request.makerAssetAmount;
const takerAssetAmountBefore = request.takerAssetAmount;
const expirationTimeSecondsBefore = request.expirationTimeSeconds;
@@ -162,7 +163,7 @@ describe('HttpClient', () => {
expect(expirationTimeSecondsBefore).to.be.deep.equal(request.expirationTimeSeconds);
});
it('throws an error for invalid JSON response', async () => {
fetchMock.post(url, { test: 'dummy' });
fetchMock.get(url, { test: 'dummy' });
expect(relayerClient.getOrderConfigAsync(request)).to.be.rejected();
});
});

View File

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
"outDir": "lib",
"rootDir": "."
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@@ -0,0 +1,7 @@
{
"extends": "../../typedoc-tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@@ -1,4 +1,80 @@
[
{
"version": "2.0.0",
"changes": [
{
"note":
"Fixes dropped events in subscriptions by fetching logs by blockHash instead of blockNumber. Support for fetching by blockHash was added in Geth > v1.8.13 and Parity > v2.1.0. Infura works too.",
"pr": 1080
},
{
"note":
"Fix misunderstanding about blockstream interface callbacks and pass the raw JSON RPC responses to it",
"pr": 1080
}
],
"timestamp": 1537907159
},
{
"version": "1.0.5",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1537875740
},
{
"version": "1.0.4",
"changes": [
{
"note": "Dependencies updated"
}
],
"timestamp": 1537541580
},
{
"version": "1.0.3",
"changes": [
{
"note": "Drastically reduce the bundle size by removing unused parts of included contract artifacts."
}
],
"timestamp": 1537369748
},
{
"version": "1.0.2",
"changes": [
{
"note": "Add ZRX & WETH mainnet contract addresses into the included artifacts"
}
],
"timestamp": 1537265493
},
{
"version": "1.0.1",
"changes": [
{
"note": "Add `OrderValidatorWrapper`"
},
{
"note":
"Fix bug where contracts not deployed on a network showed an `EXCHANGE_CONTRACT_DOES_NOT_EXIST` error instead of `CONTRACT_NOT_DEPLOYED_ON_NETWORK`",
"pr": 1044
},
{
"note":
"Export `AssetBalanceAndProxyAllowanceFetcher` and `OrderFilledCancelledFetcher` implementations",
"pr": 1054
},
{
"note":
"Add `validateOrderFillableOrThrowAsync` and `validateFillOrderThrowIfInvalidAsync` to ExchangeWrapper",
"pr": 1054
}
],
"timestamp": 1536142250
},
{
"version": "1.0.1-rc.5",
"changes": [

View File

@@ -5,6 +5,34 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.0.0 - _September 25, 2018_
* Fixes dropped events in subscriptions by fetching logs by blockHash instead of blockNumber. Support for fetching by blockHash was added in Geth > v1.8.13 and Parity > v2.1.0. Infura works too. (#1080)
* Fix misunderstanding about blockstream interface callbacks and pass the raw JSON RPC responses to it (#1080)
## v1.0.5 - _September 25, 2018_
* Dependencies updated
## v1.0.4 - _September 21, 2018_
* Dependencies updated
## v1.0.3 - _September 19, 2018_
* Drastically reduce the bundle size by removing unused parts of included contract artifacts.
## v1.0.2 - _September 18, 2018_
* Add ZRX & WETH mainnet contract addresses into the included artifacts
## v1.0.1 - _September 5, 2018_
* Add `OrderValidatorWrapper`
* Fix bug where contracts not deployed on a network showed an `EXCHANGE_CONTRACT_DOES_NOT_EXIST` error instead of `CONTRACT_NOT_DEPLOYED_ON_NETWORK` (#1044)
* Export `AssetBalanceAndProxyAllowanceFetcher` and `OrderFilledCancelledFetcher` implementations (#1054)
* Add `validateOrderFillableOrThrowAsync` and `validateFillOrderThrowIfInvalidAsync` to ExchangeWrapper (#1054)
## v1.0.1-rc.5 - _August 27, 2018_
* Fix missing `BlockParamLiteral` type import issue

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/contract-wrappers",
"version": "1.0.1-rc.5",
"version": "2.0.0",
"description": "Smart TS wrappers for 0x smart contracts",
"keywords": [
"0xproject",
@@ -11,26 +11,23 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && tsc",
"pre_build": "run-s update_artifacts_v2_beta update_artifacts_v2 generate_contract_wrappers copy_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers",
"build": "yarn pre_build && tsc -b",
"pre_build": "run-s update_artifacts generate_contract_wrappers copy_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder|OrderValidator).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_artifacts_v2_beta": "for i in ${npm_package_config_contracts_v2_beta}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-beta-testnet/$i.json src/artifacts; done;",
"update_artifacts_v2": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json src/artifacts; done;",
"update_artifacts": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-trimmed/$i.json src/artifacts; done;",
"copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts",
"clean": "shx rm -rf _bundles lib test_temp test/artifacts src/contract_wrappers/generated src/artifacts generated_docs",
"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",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES"
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"contracts_v2_beta": "AssetProxyOwner Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder OrderValidator",
"contracts_v2": "DummyERC20Token DummyERC721Token",
"contracts_v2": "AssetProxyOwner Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder OrderValidator DummyERC20Token DummyERC721Token",
"postpublish": {
"assets": []
}
@@ -44,16 +41,17 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@0xproject/abi-gen": "^1.0.7",
"@0xproject/dev-utils": "^1.0.6",
"@0xproject/migrations": "^1.0.6",
"@0xproject/subproviders": "^2.0.1",
"@0xproject/tslint-config": "^1.0.6",
"@0xproject/abi-gen": "^1.0.11",
"@0xproject/dev-utils": "^1.0.10",
"@0xproject/migrations": "^1.0.12",
"@0xproject/subproviders": "^2.0.5",
"@0xproject/tslint-config": "^1.0.7",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",
"@types/node": "*",
"@types/sinon": "^2.2.2",
"@types/uuid": "^3.4.2",
"@types/web3-provider-engine": "^14.0.0",
"awesome-typescript-loader": "^3.1.3",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
@@ -74,17 +72,17 @@
"web3-provider-engine": "14.0.6"
},
"dependencies": {
"@0xproject/assert": "^1.0.7",
"@0xproject/base-contract": "^2.0.1",
"@0xproject/fill-scenarios": "^1.0.1-rc.5",
"@0xproject/json-schemas": "^1.0.1-rc.6",
"@0xproject/order-utils": "^1.0.1-rc.6",
"@0xproject/types": "^1.0.1-rc.6",
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@0xproject/web3-wrapper": "^2.0.1",
"ethereum-types": "^1.0.5",
"ethereumjs-blockstream": "5.0.0",
"@0xproject/assert": "^1.0.11",
"@0xproject/base-contract": "^2.0.5",
"@0xproject/fill-scenarios": "^1.0.5",
"@0xproject/json-schemas": "^1.0.4",
"@0xproject/order-utils": "^1.0.5",
"@0xproject/types": "^1.1.1",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"@0xproject/web3-wrapper": "^3.0.1",
"ethereum-types": "^1.0.8",
"ethereumjs-blockstream": "6.0.0",
"ethereumjs-util": "^5.1.1",
"ethers": "3.0.22",
"js-sha3": "^0.7.0",

View File

@@ -8,6 +8,7 @@ import * as ERC721Proxy from './artifacts/ERC721Proxy.json';
import * as ERC721Token from './artifacts/ERC721Token.json';
import * as Exchange from './artifacts/Exchange.json';
import * as Forwarder from './artifacts/Forwarder.json';
import * as OrderValidator from './artifacts/OrderValidator.json';
import * as EtherToken from './artifacts/WETH9.json';
import * as ZRXToken from './artifacts/ZRXToken.json';
@@ -22,4 +23,5 @@ export const artifacts = {
ERC20Proxy: (ERC20Proxy as any) as ContractArtifact,
ERC721Proxy: (ERC721Proxy as any) as ContractArtifact,
Forwarder: (Forwarder as any) as ContractArtifact,
OrderValidator: (OrderValidator as any) as ContractArtifact,
};

View File

@@ -12,6 +12,7 @@ import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper';
import { OrderValidatorWrapper } from './contract_wrappers/order_validator_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';
@@ -52,6 +53,10 @@ export class ContractWrappers {
* An instance of the ForwarderWrapper class containing methods for interacting with any Forwarder smart contract.
*/
public forwarder: ForwarderWrapper;
/**
* An instance of the OrderValidatorWrapper class containing methods for interacting with any OrderValidator smart contract.
*/
public orderValidator: OrderValidatorWrapper;
private _web3Wrapper: Web3Wrapper;
/**
@@ -106,6 +111,8 @@ export class ContractWrappers {
this.exchange = new ExchangeWrapper(
this._web3Wrapper,
config.networkId,
this.erc20Token,
this.erc721Token,
config.exchangeContractAddress,
config.zrxContractAddress,
blockPollingIntervalMs,
@@ -116,6 +123,7 @@ export class ContractWrappers {
config.forwarderContractAddress,
config.zrxContractAddress,
);
this.orderValidator = new OrderValidatorWrapper(this._web3Wrapper, config.networkId);
}
/**
* Sets a new web3 provider for 0x.js. Updating the provider will stop all

View File

@@ -1,5 +1,5 @@
import { AbiDecoder, intervalUtils, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { marshaller, Web3Wrapper } from '@0xproject/web3-wrapper';
import {
BlockParamLiteral,
ContractAbi,
@@ -8,6 +8,7 @@ import {
LogEntry,
LogWithDecodedArgs,
RawLog,
RawLogEntry,
} from 'ethereum-types';
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
import * as _ from 'lodash';
@@ -145,16 +146,20 @@ export abstract class ContractWrapper {
}
protected _getContractAddress(artifact: ContractArtifact, addressIfExists?: string): string {
if (_.isUndefined(addressIfExists)) {
if (_.isUndefined(artifact.networks[this._networkId])) {
throw new Error(ContractWrappersError.ContractNotDeployedOnNetwork);
}
const contractAddress = artifact.networks[this._networkId].address;
if (_.isUndefined(contractAddress)) {
throw new Error(ContractWrappersError.ExchangeContractDoesNotExist);
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contractName]);
}
return contractAddress;
} else {
return addressIfExists;
}
}
private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, log: LogEntry): void {
private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, rawLog: RawLogEntry): void {
const log: LogEntry = marshaller.unmarshalLog(rawLog);
_.forEach(this._filters, (filter: FilterObject, filterToken: string) => {
if (filterUtils.matchesFilter(log, filter)) {
const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>;
@@ -171,8 +176,8 @@ export abstract class ContractWrapper {
throw new Error(ContractWrappersError.SubscriptionAlreadyPresent);
}
this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
this._blockstreamGetBlockOrNullAsync.bind(this),
this._blockstreamGetLogsAsync.bind(this),
ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose),
);
const catchAllLogFilter = {};
@@ -191,6 +196,32 @@ export abstract class ContractWrapper {
this._onLogStateChanged.bind(this, isRemoved),
);
}
// This method only exists in order to comply with the expected interface of Blockstream's constructor
private async _blockstreamGetBlockOrNullAsync(hash: string): Promise<Block | null> {
const shouldIncludeTransactionData = false;
const blockOrNull = await this._web3Wrapper.sendRawPayloadAsync<Block | null>({
method: 'eth_getBlockByHash',
params: [hash, shouldIncludeTransactionData],
});
return blockOrNull;
}
// This method only exists in order to comply with the expected interface of Blockstream's constructor
private async _blockstreamGetLatestBlockOrNullAsync(): Promise<Block | null> {
const shouldIncludeTransactionData = false;
const blockOrNull = await this._web3Wrapper.sendRawPayloadAsync<Block | null>({
method: 'eth_getBlockByNumber',
params: [BlockParamLiteral.Latest, shouldIncludeTransactionData],
});
return blockOrNull;
}
// This method only exists in order to comply with the expected interface of Blockstream's constructor
private async _blockstreamGetLogsAsync(filterOptions: FilterObject): Promise<RawLogEntry[]> {
const logs = await this._web3Wrapper.sendRawPayloadAsync<RawLogEntry[]>({
method: 'eth_getLogs',
params: [filterOptions],
});
return logs as RawLogEntry[];
}
// HACK: This should be a package-scoped method (which doesn't exist in TS)
// We don't want this method available in the public interface for all classes
// who inherit from ContractWrapper, and it is only used by the internal implementation
@@ -209,11 +240,14 @@ export abstract class ContractWrapper {
delete this._blockAndLogStreamerIfExists;
}
private async _reconcileBlockAsync(): Promise<void> {
const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
const latestBlockOrNull = await this._blockstreamGetLatestBlockOrNullAsync();
if (_.isNull(latestBlockOrNull)) {
return; // noop
}
// We need to coerce to Block type cause Web3.Block includes types for mempool blocks
if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
// If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block);
await this._blockAndLogStreamerIfExists.reconcileNewBlock(latestBlockOrNull);
}
}
}

View File

@@ -1,12 +1,19 @@
import { schemas } from '@0xproject/json-schemas';
import { assetDataUtils } from '@0xproject/order-utils';
import {
assetDataUtils,
BalanceAndProxyAllowanceLazyStore,
ExchangeTransferSimulator,
OrderValidationUtils,
} from '@0xproject/order-utils';
import { AssetProxyId, Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import { BlockParamLiteral, ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { AssetBalanceAndProxyAllowanceFetcher } from '../fetchers/asset_balance_and_proxy_allowance_fetcher';
import { OrderFilledCancelledFetcher } from '../fetchers/order_filled_cancelled_fetcher';
import { methodOptsSchema } from '../schemas/method_opts_schema';
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
import { txOptsSchema } from '../schemas/tx_opts_schema';
@@ -17,13 +24,17 @@ import {
IndexedFilterValues,
MethodOpts,
OrderInfo,
OrderStatus,
OrderTransactionOpts,
ValidateOrderFillableOpts,
} from '../types';
import { assert } from '../utils/assert';
import { decorators } from '../utils/decorators';
import { TransactionEncoder } from '../utils/transaction_encoder';
import { ContractWrapper } from './contract_wrapper';
import { ERC20TokenWrapper } from './erc20_token_wrapper';
import { ERC721TokenWrapper } from './erc721_token_wrapper';
import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from './generated/exchange';
/**
@@ -33,6 +44,8 @@ import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from './generated
export class ExchangeWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.Exchange.compilerOutput.abi;
private _exchangeContractIfExists?: ExchangeContract;
private _erc721TokenWrapper: ERC721TokenWrapper;
private _erc20TokenWrapper: ERC20TokenWrapper;
private _contractAddressIfExists?: string;
private _zrxContractAddressIfExists?: string;
/**
@@ -48,11 +61,15 @@ export class ExchangeWrapper extends ContractWrapper {
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
erc20TokenWrapper: ERC20TokenWrapper,
erc721TokenWrapper: ERC721TokenWrapper,
contractAddressIfExists?: string,
zrxContractAddressIfExists?: string,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
this._erc20TokenWrapper = erc20TokenWrapper;
this._erc721TokenWrapper = erc721TokenWrapper;
this._contractAddressIfExists = contractAddressIfExists;
this._zrxContractAddressIfExists = zrxContractAddressIfExists;
}
@@ -1084,6 +1101,64 @@ export class ExchangeWrapper extends ContractWrapper {
);
return logs;
}
/**
* Validate if the supplied order is fillable, and throw if it isn't
* @param signedOrder SignedOrder of interest
* @param opts ValidateOrderFillableOpts options (e.g expectedFillTakerTokenAmount.
* If it isn't supplied, we check if the order is fillable for a non-zero amount)
*/
public async validateOrderFillableOrThrowAsync(
signedOrder: SignedOrder,
opts: ValidateOrderFillableOpts = {},
): Promise<void> {
const balanceAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher(
this._erc20TokenWrapper,
this._erc721TokenWrapper,
BlockParamLiteral.Latest,
);
const balanceAllowanceStore = new BalanceAndProxyAllowanceLazyStore(balanceAllowanceFetcher);
const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore);
const expectedFillTakerTokenAmountIfExists = opts.expectedFillTakerTokenAmount;
const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher);
await orderValidationUtils.validateOrderFillableOrThrowAsync(
exchangeTradeSimulator,
signedOrder,
this.getZRXAssetData(),
expectedFillTakerTokenAmountIfExists,
);
}
/**
* Validate a call to FillOrder and throw if it wouldn't succeed
* @param signedOrder SignedOrder of interest
* @param fillTakerAssetAmount Amount we'd like to fill the order for
* @param takerAddress The taker of the order
*/
public async validateFillOrderThrowIfInvalidAsync(
signedOrder: SignedOrder,
fillTakerAssetAmount: BigNumber,
takerAddress: string,
): Promise<void> {
const balanceAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher(
this._erc20TokenWrapper,
this._erc721TokenWrapper,
BlockParamLiteral.Latest,
);
const balanceAllowanceStore = new BalanceAndProxyAllowanceLazyStore(balanceAllowanceFetcher);
const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore);
const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher);
await orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
exchangeTradeSimulator,
this._web3Wrapper.getProvider(),
signedOrder,
fillTakerAssetAmount,
takerAddress,
this.getZRXAssetData(),
);
}
/**
* Retrieves the Ethereum address of the Exchange contract deployed on the network
* that the user-passed web3 provider is connected to.

View File

@@ -12,6 +12,7 @@ import { TransactionOpts } from '../types';
import { assert } from '../utils/assert';
import { calldataOptimizationUtils } from '../utils/calldata_optimization_utils';
import { constants } from '../utils/constants';
import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper';
import { ForwarderContract } from './generated/forwarder';
@@ -57,7 +58,7 @@ export class ForwarderWrapper extends ContractWrapper {
takerAddress: string,
ethAmount: BigNumber,
signedFeeOrders: SignedOrder[] = [],
feePercentage: BigNumber = constants.ZERO_AMOUNT,
feePercentage: number = 0,
feeRecipientAddress: string = constants.NULL_ADDRESS,
txOpts: TransactionOpts = {},
): Promise<string> {
@@ -66,7 +67,7 @@ export class ForwarderWrapper extends ContractWrapper {
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.isBigNumber('ethAmount', ethAmount);
assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
assert.isBigNumber('feePercentage', feePercentage);
assert.isNumber('feePercentage', feePercentage);
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
// other assertions
@@ -76,6 +77,8 @@ export class ForwarderWrapper extends ContractWrapper {
this.getZRXTokenAddress(),
this.getEtherTokenAddress(),
);
// format feePercentage
const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage);
// lowercase input addresses
const normalizedTakerAddress = takerAddress.toLowerCase();
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
@@ -89,7 +92,7 @@ export class ForwarderWrapper extends ContractWrapper {
_.map(optimizedMarketOrders, order => order.signature),
optimizedFeeOrders,
_.map(optimizedFeeOrders, order => order.signature),
feePercentage,
formattedFeePercentage,
feeRecipientAddress,
{
value: ethAmount,
@@ -124,7 +127,7 @@ export class ForwarderWrapper extends ContractWrapper {
takerAddress: string,
ethAmount: BigNumber,
signedFeeOrders: SignedOrder[] = [],
feePercentage: BigNumber = constants.ZERO_AMOUNT,
feePercentage: number = 0,
feeRecipientAddress: string = constants.NULL_ADDRESS,
txOpts: TransactionOpts = {},
): Promise<string> {
@@ -134,7 +137,7 @@ export class ForwarderWrapper extends ContractWrapper {
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.isBigNumber('ethAmount', ethAmount);
assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
assert.isBigNumber('feePercentage', feePercentage);
assert.isNumber('feePercentage', feePercentage);
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
// other assertions
@@ -144,6 +147,8 @@ export class ForwarderWrapper extends ContractWrapper {
this.getZRXTokenAddress(),
this.getEtherTokenAddress(),
);
// format feePercentage
const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage);
// lowercase input addresses
const normalizedTakerAddress = takerAddress.toLowerCase();
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
@@ -158,7 +163,7 @@ export class ForwarderWrapper extends ContractWrapper {
_.map(optimizedMarketOrders, order => order.signature),
optimizedFeeOrders,
_.map(optimizedFeeOrders, order => order.signature),
feePercentage,
formattedFeePercentage,
feeRecipientAddress,
{
value: ethAmount,

View File

@@ -0,0 +1,187 @@
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { ContractAbi } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
import { BalanceAndAllowance, OrderAndTraderInfo, TraderInfo } from '../types';
import { assert } from '../utils/assert';
import { ContractWrapper } from './contract_wrapper';
import { OrderValidatorContract } from './generated/order_validator';
/**
* This class includes the functionality related to interacting with the OrderValidator contract.
*/
export class OrderValidatorWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.OrderValidator.compilerOutput.abi;
private _orderValidatorContractIfExists?: OrderValidatorContract;
/**
* Instantiate OrderValidatorWrapper
* @param web3Wrapper Web3Wrapper instance to use
* @param networkId Desired networkId
*/
constructor(web3Wrapper: Web3Wrapper, networkId: number) {
super(web3Wrapper, networkId);
}
/**
* Get an object conforming to OrderAndTraderInfo containing on-chain information of the provided order and address
* @param order An object conforming to SignedOrder
* @param takerAddress An ethereum address
* @return OrderAndTraderInfo
*/
public async getOrderAndTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<OrderAndTraderInfo> {
assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
assert.isETHAddressHex('takerAddress', takerAddress);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const orderAndTraderInfo = await OrderValidatorContractInstance.getOrderAndTraderInfo.callAsync(
order,
takerAddress,
);
const result = {
orderInfo: orderAndTraderInfo[0],
traderInfo: orderAndTraderInfo[1],
};
return result;
}
/**
* Get an array of objects conforming to OrderAndTraderInfo containing on-chain information of the provided orders and addresses
* @param orders An array of objects conforming to SignedOrder
* @param takerAddresses An array of ethereum addresses
* @return array of OrderAndTraderInfo
*/
public async getOrdersAndTradersInfoAsync(
orders: SignedOrder[],
takerAddresses: string[],
): Promise<OrderAndTraderInfo[]> {
assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
_.forEach(takerAddresses, (takerAddress, index) =>
assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
);
assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const ordersAndTradersInfo = await OrderValidatorContractInstance.getOrdersAndTradersInfo.callAsync(
orders,
takerAddresses,
);
const orderInfos = ordersAndTradersInfo[0];
const traderInfos = ordersAndTradersInfo[1];
const result = _.map(orderInfos, (orderInfo, index) => {
const traderInfo = traderInfos[index];
return {
orderInfo,
traderInfo,
};
});
return result;
}
/**
* Get an object conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order
* @param order An object conforming to SignedOrder
* @param takerAddress An ethereum address
* @return TraderInfo
*/
public async getTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<TraderInfo> {
assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
assert.isETHAddressHex('takerAddress', takerAddress);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const result = await OrderValidatorContractInstance.getTraderInfo.callAsync(order, takerAddress);
return result;
}
/**
* Get an array of objects conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order
* @param orders An array of objects conforming to SignedOrder
* @param takerAddresses An array of ethereum addresses
* @return array of TraderInfo
*/
public async getTradersInfoAsync(orders: SignedOrder[], takerAddresses: string[]): Promise<TraderInfo[]> {
assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
_.forEach(takerAddresses, (takerAddress, index) =>
assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
);
assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const result = await OrderValidatorContractInstance.getTradersInfo.callAsync(orders, takerAddresses);
return result;
}
/**
* Get an object conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and assetData
* @param address An ethereum address
* @param assetData An encoded string that can be decoded by a specified proxy contract
* @return BalanceAndAllowance
*/
public async getBalanceAndAllowanceAsync(address: string, assetData: string): Promise<BalanceAndAllowance> {
assert.isETHAddressHex('address', address);
assert.isHexString('assetData', assetData);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const balanceAndAllowance = await OrderValidatorContractInstance.getBalanceAndAllowance.callAsync(
address,
assetData,
);
const result = {
balance: balanceAndAllowance[0],
allowance: balanceAndAllowance[1],
};
return result;
}
/**
* Get an array of objects conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and array of assetDatas
* @param address An ethereum address
* @param assetDatas An array of encoded strings that can be decoded by a specified proxy contract
* @return BalanceAndAllowance
*/
public async getBalancesAndAllowancesAsync(address: string, assetDatas: string[]): Promise<BalanceAndAllowance[]> {
assert.isETHAddressHex('address', address);
_.forEach(assetDatas, (assetData, index) => assert.isHexString(`assetDatas[${index}]`, assetData));
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const balancesAndAllowances = await OrderValidatorContractInstance.getBalancesAndAllowances.callAsync(
address,
assetDatas,
);
const balances = balancesAndAllowances[0];
const allowances = balancesAndAllowances[1];
const result = _.map(balances, (balance, index) => {
const allowance = allowances[index];
return {
balance,
allowance,
};
});
return result;
}
/**
* Get owner address of tokenId by calling `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.
* @param tokenAddress An ethereum address
* @param tokenId An ERC721 tokenId
* @return Owner of tokenId or null address if unowned
*/
public async getERC721TokenOwnerAsync(tokenAddress: string, tokenId: BigNumber): Promise<string | undefined> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isBigNumber('tokenId', tokenId);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const result = await OrderValidatorContractInstance.getERC721TokenOwner.callAsync(tokenAddress, tokenId);
return result;
}
// 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._orderValidatorContractIfExists;
}
private async _getOrderValidatorContractAsync(): Promise<OrderValidatorContract> {
if (!_.isUndefined(this._orderValidatorContractIfExists)) {
return this._orderValidatorContractIfExists;
}
const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(artifacts.OrderValidator);
const contractInstance = new OrderValidatorContract(
abi,
address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._orderValidatorContractIfExists = contractInstance;
return this._orderValidatorContractIfExists;
}
}

View File

@@ -1,8 +1,11 @@
// tslint:disable:no-unnecessary-type-assertion
import { BlockParamLiteral, ERC20TokenWrapper, ERC721TokenWrapper } from '@0xproject/contract-wrappers';
import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0xproject/order-utils';
import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { BlockParamLiteral } from 'ethereum-types';
import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper';
import { ERC721TokenWrapper } from '../contract_wrappers/erc721_token_wrapper';
export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher {
private readonly _erc20Token: ERC20TokenWrapper;

View File

@@ -1,7 +1,10 @@
// tslint:disable:no-unnecessary-type-assertion
import { BlockParamLiteral, ExchangeWrapper } from '@0xproject/contract-wrappers';
import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
import { BigNumber } from '@0xproject/utils';
import { BlockParamLiteral } from 'ethereum-types';
import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher {
private readonly _exchange: ExchangeWrapper;

View File

@@ -6,6 +6,7 @@ export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
export { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper';
export { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper';
export { TransactionEncoder } from './utils/transaction_encoder';
@@ -21,6 +22,10 @@ export {
OrderInfo,
EventCallback,
DecodedLogEvent,
BalanceAndAllowance,
OrderAndTraderInfo,
TraderInfo,
ValidateOrderFillableOpts,
} from './types';
export { Order, SignedOrder, AssetProxyId } from '@0xproject/types';
@@ -81,3 +86,8 @@ export {
ExchangeEventArgs,
ExchangeEvents,
} from './contract_wrappers/generated/exchange';
export { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
export { AssetBalanceAndProxyAllowanceFetcher } from './fetchers/asset_balance_and_proxy_allowance_fetcher';
export { OrderFilledCancelledFetcher } from './fetchers/order_filled_cancelled_fetcher';

View File

@@ -188,3 +188,24 @@ export enum OrderStatus {
FULLY_FILLED,
CANCELLED,
}
export interface TraderInfo {
makerBalance: BigNumber;
makerAllowance: BigNumber;
takerBalance: BigNumber;
takerAllowance: BigNumber;
makerZrxBalance: BigNumber;
makerZrxAllowance: BigNumber;
takerZrxBalance: BigNumber;
takerZrxAllowance: BigNumber;
}
export interface OrderAndTraderInfo {
orderInfo: OrderInfo;
traderInfo: TraderInfo;
}
export interface BalanceAndAllowance {
balance: BigNumber;
allowance: BigNumber;
}

View File

@@ -12,4 +12,6 @@ export const constants = {
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
DEFAULT_BLOCK_POLLING_INTERVAL: 1000,
ZERO_AMOUNT: new BigNumber(0),
ONE_AMOUNT: new BigNumber(1),
ETHER_TOKEN_DECIMALS: 18,
};

View File

@@ -24,7 +24,7 @@ const contractCallErrorTransformer = (error: Error) => {
const schemaErrorTransformer = (error: Error) => {
if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) {
const errMsg =
'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
'Order taker must be of type string. If you want anyone to be able to fill an order - pass NULL_ADDRESS';
return new Error(errMsg);
}
return error;

View File

@@ -1,4 +1,7 @@
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { constants } from './constants';
export const utils = {
getCurrentUnixTimestampSec(): BigNumber {
@@ -8,4 +11,7 @@ export const utils = {
getCurrentUnixTimestampMs(): BigNumber {
return new BigNumber(Date.now());
},
numberPercentageToEtherTokenAmountPercentage(percentage: number): BigNumber {
return Web3Wrapper.toBaseUnitAmount(constants.ONE_AMOUNT, constants.ETHER_TOKEN_DECIMALS).mul(percentage);
},
};

View File

@@ -358,7 +358,7 @@ describe('ExchangeWrapper', () => {
describe('#getVersionAsync', () => {
it('should return version the hash', async () => {
const version = await contractWrappers.exchange.getVersionAsync();
const VERSION = '2.0.1-alpha';
const VERSION = '2.0.0';
expect(version).to.be.equal(VERSION);
});
});

View File

@@ -25,10 +25,8 @@ describe('ForwarderWrapper', () => {
blockPollingIntervalMs: 0,
};
const fillableAmount = new BigNumber(5);
const takerTokenFillAmount = new BigNumber(5);
let contractWrappers: ContractWrappers;
let fillScenarios: FillScenarios;
let forwarderContractAddress: string;
let exchangeContractAddress: string;
let zrxTokenAddress: string;
let userAddresses: string[];
@@ -46,7 +44,6 @@ describe('ForwarderWrapper', () => {
before(async () => {
await blockchainLifecycle.startAsync();
contractWrappers = new ContractWrappers(provider, contractWrappersConfig);
forwarderContractAddress = contractWrappers.forwarder.getContractAddress();
exchangeContractAddress = contractWrappers.exchange.getContractAddress();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
zrxTokenAddress = tokenUtils.getProtocolTokenAddress();

View File

@@ -0,0 +1,142 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { DoneCallback, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { BlockParamLiteral } from 'ethereum-types';
import * as _ from 'lodash';
import 'mocha';
import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src';
import { DecodedLogEvent, OrderInfo, TraderInfo } from '../src/types';
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('OrderValidator', () => {
const contractWrappersConfig = {
networkId: constants.TESTRPC_NETWORK_ID,
blockPollingIntervalMs: 0,
};
const fillableAmount = new BigNumber(5);
const partialFillAmount = new BigNumber(2);
let contractWrappers: ContractWrappers;
let fillScenarios: FillScenarios;
let exchangeContractAddress: string;
let zrxTokenAddress: string;
let zrxTokenAssetData: string;
let userAddresses: string[];
let coinbase: string;
let makerAddress: string;
let takerAddress: string;
let feeRecipient: string;
let anotherMakerAddress: string;
let makerTokenAddress: string;
let takerTokenAddress: string;
let makerAssetData: string;
let takerAssetData: string;
let signedOrder: SignedOrder;
let anotherSignedOrder: SignedOrder;
before(async () => {
await blockchainLifecycle.startAsync();
contractWrappers = new ContractWrappers(provider, contractWrappersConfig);
exchangeContractAddress = contractWrappers.exchange.getContractAddress();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
zrxTokenAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress);
fillScenarios = new FillScenarios(
provider,
userAddresses,
zrxTokenAddress,
exchangeContractAddress,
contractWrappers.erc20Proxy.getContractAddress(),
contractWrappers.erc721Proxy.getContractAddress(),
);
[coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
[makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
takerTokenAddress = tokenUtils.getWethTokenAddress();
[makerAssetData, takerAssetData] = [
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
assetDataUtils.encodeERC20AssetData(takerTokenAddress),
];
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerAssetData,
takerAssetData,
makerAddress,
constants.NULL_ADDRESS,
fillableAmount,
);
anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
zrxTokenAssetData,
takerAssetData,
makerAddress,
constants.NULL_ADDRESS,
fillableAmount,
);
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('#getOrdersAndTradersInfoAsync', () => {
let signedOrders: SignedOrder[];
let takerAddresses: string[];
let ordersInfo: OrderInfo[];
let tradersInfo: TraderInfo[];
beforeEach(async () => {
signedOrders = [signedOrder, anotherSignedOrder];
takerAddresses = [takerAddress, takerAddress];
const ordersAndTradersInfo = await contractWrappers.orderValidator.getOrdersAndTradersInfoAsync(
signedOrders,
takerAddresses,
);
ordersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.orderInfo);
tradersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.traderInfo);
});
it('should return the same number of order infos and trader infos as input orders', async () => {
expect(ordersInfo.length).to.be.equal(signedOrders.length);
expect(tradersInfo.length).to.be.equal(takerAddresses.length);
});
it('should return correct on-chain order info for input orders', async () => {
const firstOrderInfo = ordersInfo[0];
const secondOrderInfo = ordersInfo[1];
expect(firstOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE);
expect(firstOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
expect(secondOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE);
expect(secondOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should return correct on-chain trader info for input takers', async () => {
const firstTraderInfo = tradersInfo[0];
const secondTraderInfo = tradersInfo[1];
expect(firstTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5));
expect(firstTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5));
expect(firstTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0));
expect(firstTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0));
expect(firstTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5));
expect(firstTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5));
expect(firstTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0));
expect(firstTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0));
expect(secondTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5));
expect(secondTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5));
expect(secondTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0));
expect(secondTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0));
expect(secondTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5));
expect(secondTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5));
expect(secondTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0));
expect(secondTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0));
});
});
});

View File

@@ -61,7 +61,7 @@ describe('SubscriptionTest', () => {
callback,
);
stubs = [
Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws(
Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockIfExistsAsync').throws(
new Error('JSON RPC error'),
),
];

View File

@@ -15,4 +15,5 @@ export const constants = {
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,
ZERO_AMOUNT: new BigNumber(0),
};

View File

@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib"
"outDir": "lib",
"rootDir": "."
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@@ -0,0 +1,7 @@
{
"extends": "../../typedoc-tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@@ -1,14 +1,35 @@
## Contracts
Smart contracts that implement the 0x protocol.
Smart contracts that implement the 0x protocol. Addresses of the deployed contracts can be found [here](https://0xproject.com/wiki#Deployed-Addresses).
## Usage
* [Docs](https://0xproject.com/docs/contracts)
* [Overview of 0x protocol architecture](https://0xproject.com/wiki#Architecture)
* [0x smart contract interactions](https://0xproject.com/wiki#Contract-Interactions)
* [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses)
* [0x protocol message format](https://0xproject.com/wiki#Message-Format)
### 2.0.0
Contracts that make up and interact with version 2.0.0 of the protocol can be found in the `src/2.0.0` directory. The contents of this directory are broken down into the following subdirectories:
* protocol
* This directory contains the contracts that make up version 2.0.0. A full specification can be found [here](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* extensions
* This directory contains contracts that interact with the 2.0.0 contracts and will be used in production, such as the [Forwarder](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md) contract.
* examples
* This directory contains example implementations of contracts that interact with the protocol but are _not_ intended for use in production. Examples include [filter](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#filter-contracts) contracts, a [Wallet](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#wallet) contract, and a [Validator](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#validator) contract, among others.
* tokens
* This directory contains implementations of different tokens and token standards, including [wETH](https://weth.io/), ZRX, [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md), and [ERC721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md).
* multisig
* This directory contains the [Gnosis MultiSigWallet](https://github.com/gnosis/MultiSigWallet) and a custom extension that adds a timelock to transactions within the MultiSigWallet.
* utils
* This directory contains libraries and utils that are shared across all of the other directories.
* test
* This directory contains mocks and other contracts that are used solely for testing contracts within the other directories.
### 1.0.0
Contracts that make up version 1.0.0 of the protocol can be found in `src/1.0.0`. These contracts are considered deprecated and will have limited support going forward.
## Bug bounty
A bug bounty for the 2.0.0 contracts is ongoing! Instructions can be found [here](https://0xproject.com/wiki#Bug-Bounty).
## Contributing

View File

@@ -1,5 +1,5 @@
{
"artifactsDir": "../migrations/artifacts/2.0.0",
"artifactsDir": "../migrations/artifacts/development",
"contractsDir": "src/",
"compilerSettings": {
"optimizer": {
@@ -23,6 +23,7 @@
"DummyERC20Token",
"DummyERC721Receiver",
"DummyERC721Token",
"DummyMultipleReturnERC20Token",
"DummyNoReturnERC20Token",
"ERC20Proxy",
"ERC20Token",

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "contracts",
"version": "2.1.42",
"version": "2.1.47",
"engines": {
"node": ">=6.12"
},
@@ -11,10 +11,9 @@
"test": "test"
},
"scripts": {
"watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && tsc",
"build": "yarn pre_build && tsc -b",
"pre_build": "run-s compile copy_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles -u 4 '../migrations/artifacts/2.0.0/**/*' ./lib/artifacts;",
"copy_artifacts": "copyfiles -u 4 '../migrations/artifacts/development/**/*' ./lib/artifacts;",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
@@ -33,7 +32,7 @@
"lint-contracts": "solhint src/2.0.0/**/**/**/**/*.sol"
},
"config": {
"abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyNoReturnERC20Token|ERC20Proxy|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|TokenRegistry|Whitelist|WETH9|ZRXToken).json"
"abis": "../migrations/artifacts/development/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Proxy|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|TokenRegistry|Whitelist|WETH9|ZRXToken).json"
},
"repository": {
"type": "git",
@@ -46,16 +45,16 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
"devDependencies": {
"@0xproject/abi-gen": "^1.0.7",
"@0xproject/dev-utils": "^1.0.6",
"@0xproject/sol-compiler": "^1.1.1",
"@0xproject/sol-cov": "^2.1.1",
"@0xproject/subproviders": "^2.0.1",
"@0xproject/tslint-config": "^1.0.6",
"@0xproject/abi-gen": "^1.0.11",
"@0xproject/dev-utils": "^1.0.10",
"@0xproject/sol-compiler": "^1.1.5",
"@0xproject/sol-cov": "^2.1.5",
"@0xproject/subproviders": "^2.0.5",
"@0xproject/tslint-config": "^1.0.7",
"@types/bn.js": "^4.11.0",
"@types/ethereumjs-abi": "^0.6.0",
"@types/lodash": "4.14.104",
"@types/node": "^8.0.53",
"@types/node": "*",
"@types/yargs": "^10.0.0",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
@@ -73,15 +72,15 @@
"yargs": "^10.0.3"
},
"dependencies": {
"@0xproject/base-contract": "^2.0.1",
"@0xproject/order-utils": "^1.0.1-rc.6",
"@0xproject/types": "^1.0.1-rc.6",
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@0xproject/web3-wrapper": "^2.0.1",
"@0xproject/base-contract": "^2.0.5",
"@0xproject/order-utils": "^1.0.5",
"@0xproject/types": "^1.1.1",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"@0xproject/web3-wrapper": "^3.0.1",
"@types/js-combinatorics": "^0.5.29",
"bn.js": "^4.11.8",
"ethereum-types": "^1.0.5",
"ethereum-types": "^1.0.8",
"ethereumjs-abi": "0.6.5",
"ethereumjs-util": "^5.1.1",
"ethers": "3.0.22",

View File

@@ -34,7 +34,6 @@ contract Forwarder is
MixinExchangeWrapper,
MixinForwarderCore
{
constructor (
address _exchange,
bytes memory _zrxAssetData,

View File

@@ -31,7 +31,6 @@ contract MixinAssets is
LibConstants,
MAssets
{
using LibBytes for bytes;
bytes4 constant internal ERC20_TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)"));

View File

@@ -34,7 +34,6 @@ contract MixinExchangeWrapper is
LibConstants,
MExchangeWrapper
{
/// @dev Fills the input order.
/// Returns false if the transaction would otherwise revert.
/// @param order Order struct containing order specifications.
@@ -61,7 +60,7 @@ contract MixinExchangeWrapper is
// Call `fillOrder` and handle any exceptions gracefully
assembly {
let success := call(
gas, // forward all gas, TODO: look into gas consumption of assert/throw
gas, // forward all gas
exchange, // call address of Exchange contract
0, // transfer 0 wei
add(fillOrderCalldata, 32), // pointer to start of input (skip array length in first 32 bytes)
@@ -69,20 +68,14 @@ contract MixinExchangeWrapper is
fillOrderCalldata, // write output over input
128 // output size is 128 bytes
)
switch success
case 0 {
mstore(fillResults, 0)
mstore(add(fillResults, 32), 0)
mstore(add(fillResults, 64), 0)
mstore(add(fillResults, 96), 0)
}
case 1 {
if success {
mstore(fillResults, mload(fillOrderCalldata))
mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32)))
mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64)))
mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))
}
}
// fillResults values will be 0 by default if call was unsuccessful
return fillResults;
}

View File

@@ -39,7 +39,6 @@ contract MixinForwarderCore is
MExchangeWrapper,
IForwarderCore
{
using LibBytes for bytes;
/// @dev Constructor approves ERC20 proxy to transfer ZRX and WETH on this contract's behalf.
@@ -47,10 +46,12 @@ contract MixinForwarderCore is
public
{
address proxyAddress = EXCHANGE.getAssetProxy(ERC20_DATA_ID);
if (proxyAddress != address(0)) {
ETHER_TOKEN.approve(proxyAddress, MAX_UINT);
ZRX_TOKEN.approve(proxyAddress, MAX_UINT);
}
require(
proxyAddress != address(0),
"UNREGISTERED_ASSET_PROXY"
);
ETHER_TOKEN.approve(proxyAddress, MAX_UINT);
ZRX_TOKEN.approve(proxyAddress, MAX_UINT);
}
/// @dev Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.

View File

@@ -28,7 +28,6 @@ contract MixinWeth is
LibConstants,
MWeth
{
/// @dev Default payabale function, this allows us to withdraw WETH
function ()
public

View File

@@ -24,7 +24,6 @@ import "../interfaces/IAssets.sol";
contract MAssets is
IAssets
{
/// @dev Transfers given amount of asset to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
/// @param amount Amount of asset to transfer to sender.

View File

@@ -28,11 +28,11 @@ import "../../utils/LibBytes/LibBytes.sol";
contract OrderValidator {
using LibBytes for bytes;
bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256("ERC20Token(address)"));
bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256("ERC721Token(address,uint256)"));
using LibBytes for bytes;
struct TraderInfo {
uint256 makerBalance; // Maker's balance of makerAsset
uint256 makerAllowance; // Maker's allowance to corresponding AssetProxy

View File

@@ -1,13 +1,14 @@
// solhint-disable
pragma solidity ^0.4.10;
pragma solidity ^0.4.15;
/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution.
/// @author Stefan George - <stefan.george@consensys.net>
contract MultiSigWallet {
uint constant public MAX_OWNER_COUNT = 50;
/*
* Events
*/
event Confirmation(address indexed sender, uint indexed transactionId);
event Revocation(address indexed sender, uint indexed transactionId);
event Submission(uint indexed transactionId);
@@ -18,6 +19,14 @@ contract MultiSigWallet {
event OwnerRemoval(address indexed owner);
event RequirementChange(uint required);
/*
* Constants
*/
uint constant public MAX_OWNER_COUNT = 50;
/*
* Storage
*/
mapping (uint => Transaction) public transactions;
mapping (uint => mapping (address => bool)) public confirmations;
mapping (address => bool) public isOwner;
@@ -32,60 +41,54 @@ contract MultiSigWallet {
bool executed;
}
/*
* Modifiers
*/
modifier onlyWallet() {
if (msg.sender != address(this))
throw;
require(msg.sender == address(this));
_;
}
modifier ownerDoesNotExist(address owner) {
if (isOwner[owner])
throw;
require(!isOwner[owner]);
_;
}
modifier ownerExists(address owner) {
if (!isOwner[owner])
throw;
require(isOwner[owner]);
_;
}
modifier transactionExists(uint transactionId) {
if (transactions[transactionId].destination == 0)
throw;
require(transactions[transactionId].destination != 0);
_;
}
modifier confirmed(uint transactionId, address owner) {
if (!confirmations[transactionId][owner])
throw;
require(confirmations[transactionId][owner]);
_;
}
modifier notConfirmed(uint transactionId, address owner) {
if (confirmations[transactionId][owner])
throw;
require(!confirmations[transactionId][owner]);
_;
}
modifier notExecuted(uint transactionId) {
if (transactions[transactionId].executed)
throw;
require(!transactions[transactionId].executed);
_;
}
modifier notNull(address _address) {
if (_address == 0)
throw;
require(_address != 0);
_;
}
modifier validRequirement(uint ownerCount, uint _required) {
if ( ownerCount > MAX_OWNER_COUNT
|| _required > ownerCount
|| _required == 0
|| ownerCount == 0)
throw;
require(ownerCount <= MAX_OWNER_COUNT
&& _required <= ownerCount
&& _required != 0
&& ownerCount != 0);
_;
}
@@ -108,8 +111,7 @@ contract MultiSigWallet {
validRequirement(_owners.length, _required)
{
for (uint i=0; i<_owners.length; i++) {
if (isOwner[_owners[i]] || _owners[i] == 0)
throw;
require(!isOwner[_owners[i]] && _owners[i] != 0);
isOwner[_owners[i]] = true;
}
owners = _owners;
@@ -151,7 +153,7 @@ contract MultiSigWallet {
/// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet.
/// @param owner Address of owner to be replaced.
/// @param owner Address of new owner.
/// @param newOwner Address of new owner.
function replaceOwner(address owner, address newOwner)
public
onlyWallet
@@ -222,20 +224,44 @@ contract MultiSigWallet {
/// @param transactionId Transaction ID.
function executeTransaction(uint transactionId)
public
ownerExists(msg.sender)
confirmed(transactionId, msg.sender)
notExecuted(transactionId)
{
if (isConfirmed(transactionId)) {
Transaction tx = transactions[transactionId];
tx.executed = true;
if (tx.destination.call.value(tx.value)(tx.data))
Transaction storage txn = transactions[transactionId];
txn.executed = true;
if (external_call(txn.destination, txn.value, txn.data.length, txn.data))
Execution(transactionId);
else {
ExecutionFailure(transactionId);
tx.executed = false;
txn.executed = false;
}
}
}
// call has been separated into its own function in order to take advantage
// of the Solidity's code generator to produce a loop that copies tx.data into memory.
function external_call(address destination, uint value, uint dataLength, bytes data) internal returns (bool) {
bool result;
assembly {
let x := mload(0x40) // "Allocate" memory for output (0x40 is where "free memory" pointer is stored by convention)
let d := add(data, 32) // First 32 bytes are the padded length of data, so exclude that
result := call(
sub(gas, 34710), // 34710 is the value that solidity is currently emitting
// It includes callGas (700) + callVeryLow (3, to pay for SUB) + callValueTransferGas (9000) +
// callNewAccountGas (25000, in case the destination address does not exist and needs creating)
destination,
value,
d,
dataLength, // Size of the input (in bytes) - this is what fixes the padding problem
x,
0 // Output is ignored, therefore the output size is zero
)
}
return result;
}
/// @dev Returns the confirmation status of a transaction.
/// @param transactionId Transaction ID.
/// @return Confirmation status.
@@ -364,4 +390,4 @@ contract MultiSigWallet {
for (i=from; i<to; i++)
_transactionIds[i - from] = transactionIdsTemp[i];
}
}
}

View File

@@ -16,47 +16,57 @@
*/
// solhint-disable
pragma solidity ^0.4.10;
pragma solidity 0.4.24;
import "./MultiSigWallet.sol";
/// @title Multisignature wallet with time lock- Allows multiple parties to execute a transaction after a time lock has passed.
/// @author Amir Bandeali - <amir@0xProject.com>
contract MultiSigWalletWithTimeLock is MultiSigWallet {
// solhint-disable not-rely-on-time
contract MultiSigWalletWithTimeLock is
MultiSigWallet
{
event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime);
event TimeLockChange(uint256 secondsTimeLocked);
event ConfirmationTimeSet(uint indexed transactionId, uint confirmationTime);
event TimeLockChange(uint secondsTimeLocked);
uint256 public secondsTimeLocked;
uint public secondsTimeLocked;
mapping (uint256 => uint256) public confirmationTimes;
mapping (uint => uint) public confirmationTimes;
modifier notFullyConfirmed(uint transactionId) {
require(!isConfirmed(transactionId));
modifier notFullyConfirmed(uint256 transactionId) {
require(
!isConfirmed(transactionId),
"TX_FULLY_CONFIRMED"
);
_;
}
modifier fullyConfirmed(uint transactionId) {
require(isConfirmed(transactionId));
modifier fullyConfirmed(uint256 transactionId) {
require(
isConfirmed(transactionId),
"TX_NOT_FULLY_CONFIRMED"
);
_;
}
modifier pastTimeLock(uint transactionId) {
require(block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked);
modifier pastTimeLock(uint256 transactionId) {
require(
block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked,
"TIME_LOCK_INCOMPLETE"
);
_;
}
/*
* Public functions
*/
/// @dev Contract constructor sets initial owners, required number of confirmations, and time lock.
/// @param _owners List of initial owners.
/// @param _required Number of required confirmations.
/// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.
function MultiSigWalletWithTimeLock(address[] _owners, uint _required, uint _secondsTimeLocked)
constructor (
address[] _owners,
uint256 _required,
uint256 _secondsTimeLocked
)
public
MultiSigWallet(_owners, _required)
{
@@ -65,17 +75,17 @@ contract MultiSigWalletWithTimeLock is MultiSigWallet {
/// @dev Changes the duration of the time lock for transactions.
/// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.
function changeTimeLock(uint _secondsTimeLocked)
function changeTimeLock(uint256 _secondsTimeLocked)
public
onlyWallet
{
secondsTimeLocked = _secondsTimeLocked;
TimeLockChange(_secondsTimeLocked);
emit TimeLockChange(_secondsTimeLocked);
}
/// @dev Allows an owner to confirm a transaction.
/// @param transactionId Transaction ID.
function confirmTransaction(uint transactionId)
function confirmTransaction(uint256 transactionId)
public
ownerExists(msg.sender)
transactionExists(transactionId)
@@ -83,52 +93,35 @@ contract MultiSigWalletWithTimeLock is MultiSigWallet {
notFullyConfirmed(transactionId)
{
confirmations[transactionId][msg.sender] = true;
Confirmation(msg.sender, transactionId);
emit Confirmation(msg.sender, transactionId);
if (isConfirmed(transactionId)) {
setConfirmationTime(transactionId, block.timestamp);
}
}
/// @dev Allows an owner to revoke a confirmation for a transaction.
/// @param transactionId Transaction ID.
function revokeConfirmation(uint transactionId)
public
ownerExists(msg.sender)
confirmed(transactionId, msg.sender)
notExecuted(transactionId)
notFullyConfirmed(transactionId)
{
confirmations[transactionId][msg.sender] = false;
Revocation(msg.sender, transactionId);
}
/// @dev Allows anyone to execute a confirmed transaction.
/// @param transactionId Transaction ID.
function executeTransaction(uint transactionId)
function executeTransaction(uint256 transactionId)
public
notExecuted(transactionId)
fullyConfirmed(transactionId)
pastTimeLock(transactionId)
{
Transaction storage tx = transactions[transactionId];
tx.executed = true;
if (tx.destination.call.value(tx.value)(tx.data))
Execution(transactionId);
else {
ExecutionFailure(transactionId);
tx.executed = false;
Transaction storage txn = transactions[transactionId];
txn.executed = true;
if (external_call(txn.destination, txn.value, txn.data.length, txn.data)) {
emit Execution(transactionId);
} else {
emit ExecutionFailure(transactionId);
txn.executed = false;
}
}
/*
* Internal functions
*/
/// @dev Sets the time of when a submission first passed.
function setConfirmationTime(uint transactionId, uint confirmationTime)
function setConfirmationTime(uint256 transactionId, uint256 confirmationTime)
internal
{
confirmationTimes[transactionId] = confirmationTime;
ConfirmationTimeSet(transactionId, confirmationTime);
emit ConfirmationTimeSet(transactionId, confirmationTime);
}
}

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