diff options
author | Hsuan Lee <hsuan@cobinhood.com> | 2019-01-19 18:42:04 +0800 |
---|---|---|
committer | Hsuan Lee <hsuan@cobinhood.com> | 2019-01-19 18:42:04 +0800 |
commit | 7ae38906926dc09bc10670c361af0d2bf0050426 (patch) | |
tree | 5fb10ae366b987db09e4ddb4bc3ba0f75404ad08 /packages/contract-wrappers | |
parent | b5fd3c72a08aaa6957917d74c333387a16edf66b (diff) | |
download | dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.gz dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.bz2 dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.lz dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.xz dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.zst dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.zip |
Update dependency packages
Diffstat (limited to 'packages/contract-wrappers')
59 files changed, 0 insertions, 8882 deletions
diff --git a/packages/contract-wrappers/.npmignore b/packages/contract-wrappers/.npmignore deleted file mode 100644 index 6a222fd45..000000000 --- a/packages/contract-wrappers/.npmignore +++ /dev/null @@ -1,11 +0,0 @@ -.* -tsconfig.json -webpack.config.js -yarn-error.log -test/ -/src/ -/_bundles/ -/abi-gen-templates/ -/generated_docs/ -/scripts/ -/lib/src/monorepo_scripts/ diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json deleted file mode 100644 index 30199ae1d..000000000 --- a/packages/contract-wrappers/CHANGELOG.json +++ /dev/null @@ -1,414 +0,0 @@ -[ - { - "version": "6.0.0", - "changes": [ - { - "note": "Upgrade the bignumber.js to v8.0.2", - "pr": 1517 - } - ] - }, - { - "timestamp": 1547747677, - "version": "5.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "5.0.0", - "changes": [ - { - "note": "Renamed OrderStatus enum members to PascalCase to conform with tslint enum-naming rule", - "pr": 1474 - }, - { - "note": "Remove Exchange `matchOrdersAsync` optimization", - "pr": 1514 - } - ], - "timestamp": 1547561734 - }, - { - "timestamp": 1547225310, - "version": "4.2.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "4.2.0", - "changes": [ - { - "note": "Added Dutch Auction wrapper", - "pr": 1465 - } - ], - "timestamp": 1547040760 - }, - { - "version": "4.1.4", - "changes": [ - { - "note": "Add support for Trust Wallet signature denial error" - }, - { - "note": "Add balance and allowance queries for `MultiAssetProxy`", - "pr": 1363 - } - ] - }, - { - "version": "4.1.3", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1544739608 - }, - { - "version": "4.1.2", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1544570656 - }, - { - "timestamp": 1543401373, - "version": "4.1.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "4.1.0", - "changes": [ - { - "note": "Add a `nonce` field for `TxOpts` so that it's now possible to re-broadcast stuck transactions with a higher gas amount", - "pr": 1292 - } - ], - "timestamp": 1542821676 - }, - { - "timestamp": 1542208198, - "version": "4.0.2", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1542134075, - "version": "4.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "4.0.0", - "changes": [ - { - "note": "Add signature validation, regular cancellation and `cancelledUpTo` checks to `validateOrderFillableOrThrowAsync`", - "pr": 1235 - }, - { - "note": "Improved the errors thrown by `validateOrderFillableOrThrowAsync` by making them more descriptive", - "pr": 1235 - }, - { - "note": "Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218)", - "pr": 1235 - } - ], - "timestamp": 1542028948 - }, - { - "version": "3.0.1", - "changes": [ - { - "note": "Fix bug in `ForwarderWrapper` where `feeRecipientAddress` was not correctly normalized.", - "pr": 1178 - } - ], - "timestamp": 1541740904 - }, - { - "version": "3.0.0", - "changes": [ - { - "note": "Add optional validation to the forwarder wrapper methods" - }, - { - "note": "Updated to use new modularized artifacts.", - "pr": 1105 - }, - { - "note": "Top-level `ContractWrappers` class has a new optional `contractAddresses` parameter.", - "pr": 1105 - }, - { - "note": "Default contract addresses are no longer stored in artifacts and are instead loaded from the `@0xproject/contract-addresses` package.", - "pr": 1105 - }, - { - "note": "Most contract addresses are now defined at instantiation time and are available as properties (e.g., `exchangeWrapper.address`) instead of methods (e.g., `exchangeWrapper.getContractAddress()`).", - "pr": 1105 - }, - { - "note": "Removed `setProvider` method in top-level `ContractWrapper` class and added new `unsubscribeAll` method.", - "pr": 1105 - }, - { - "note": "Some properties and methods have been renamed. For example, some methods that previously could throw no longer can, and so their names have been updated accordingly.", - "pr": 1105 - }, - { - "note": "Removed ContractNotFound errors. Checking for this error was somewhat ineffecient. Relevant methods/functions now return the default error from web3-wrapper, which we feel provides enough information.", - "pr": 1105 - }, - { - "note": "Add `ForwarderWrapperError` to public interface", - "pr": 1147 - }, - { - "note": "Add `ContractWrapperError.SignatureRequestDenied` to public interface", - "pr": 1147 - } - ], - "timestamp": 1539871071 - }, - { - "version": "2.0.2", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1538693146 - }, - { - "timestamp": 1538157789, - "version": "2.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "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": [ - { - "note": "Fix missing `BlockParamLiteral` type import issue" - } - ], - "timestamp": 1535377027 - }, - { - "version": "1.0.1-rc.4", - "changes": [ - { - "note": "Export missing types: `TransactionEncoder`, `ContractAbi`, `JSONRPCRequestPayload`, `JSONRPCResponsePayload`, `JSONRPCErrorCallback`, `AbiDefinition`, `FunctionAbi`, `EventAbi`, `EventParameter`, `DecodedLogArgs`, `MethodAbi`, `ConstructorAbi`, `FallbackAbi`, `DataItem`, `ConstructorStateMutability`, `StateMutability` & `ExchangeSignatureValidatorApprovalEventArgs`", - "pr": 924 - }, - { - "note": "Remove superfluous exported types: `ContractEvent`, `Token`, `OrderFillRequest`, `ContractEventArgs`, `LogEvent`, `OnOrderStateChangeCallback`, `ECSignature`, `OrderStateValid`, `OrderStateInvalid`, `OrderState`, `FilterObject`, `TransactionReceipt` & `TransactionReceiptWithDecodedLogs`", - "pr": 924 - }, - { - "note": "Added Transaction Encoder for use with 0x Exchange executeTransaction", - "pr": 975 - } - ], - "timestamp": 1535133899 - }, - { - "version": "1.0.1-rc.3", - "changes": [ - { - "pr": 915, - "note": "Added strict encoding/decoding checks for sendTransaction and call" - }, - { - "note": "Add ForwarderWrapper", - "pr": 934 - }, - { - "note": "Optimize orders in ForwarderWrapper", - "pr": 936 - } - ], - "timestamp": 1534210131 - }, - { - "version": "1.0.1-rc.2", - "changes": [ - { - "note": "Fixed bug caused by importing non-existent dep" - } - ], - "timestamp": 1532619515 - }, - { - "version": "1.0.1-rc.1", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1532605697 - }, - { - "timestamp": 1532357734, - "version": "1.0.0", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1532043000, - "version": "1.0.0-rc.1", - "changes": [ - { - "note": "Update blockstream to v5.0 and propogate up caught errors to active subscriptions", - "pr": 815 - }, - { - "note": "Update to v2 of 0x rpotocol", - "pr": 822 - } - ] - }, - { - "timestamp": 1531919263, - "version": "0.1.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1529397769, - "version": "0.0.5", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1527617227, - "version": "0.0.4", - "changes": [ - { - "note": "Expose 'abi' ContractAbi property on all contract wrappers" - } - ] - }, - { - "version": "0.0.2", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1527008544 - }, - { - "timestamp": 1527008270, - "version": "0.0.1", - "changes": [ - { - "note": "Moved contractWrappers out of 0x.js", - "pr": 579 - } - ] - } -] diff --git a/packages/contract-wrappers/CHANGELOG.md b/packages/contract-wrappers/CHANGELOG.md deleted file mode 100644 index 28cbf2ec6..000000000 --- a/packages/contract-wrappers/CHANGELOG.md +++ /dev/null @@ -1,164 +0,0 @@ -<!-- -changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly. -Edit the package's CHANGELOG.json file only. ---> - -CHANGELOG - -## v5.0.1 - _January 17, 2019_ - - * Dependencies updated - -## v5.0.0 - _January 15, 2019_ - - * Renamed OrderStatus enum members to PascalCase to conform with tslint enum-naming rule (#1474) - * Remove Exchange `matchOrdersAsync` optimization (#1514) - -## v4.2.1 - _January 11, 2019_ - - * Dependencies updated - -## v4.2.0 - _January 9, 2019_ - - * Added Dutch Auction wrapper (#1465) - -## v4.1.4 - _Invalid date_ - - * Add support for Trust Wallet signature denial error - * Add balance and allowance queries for `MultiAssetProxy` (#1363) - -## v4.1.3 - _December 13, 2018_ - - * Dependencies updated - -## v4.1.2 - _December 11, 2018_ - - * Dependencies updated - -## v4.1.1 - _November 28, 2018_ - - * Dependencies updated - -## v4.1.0 - _November 21, 2018_ - - * Add a `nonce` field for `TxOpts` so that it's now possible to re-broadcast stuck transactions with a higher gas amount (#1292) - -## v4.0.2 - _November 14, 2018_ - - * Dependencies updated - -## v4.0.1 - _November 13, 2018_ - - * Dependencies updated - -## v4.0.0 - _November 12, 2018_ - - * Add signature validation, regular cancellation and `cancelledUpTo` checks to `validateOrderFillableOrThrowAsync` (#1235) - * Improved the errors thrown by `validateOrderFillableOrThrowAsync` by making them more descriptive (#1235) - * Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218) (#1235) - -## v3.0.1 - _November 9, 2018_ - - * Fix bug in `ForwarderWrapper` where `feeRecipientAddress` was not correctly normalized. (#1178) - -## v3.0.0 - _October 18, 2018_ - - * Add optional validation to the forwarder wrapper methods - * Updated to use new modularized artifacts. (#1105) - * Top-level `ContractWrappers` class has a new optional `contractAddresses` parameter. (#1105) - * Default contract addresses are no longer stored in artifacts and are instead loaded from the `@0xproject/contract-addresses` package. (#1105) - * Most contract addresses are now defined at instantiation time and are available as properties (e.g., `exchangeWrapper.address`) instead of methods (e.g., `exchangeWrapper.getContractAddress()`). (#1105) - * Removed `setProvider` method in top-level `ContractWrapper` class and added new `unsubscribeAll` method. (#1105) - * Some properties and methods have been renamed. For example, some methods that previously could throw no longer can, and so their names have been updated accordingly. (#1105) - * Removed ContractNotFound errors. Checking for this error was somewhat ineffecient. Relevant methods/functions now return the default error from web3-wrapper, which we feel provides enough information. (#1105) - * Add `ForwarderWrapperError` to public interface (#1147) - * Add `ContractWrapperError.SignatureRequestDenied` to public interface (#1147) - -## v2.0.2 - _October 4, 2018_ - - * Dependencies updated - -## v2.0.1 - _September 28, 2018_ - - * Dependencies updated - -## 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 - -## v1.0.1-rc.4 - _August 24, 2018_ - - * Export missing types: `TransactionEncoder`, `ContractAbi`, `JSONRPCRequestPayload`, `JSONRPCResponsePayload`, `JSONRPCErrorCallback`, `AbiDefinition`, `FunctionAbi`, `EventAbi`, `EventParameter`, `DecodedLogArgs`, `MethodAbi`, `ConstructorAbi`, `FallbackAbi`, `DataItem`, `ConstructorStateMutability`, `StateMutability` & `ExchangeSignatureValidatorApprovalEventArgs` (#924) - * Remove superfluous exported types: `ContractEvent`, `Token`, `OrderFillRequest`, `ContractEventArgs`, `LogEvent`, `OnOrderStateChangeCallback`, `ECSignature`, `OrderStateValid`, `OrderStateInvalid`, `OrderState`, `FilterObject`, `TransactionReceipt` & `TransactionReceiptWithDecodedLogs` (#924) - * Added Transaction Encoder for use with 0x Exchange executeTransaction (#975) - -## v1.0.1-rc.3 - _August 14, 2018_ - - * Added strict encoding/decoding checks for sendTransaction and call (#915) - * Add ForwarderWrapper (#934) - * Optimize orders in ForwarderWrapper (#936) - -## v1.0.1-rc.2 - _July 26, 2018_ - - * Fixed bug caused by importing non-existent dep - -## v1.0.1-rc.1 - _July 26, 2018_ - - * Dependencies updated - -## v1.0.0 - _July 23, 2018_ - - * Dependencies updated - -## v1.0.0-rc.1 - _July 19, 2018_ - - * Update blockstream to v5.0 and propogate up caught errors to active subscriptions (#815) - * Update to v2 of 0x rpotocol (#822) - -## v0.1.1 - _July 18, 2018_ - - * Dependencies updated - -## v0.0.5 - _June 19, 2018_ - - * Dependencies updated - -## v0.0.4 - _May 29, 2018_ - - * Expose 'abi' ContractAbi property on all contract wrappers - -## v0.0.2 - _May 22, 2018_ - - * Dependencies updated - -## v0.0.1 - _May 22, 2018_ - - * Moved contractWrappers out of 0x.js (#579) diff --git a/packages/contract-wrappers/README.md b/packages/contract-wrappers/README.md deleted file mode 100644 index 36f2f48fb..000000000 --- a/packages/contract-wrappers/README.md +++ /dev/null @@ -1,89 +0,0 @@ -## @0x/contract-wrappers - -Smart TS wrappers for 0x smart contracts. The wrappers have simplified interfaces, perform client-side validation on transactions and throw helpful error messages. - -### Read the [Documentation](https://0xproject.com/docs/0x.js). - -## Installation - -**Install** - -```bash -npm install @0x/contract-wrappers --save -``` - -**Import** - -```javascript -import { ContractWrappers } from '@0x/contract-wrappers'; -``` - -If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: - -```json -"compilerOptions": { - "typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"], -} -``` - -## Contributing - -We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. - -Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. - -### Install dependencies - -If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: - -```bash -yarn config set workspaces-experimental true -``` - -Then install dependencies - -```bash -yarn install -``` - -### Build - -To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory: - -```bash -PKG=@0x/contract-wrappers yarn build -``` - -Or continuously rebuild on change: - -```bash -PKG=@0x/contract-wrappers yarn watch -``` - -```bash -yarn build -``` - -or continuously rebuild on change: - -```bash -yarn watch -``` - -### Clean - -```bash -yarn clean -``` - -### Lint - -```bash -yarn lint -``` - -### Run Tests - -```bash -yarn test -``` diff --git a/packages/contract-wrappers/coverage/.gitkeep b/packages/contract-wrappers/coverage/.gitkeep deleted file mode 100644 index e69de29bb..000000000 --- a/packages/contract-wrappers/coverage/.gitkeep +++ /dev/null diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json deleted file mode 100644 index cc7dc1a3e..000000000 --- a/packages/contract-wrappers/package.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "name": "@0x/contract-wrappers", - "version": "5.0.1", - "description": "Smart TS wrappers for 0x smart contracts", - "keywords": [ - "0xproject", - "ethereum", - "tokens", - "exchange" - ], - "main": "lib/src/index.js", - "types": "lib/src/index.d.ts", - "scripts": { - "build": "tsc -b", - "build:ci": "yarn build", - "lint": "tslint --format stylish --project . --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", - "clean": "shx rm -rf _bundles lib test_temp 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 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" - }, - "config": { - "postpublish": { - "assets": [] - } - }, - "repository": { - "type": "git", - "url": "https://github.com/0xProject/0x-monorepo" - }, - "license": "Apache-2.0", - "engines": { - "node": ">=6.0.0" - }, - "devDependencies": { - "@0x/dev-utils": "^1.0.24", - "@0x/migrations": "^2.4.0", - "@0x/subproviders": "^2.1.11", - "@0x/tslint-config": "^2.0.2", - "@types/lodash": "4.14.104", - "@types/mocha": "^2.2.42", - "@types/node": "*", - "@types/sinon": "^2.2.2", - "@types/uuid": "^3.4.2", - "@types/web3-provider-engine": "^14.0.0", - "chai": "^4.0.1", - "chai-as-promised": "^7.1.0", - "chai-bignumber": "^3.0.0", - "dirty-chai": "^2.0.1", - "make-promises-safe": "^1.1.0", - "mocha": "^4.1.0", - "npm-run-all": "^4.1.2", - "nyc": "^11.0.1", - "opn-cli": "^3.1.0", - "shx": "^0.2.2", - "sinon": "^4.0.0", - "source-map-support": "^0.5.0", - "tslint": "5.11.0", - "typedoc": "0.13.0", - "typescript": "3.0.1", - "web3-provider-engine": "14.0.6" - }, - "dependencies": { - "@0x/abi-gen-wrappers": "^2.2.0", - "@0x/assert": "^1.0.23", - "@0x/contract-addresses": "^2.2.0", - "@0x/contract-artifacts": "^1.3.0", - "@0x/contracts-test-utils": "^2.0.1", - "@0x/fill-scenarios": "^1.1.2", - "@0x/json-schemas": "^2.1.7", - "@0x/order-utils": "^3.1.2", - "@0x/types": "^1.5.2", - "@0x/typescript-typings": "^3.0.8", - "@0x/utils": "^3.0.1", - "@0x/web3-wrapper": "^3.2.4", - "ethereum-types": "^1.1.6", - "ethereumjs-abi": "0.6.5", - "ethereumjs-blockstream": "6.0.0", - "ethereumjs-util": "^5.1.1", - "ethers": "~4.0.4", - "js-sha3": "^0.7.0", - "lodash": "^4.17.5", - "uuid": "^3.1.0" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/contract-wrappers/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts b/packages/contract-wrappers/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts deleted file mode 100644 index b095c8e79..000000000 --- a/packages/contract-wrappers/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -export abstract class AbstractBalanceAndProxyAllowanceLazyStore { - public abstract async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; - public abstract async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; - public abstract setBalance(tokenAddress: string, userAddress: string, balance: BigNumber): void; - public abstract deleteBalance(tokenAddress: string, userAddress: string): void; - public abstract setProxyAllowance(tokenAddress: string, userAddress: string, proxyAllowance: BigNumber): void; - public abstract deleteProxyAllowance(tokenAddress: string, userAddress: string): void; - public abstract deleteAll(): void; -} diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts deleted file mode 100644 index 4e594593e..000000000 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { - ERC20Proxy, - ERC20Token, - ERC721Proxy, - ERC721Token, - Exchange, - Forwarder, - OrderValidator, - WETH9, -} from '@0x/contract-artifacts'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { DutchAuctionWrapper } from './contract_wrappers/dutch_auction_wrapper'; -import { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper'; -import { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper'; -import { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper'; -import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper'; -import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; -import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; -import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper'; -import { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper'; -import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema'; -import { ContractWrappersConfig } from './types'; -import { assert } from './utils/assert'; -import { constants } from './utils/constants'; -import { _getDefaultContractAddresses } from './utils/contract_addresses'; - -/** - * The ContractWrappers class contains smart contract wrappers helpful when building on 0x protocol. - */ -export class ContractWrappers { - /** - * An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract. - */ - public exchange: ExchangeWrapper; - /** - * An instance of the ERC20TokenWrapper class containing methods for interacting with any ERC20 token smart contract. - */ - public erc20Token: ERC20TokenWrapper; - /** - * An instance of the ERC721TokenWrapper class containing methods for interacting with any ERC721 token smart contract. - */ - public erc721Token: ERC721TokenWrapper; - /** - * An instance of the EtherTokenWrapper class containing methods for interacting with the - * wrapped ETH ERC20 token smart contract. - */ - public etherToken: EtherTokenWrapper; - /** - * An instance of the ERC20ProxyWrapper class containing methods for interacting with the - * erc20Proxy smart contract. - */ - public erc20Proxy: ERC20ProxyWrapper; - /** - * An instance of the ERC721ProxyWrapper class containing methods for interacting with the - * erc721Proxy smart contract. - */ - public erc721Proxy: ERC721ProxyWrapper; - /** - * 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; - /** - * An instance of the DutchAuctionWrapper class containing methods for interacting with any DutchAuction smart contract. - */ - public dutchAuction: DutchAuctionWrapper; - - private readonly _web3Wrapper: Web3Wrapper; - /** - * Instantiates a new ContractWrappers instance. - * @param provider The Provider instance you would like the contract-wrappers library to use for interacting with - * the Ethereum network. - * @param config The configuration object. Look up the type for the description. - * @return An instance of the ContractWrappers class. - */ - constructor(provider: Provider, config: ContractWrappersConfig) { - assert.isWeb3Provider('provider', provider); - assert.doesConformToSchema('config', config, ContractWrappersConfigSchema); - const txDefaults = { - gasPrice: config.gasPrice, - }; - this._web3Wrapper = new Web3Wrapper(provider, txDefaults); - const artifactsArray = [ - ERC20Proxy, - ERC20Token, - ERC721Proxy, - ERC721Token, - Exchange, - Forwarder, - OrderValidator, - WETH9, - ]; - _.forEach(artifactsArray, artifact => { - this._web3Wrapper.abiDecoder.addABI(artifact.compilerOutput.abi); - }); - const blockPollingIntervalMs = _.isUndefined(config.blockPollingIntervalMs) - ? constants.DEFAULT_BLOCK_POLLING_INTERVAL - : config.blockPollingIntervalMs; - const contractAddresses = _.isUndefined(config.contractAddresses) - ? _getDefaultContractAddresses(config.networkId) - : config.contractAddresses; - this.erc20Proxy = new ERC20ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc20Proxy); - this.erc721Proxy = new ERC721ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc721Proxy); - this.erc20Token = new ERC20TokenWrapper( - this._web3Wrapper, - config.networkId, - this.erc20Proxy, - blockPollingIntervalMs, - ); - this.erc721Token = new ERC721TokenWrapper( - this._web3Wrapper, - config.networkId, - this.erc721Proxy, - blockPollingIntervalMs, - ); - this.etherToken = new EtherTokenWrapper( - this._web3Wrapper, - config.networkId, - this.erc20Token, - blockPollingIntervalMs, - ); - this.exchange = new ExchangeWrapper( - this._web3Wrapper, - config.networkId, - this.erc20Token, - this.erc721Token, - contractAddresses.exchange, - contractAddresses.zrxToken, - blockPollingIntervalMs, - ); - this.forwarder = new ForwarderWrapper( - this._web3Wrapper, - config.networkId, - contractAddresses.forwarder, - contractAddresses.zrxToken, - contractAddresses.etherToken, - ); - this.orderValidator = new OrderValidatorWrapper( - this._web3Wrapper, - config.networkId, - contractAddresses.orderValidator, - ); - this.dutchAuction = new DutchAuctionWrapper( - this._web3Wrapper, - config.networkId, - contractAddresses.dutchAuction, - ); - } - /** - * Unsubscribes from all subscriptions for all contracts. - */ - public unsubscribeAll(): void { - this.exchange.unsubscribeAll(); - this.erc20Token.unsubscribeAll(); - this.erc721Token.unsubscribeAll(); - this.etherToken.unsubscribeAll(); - } - /** - * Get the provider instance currently used by contract-wrappers - * @return Web3 provider instance - */ - public getProvider(): Provider { - return this._web3Wrapper.getProvider(); - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts deleted file mode 100644 index 749aaae10..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { AbiDecoder, intervalUtils, logUtils } from '@0x/utils'; -import { marshaller, Web3Wrapper } from '@0x/web3-wrapper'; -import { - BlockParamLiteral, - ContractAbi, - FilterObject, - LogEntry, - LogWithDecodedArgs, - RawLog, - RawLogEntry, -} from 'ethereum-types'; -import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream'; -import * as _ from 'lodash'; - -import { - BlockRange, - ContractEventArgs, - ContractEvents, - ContractWrappersError, - EventCallback, - IndexedFilterValues, -} from '../types'; -import { constants } from '../utils/constants'; -import { filterUtils } from '../utils/filter_utils'; - -export abstract class ContractWrapper { - public abstract abi: ContractAbi; - protected _networkId: number; - protected _web3Wrapper: Web3Wrapper; - private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined; - private readonly _blockPollingIntervalMs: number; - private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer; - private readonly _filters: { [filterToken: string]: FilterObject }; - private readonly _filterCallbacks: { - [filterToken: string]: EventCallback<ContractEventArgs>; - }; - private _onLogAddedSubscriptionToken: string | undefined; - private _onLogRemovedSubscriptionToken: string | undefined; - private static _onBlockAndLogStreamerError(isVerbose: boolean, err: Error): void { - // Since Blockstream errors are all recoverable, we simply log them if the verbose - // config is passed in. - if (isVerbose) { - logUtils.warn(err); - } - } - constructor(web3Wrapper: Web3Wrapper, networkId: number, blockPollingIntervalMs?: number) { - this._web3Wrapper = web3Wrapper; - this._networkId = networkId; - this._blockPollingIntervalMs = _.isUndefined(blockPollingIntervalMs) - ? constants.DEFAULT_BLOCK_POLLING_INTERVAL - : blockPollingIntervalMs; - this._filters = {}; - this._filterCallbacks = {}; - this._blockAndLogStreamerIfExists = undefined; - this._onLogAddedSubscriptionToken = undefined; - this._onLogRemovedSubscriptionToken = undefined; - } - protected _unsubscribeAll(): void { - const filterTokens = _.keys(this._filterCallbacks); - _.each(filterTokens, filterToken => { - this._unsubscribe(filterToken); - }); - } - protected _unsubscribe(filterToken: string, err?: Error): void { - if (_.isUndefined(this._filters[filterToken])) { - throw new Error(ContractWrappersError.SubscriptionNotFound); - } - if (!_.isUndefined(err)) { - const callback = this._filterCallbacks[filterToken]; - callback(err, undefined); - } - delete this._filters[filterToken]; - delete this._filterCallbacks[filterToken]; - if (_.isEmpty(this._filters)) { - this._stopBlockAndLogStream(); - } - } - protected _subscribe<ArgsType extends ContractEventArgs>( - address: string, - eventName: ContractEvents, - indexFilterValues: IndexedFilterValues, - abi: ContractAbi, - callback: EventCallback<ArgsType>, - isVerbose: boolean = false, - ): string { - const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi); - if (_.isUndefined(this._blockAndLogStreamerIfExists)) { - this._startBlockAndLogStream(isVerbose); - } - const filterToken = filterUtils.generateUUID(); - this._filters[filterToken] = filter; - this._filterCallbacks[filterToken] = callback as EventCallback<ContractEventArgs>; - return filterToken; - } - protected async _getLogsAsync<ArgsType extends ContractEventArgs>( - address: string, - eventName: ContractEvents, - blockRange: BlockRange, - indexFilterValues: IndexedFilterValues, - abi: ContractAbi, - ): Promise<Array<LogWithDecodedArgs<ArgsType>>> { - const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange); - const logs = await this._web3Wrapper.getLogsAsync(filter); - const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this)); - return logsWithDecodedArguments; - } - protected _tryToDecodeLogOrNoop<ArgsType extends ContractEventArgs>( - log: LogEntry, - ): LogWithDecodedArgs<ArgsType> | RawLog { - const abiDecoder = new AbiDecoder([this.abi]); - const logWithDecodedArgs = abiDecoder.tryToDecodeLogOrNoop(log); - return logWithDecodedArgs; - } - 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>; - const logEvent = { - log: decodedLog, - isRemoved, - }; - this._filterCallbacks[filterToken](null, logEvent); - } - }); - } - private _startBlockAndLogStream(isVerbose: boolean): void { - if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { - throw new Error(ContractWrappersError.SubscriptionAlreadyPresent); - } - this._blockAndLogStreamerIfExists = new BlockAndLogStreamer( - this._blockstreamGetBlockOrNullAsync.bind(this), - this._blockstreamGetLogsAsync.bind(this), - ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose), - ); - const catchAllLogFilter = {}; - this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter); - this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval( - this._reconcileBlockAsync.bind(this), - this._blockPollingIntervalMs, - ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose), - ); - let isRemoved = false; - this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded( - this._onLogStateChanged.bind(this, isRemoved), - ); - isRemoved = true; - this._onLogRemovedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogRemoved( - 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[]; - } - private _stopBlockAndLogStream(): void { - if (_.isUndefined(this._blockAndLogStreamerIfExists)) { - throw new Error(ContractWrappersError.SubscriptionNotFound); - } - this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string); - this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string); - intervalUtils.clearAsyncExcludingInterval(this._blockAndLogStreamIntervalIfExists as NodeJS.Timer); - delete this._blockAndLogStreamerIfExists; - } - private async _reconcileBlockAsync(): Promise<void> { - 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(latestBlockOrNull); - } - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/dutch_auction_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/dutch_auction_wrapper.ts deleted file mode 100644 index c1aceff47..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/dutch_auction_wrapper.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { DutchAuctionContract } from '@0x/abi-gen-wrappers'; -import { DutchAuction } from '@0x/contract-artifacts'; -import { schemas } from '@0x/json-schemas'; -import { assetDataUtils } from '@0x/order-utils'; -import { DutchAuctionDetails, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { ContractAbi } from 'ethereum-types'; -import * as ethAbi from 'ethereumjs-abi'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema'; -import { txOptsSchema } from '../schemas/tx_opts_schema'; -import { DutchAuctionData, DutchAuctionWrapperError, OrderTransactionOpts } from '../types'; -import { assert } from '../utils/assert'; -import { _getDefaultContractAddresses } from '../utils/contract_addresses'; - -import { ContractWrapper } from './contract_wrapper'; - -export class DutchAuctionWrapper extends ContractWrapper { - public abi: ContractAbi = DutchAuction.compilerOutput.abi; - public address: string; - private _dutchAuctionContractIfExists?: DutchAuctionContract; - /** - * Dutch auction details are encoded with the asset data for a 0x order. This function produces a hex - * encoded assetData string, containing information both about the asset being traded and the - * dutch auction; which is usable in the makerAssetData or takerAssetData fields in a 0x order. - * @param assetData Hex encoded assetData string for the asset being auctioned. - * @param beginTimeSeconds Begin time of the dutch auction. - * @param beginAmount Starting amount being sold in the dutch auction. - * @return The hex encoded assetData string. - */ - public static encodeDutchAuctionAssetData( - assetData: string, - beginTimeSeconds: BigNumber, - beginAmount: BigNumber, - ): string { - const assetDataBuffer = ethUtil.toBuffer(assetData); - const abiEncodedAuctionData = (ethAbi as any).rawEncode( - ['uint256', 'uint256'], - [beginTimeSeconds.toString(), beginAmount.toString()], - ); - const abiEncodedAuctionDataBuffer = ethUtil.toBuffer(abiEncodedAuctionData); - const dutchAuctionDataBuffer = Buffer.concat([assetDataBuffer, abiEncodedAuctionDataBuffer]); - const dutchAuctionData = ethUtil.bufferToHex(dutchAuctionDataBuffer); - return dutchAuctionData; - } - /** - * Dutch auction details are encoded with the asset data for a 0x order. This function decodes a hex - * encoded assetData string, containing information both about the asset being traded and the - * dutch auction. - * @param dutchAuctionData Hex encoded assetData string for the asset being auctioned. - * @return An object containing the auction asset, auction begin time and auction begin amount. - */ - public static decodeDutchAuctionData(dutchAuctionData: string): DutchAuctionData { - const dutchAuctionDataBuffer = ethUtil.toBuffer(dutchAuctionData); - // Decode asset data - const dutchAuctionDataLengthInBytes = 64; - const assetDataBuffer = dutchAuctionDataBuffer.slice( - 0, - dutchAuctionDataBuffer.byteLength - dutchAuctionDataLengthInBytes, - ); - const assetDataHex = ethUtil.bufferToHex(assetDataBuffer); - const assetData = assetDataUtils.decodeAssetDataOrThrow(assetDataHex); - // Decode auction details - const dutchAuctionDetailsBuffer = dutchAuctionDataBuffer.slice( - dutchAuctionDataBuffer.byteLength - dutchAuctionDataLengthInBytes, - ); - const [beginTimeSecondsAsBN, beginAmountAsBN] = ethAbi.rawDecode( - ['uint256', 'uint256'], - dutchAuctionDetailsBuffer, - ); - const beginTimeSeconds = new BigNumber(`0x${beginTimeSecondsAsBN.toString()}`); - const beginAmount = new BigNumber(`0x${beginAmountAsBN.toString()}`); - return { - assetData, - beginTimeSeconds, - beginAmount, - }; - } - /** - * Instantiate DutchAuctionWrapper - * @param web3Wrapper Web3Wrapper instance to use. - * @param networkId Desired networkId. - * @param address The address of the Dutch Auction contract. If undefined, will - * default to the known address corresponding to the networkId. - */ - public constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { - super(web3Wrapper, networkId); - this.address = _.isUndefined(address) ? _getDefaultContractAddresses(networkId).dutchAuction : address; - } - /** - * Matches the buy and sell orders at an amount given the following: the current block time, the auction - * start time and the auction begin amount. The sell order is a an order at the lowest amount - * at the end of the auction. Excess from the match is transferred to the seller. - * Over time the price moves from beginAmount to endAmount given the current block.timestamp. - * @param buyOrder The Buyer's order. This order is for the current expected price of the auction. - * @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction). - * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied - * Provider provided at instantiation. - * @return Transaction hash. - */ - public async matchOrdersAsync( - buyOrder: SignedOrder, - sellOrder: SignedOrder, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - // type assertions - assert.doesConformToSchema('buyOrder', buyOrder, schemas.signedOrderSchema); - assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - // other assertions - if ( - sellOrder.makerAssetData !== buyOrder.takerAssetData || - sellOrder.takerAssetData !== buyOrder.makerAssetData - ) { - throw new Error(DutchAuctionWrapperError.AssetDataMismatch); - } - // get contract - const dutchAuctionInstance = await this._getDutchAuctionContractAsync(); - // validate transaction - if (orderTransactionOpts.shouldValidate) { - await dutchAuctionInstance.matchOrders.callAsync( - buyOrder, - sellOrder, - buyOrder.signature, - sellOrder.signature, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - } - // send transaction - const txHash = await dutchAuctionInstance.matchOrders.sendTransactionAsync( - buyOrder, - sellOrder, - buyOrder.signature, - sellOrder.signature, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Fetches the Auction Details for the given order - * @param sellOrder The Seller's order. This order is for the lowest amount (at the end of the auction). - * @return The dutch auction details. - */ - public async getAuctionDetailsAsync(sellOrder: SignedOrder): Promise<DutchAuctionDetails> { - // type assertions - assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema); - // get contract - const dutchAuctionInstance = await this._getDutchAuctionContractAsync(); - // call contract - const auctionDetails = await dutchAuctionInstance.getAuctionDetails.callAsync(sellOrder); - return auctionDetails; - } - private async _getDutchAuctionContractAsync(): Promise<DutchAuctionContract> { - if (!_.isUndefined(this._dutchAuctionContractIfExists)) { - return this._dutchAuctionContractIfExists; - } - const contractInstance = new DutchAuctionContract( - this.abi, - this.address, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - this._dutchAuctionContractIfExists = contractInstance; - return this._dutchAuctionContractIfExists; - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts deleted file mode 100644 index 45460bd6d..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { ERC20ProxyContract } from '@0x/abi-gen-wrappers'; -import { ERC20Proxy } from '@0x/contract-artifacts'; -import { AssetProxyId } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { ContractAbi } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { assert } from '../utils/assert'; -import { _getDefaultContractAddresses } from '../utils/contract_addresses'; - -import { ContractWrapper } from './contract_wrapper'; - -/** - * This class includes the functionality related to interacting with the ERC20Proxy contract. - */ -export class ERC20ProxyWrapper extends ContractWrapper { - public abi: ContractAbi = ERC20Proxy.compilerOutput.abi; - public address: string; - private _erc20ProxyContractIfExists?: ERC20ProxyContract; - /** - * Instantiate ERC20ProxyWrapper - * @param web3Wrapper Web3Wrapper instance to use - * @param networkId Desired networkId - * @param address The address of the ERC20Proxy contract. If undefined, will - * default to the known address corresponding to the networkId. - */ - constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { - super(web3Wrapper, networkId); - this.address = _.isUndefined(address) ? _getDefaultContractAddresses(networkId).erc20Proxy : address; - } - /** - * Get the 4 bytes ID of this asset proxy - * @return Proxy id - */ - public async getProxyIdAsync(): Promise<AssetProxyId> { - const ERC20ProxyContractInstance = this._getERC20ProxyContract(); - // Note(albrow): Below is a TSLint false positive. Code won't compile if - // you remove the type assertion. - /* tslint:disable-next-line:no-unnecessary-type-assertion */ - const proxyId = (await ERC20ProxyContractInstance.getProxyId.callAsync()) as AssetProxyId; - return proxyId; - } - /** - * Check if the Exchange contract address is authorized by the ERC20Proxy contract. - * @param exchangeContractAddress The hex encoded address of the Exchange contract to call. - * @return Whether the exchangeContractAddress is authorized. - */ - public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> { - assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress); - const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase(); - const ERC20ProxyContractInstance = this._getERC20ProxyContract(); - const isAuthorized = await ERC20ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress); - return isAuthorized; - } - /** - * Get the list of all Exchange contract addresses authorized by the ERC20Proxy contract. - * @return The list of authorized addresses. - */ - public async getAuthorizedAddressesAsync(): Promise<string[]> { - const ERC20ProxyContractInstance = this._getERC20ProxyContract(); - const authorizedAddresses = await ERC20ProxyContractInstance.getAuthorizedAddresses.callAsync(); - return authorizedAddresses; - } - private _getERC20ProxyContract(): ERC20ProxyContract { - if (!_.isUndefined(this._erc20ProxyContractIfExists)) { - return this._erc20ProxyContractIfExists; - } - const contractInstance = new ERC20ProxyContract( - this.abi, - this.address, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - this._erc20ProxyContractIfExists = contractInstance; - return this._erc20ProxyContractIfExists; - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts deleted file mode 100644 index cd79a0e5d..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts +++ /dev/null @@ -1,443 +0,0 @@ -import { ERC20TokenContract, ERC20TokenEventArgs, ERC20TokenEvents } from '@0x/abi-gen-wrappers'; -import { ERC20Token } from '@0x/contract-artifacts'; -import { schemas } from '@0x/json-schemas'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { methodOptsSchema } from '../schemas/method_opts_schema'; -import { txOptsSchema } from '../schemas/tx_opts_schema'; -import { - BlockRange, - ContractWrappersError, - EventCallback, - IndexedFilterValues, - MethodOpts, - TransactionOpts, -} from '../types'; -import { assert } from '../utils/assert'; -import { constants } from '../utils/constants'; -import { utils } from '../utils/utils'; - -import { ContractWrapper } from './contract_wrapper'; -import { ERC20ProxyWrapper } from './erc20_proxy_wrapper'; - -/** - * This class includes all the functionality related to interacting with ERC20 token contracts. - * All ERC20 method calls are supported, along with some convenience methods for getting/setting allowances - * to the 0x ERC20 Proxy smart contract. - */ -export class ERC20TokenWrapper extends ContractWrapper { - public abi: ContractAbi = ERC20Token.compilerOutput.abi; - public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; - private readonly _tokenContractsByAddress: { [address: string]: ERC20TokenContract }; - private readonly _erc20ProxyWrapper: ERC20ProxyWrapper; - /** - * Instantiate ERC20TokenWrapper - * @param web3Wrapper Web3Wrapper instance to use - * @param networkId Desired networkId - * @param erc20ProxyWrapper The ERC20ProxyWrapper instance to use - * @param blockPollingIntervalMs The block polling interval to use for active subscriptions - */ - constructor( - web3Wrapper: Web3Wrapper, - networkId: number, - erc20ProxyWrapper: ERC20ProxyWrapper, - blockPollingIntervalMs?: number, - ) { - super(web3Wrapper, networkId, blockPollingIntervalMs); - this._tokenContractsByAddress = {}; - this._erc20ProxyWrapper = erc20ProxyWrapper; - } - /** - * Retrieves an owner's ERC20 token balance. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address whose balance you would like to check. - * @param methodOpts Optional arguments this method accepts. - * @return The owner's ERC20 token balance in base units. - */ - public async getBalanceAsync( - tokenAddress: string, - ownerAddress: string, - methodOpts: MethodOpts = {}, - ): Promise<BigNumber> { - assert.isETHAddressHex('ownerAddress', ownerAddress); - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedOwnerAddress = ownerAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - - const txData = {}; - let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, methodOpts.defaultBlock); - // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber - balance = new BigNumber(balance); - return balance; - } - /** - * Sets the spender's allowance to a specified number of baseUnits on behalf of the owner address. - * Equivalent to the ERC20 spec method `approve`. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance - * for spenderAddress. - * @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance. - * @param amountInBaseUnits The allowance amount you would like to set. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async setAllowanceAsync( - tokenAddress: string, - ownerAddress: string, - spenderAddress: string, - amountInBaseUnits: BigNumber, - txOpts: TransactionOpts = {}, - ): Promise<string> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper); - assert.isETHAddressHex('spenderAddress', spenderAddress); - assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits); - assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedOwnerAddress = ownerAddress.toLowerCase(); - const normalizedSpenderAddress = spenderAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - const txHash = await tokenContract.approve.sendTransactionAsync( - normalizedSpenderAddress, - amountInBaseUnits, - utils.removeUndefinedProperties({ - from: normalizedOwnerAddress, - gas: txOpts.gasLimit, - gasPrice: txOpts.gasPrice, - nonce: txOpts.nonce, - }), - ); - return txHash; - } - /** - * Sets the spender's allowance to an unlimited number of baseUnits on behalf of the owner address. - * Equivalent to the ERC20 spec method `approve`. - * Setting an unlimited allowance will lower the gas cost for filling orders involving tokens that forego updating - * allowances set to the max amount (e.g ZRX, WETH) - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address who would like to set an allowance - * for spenderAddress. - * @param spenderAddress The hex encoded user Ethereum address who will be able to spend the set allowance. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async setUnlimitedAllowanceAsync( - tokenAddress: string, - ownerAddress: string, - spenderAddress: string, - txOpts: TransactionOpts = {}, - ): Promise<string> { - const txHash = await this.setAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - txOpts, - ); - return txHash; - } - /** - * Retrieves the owners allowance in baseUnits set to the spender's address. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address whose allowance to spenderAddress - * you would like to retrieve. - * @param spenderAddress The hex encoded user Ethereum address who can spend the allowance you are fetching. - * @param methodOpts Optional arguments this method accepts. - */ - public async getAllowanceAsync( - tokenAddress: string, - ownerAddress: string, - spenderAddress: string, - methodOpts: MethodOpts = {}, - ): Promise<BigNumber> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.isETHAddressHex('ownerAddress', ownerAddress); - assert.isETHAddressHex('spenderAddress', spenderAddress); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedOwnerAddress = ownerAddress.toLowerCase(); - const normalizedSpenderAddress = spenderAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - - const txData = {}; - let allowanceInBaseUnits = await tokenContract.allowance.callAsync( - normalizedOwnerAddress, - normalizedSpenderAddress, - txData, - methodOpts.defaultBlock, - ); - // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber - allowanceInBaseUnits = new BigNumber(allowanceInBaseUnits); - return allowanceInBaseUnits; - } - /** - * Retrieves the owner's allowance in baseUnits set to the 0x proxy contract. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address whose proxy contract allowance we are retrieving. - * @param methodOpts Optional arguments this method accepts. - */ - public async getProxyAllowanceAsync( - tokenAddress: string, - ownerAddress: string, - methodOpts: MethodOpts = {}, - ): Promise<BigNumber> { - const proxyAddress = this._erc20ProxyWrapper.address; - const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts); - return allowanceInBaseUnits; - } - /** - * Sets the 0x proxy contract's allowance to a specified number of a tokens' baseUnits on behalf - * of an owner address. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address who is setting an allowance - * for the Proxy contract. - * @param amountInBaseUnits The allowance amount specified in baseUnits. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async setProxyAllowanceAsync( - tokenAddress: string, - ownerAddress: string, - amountInBaseUnits: BigNumber, - txOpts: TransactionOpts = {}, - ): Promise<string> { - const proxyAddress = this._erc20ProxyWrapper.address; - const txHash = await this.setAllowanceAsync( - tokenAddress, - ownerAddress, - proxyAddress, - amountInBaseUnits, - txOpts, - ); - return txHash; - } - /** - * Sets the 0x proxy contract's allowance to a unlimited number of a tokens' baseUnits on behalf - * of an owner address. - * Setting an unlimited allowance will lower the gas cost for filling orders involving tokens that forego updating - * allowances set to the max amount (e.g ZRX, WETH) - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address who is setting an allowance - * for the Proxy contract. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async setUnlimitedProxyAllowanceAsync( - tokenAddress: string, - ownerAddress: string, - txOpts: TransactionOpts = {}, - ): Promise<string> { - const txHash = await this.setProxyAllowanceAsync( - tokenAddress, - ownerAddress, - this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - txOpts, - ); - return txHash; - } - /** - * Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param fromAddress The hex encoded user Ethereum address that will send the funds. - * @param toAddress The hex encoded user Ethereum address that will receive the funds. - * @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async transferAsync( - tokenAddress: string, - fromAddress: string, - toAddress: string, - amountInBaseUnits: BigNumber, - txOpts: TransactionOpts = {}, - ): Promise<string> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - await assert.isSenderAddressAsync('fromAddress', fromAddress, this._web3Wrapper); - assert.isETHAddressHex('toAddress', toAddress); - assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits); - assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedFromAddress = fromAddress.toLowerCase(); - const normalizedToAddress = toAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - - const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress); - if (fromAddressBalance.isLessThan(amountInBaseUnits)) { - throw new Error(ContractWrappersError.InsufficientBalanceForTransfer); - } - - const txHash = await tokenContract.transfer.sendTransactionAsync( - normalizedToAddress, - amountInBaseUnits, - utils.removeUndefinedProperties({ - from: normalizedFromAddress, - gas: txOpts.gasLimit, - gasPrice: txOpts.gasPrice, - nonce: txOpts.nonce, - }), - ); - return txHash; - } - /** - * Transfers `amountInBaseUnits` ERC20 tokens from `fromAddress` to `toAddress`. - * Requires the fromAddress to have sufficient funds and to have approved an allowance of - * `amountInBaseUnits` to `senderAddress`. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC20 token is deployed. - * @param fromAddress The hex encoded user Ethereum address whose funds are being sent. - * @param toAddress The hex encoded user Ethereum address that will receive the funds. - * @param senderAddress The hex encoded user Ethereum address whose initiates the fund transfer. The - * `fromAddress` must have set an allowance to the `senderAddress` - * before this call. - * @param amountInBaseUnits The amount (specified in baseUnits) of the token to transfer. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async transferFromAsync( - tokenAddress: string, - fromAddress: string, - toAddress: string, - senderAddress: string, - amountInBaseUnits: BigNumber, - txOpts: TransactionOpts = {}, - ): Promise<string> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.isETHAddressHex('fromAddress', fromAddress); - assert.isETHAddressHex('toAddress', toAddress); - await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); - assert.isValidBaseUnitAmount('amountInBaseUnits', amountInBaseUnits); - assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); - const normalizedToAddress = toAddress.toLowerCase(); - const normalizedFromAddress = fromAddress.toLowerCase(); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedSenderAddress = senderAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - - const fromAddressAllowance = await this.getAllowanceAsync( - normalizedTokenAddress, - normalizedFromAddress, - normalizedSenderAddress, - ); - if (fromAddressAllowance.isLessThan(amountInBaseUnits)) { - throw new Error(ContractWrappersError.InsufficientAllowanceForTransfer); - } - - const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress); - if (fromAddressBalance.isLessThan(amountInBaseUnits)) { - throw new Error(ContractWrappersError.InsufficientBalanceForTransfer); - } - - const txHash = await tokenContract.transferFrom.sendTransactionAsync( - normalizedFromAddress, - normalizedToAddress, - amountInBaseUnits, - utils.removeUndefinedProperties({ - from: normalizedSenderAddress, - gas: txOpts.gasLimit, - gasPrice: txOpts.gasPrice, - nonce: txOpts.nonce, - }), - ); - return txHash; - } - /** - * Subscribe to an event type emitted by the Token contract. - * @param tokenAddress The hex encoded address where the ERC20 token is deployed. - * @param eventName The token contract event you would like to subscribe to. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` - * @param callback Callback that gets called when a log is added/removed - * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) - * @return Subscription token used later to unsubscribe - */ - public subscribe<ArgsType extends ERC20TokenEventArgs>( - tokenAddress: string, - eventName: ERC20TokenEvents, - indexFilterValues: IndexedFilterValues, - callback: EventCallback<ArgsType>, - isVerbose: boolean = false, - ): string { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - assert.isFunction('callback', callback); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const subscriptionToken = this._subscribe<ArgsType>( - normalizedTokenAddress, - eventName, - indexFilterValues, - ERC20Token.compilerOutput.abi, - callback, - isVerbose, - ); - return subscriptionToken; - } - /** - * Cancel a subscription - * @param subscriptionToken Subscription token returned by `subscribe()` - */ - public unsubscribe(subscriptionToken: string): void { - assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken); - this._unsubscribe(subscriptionToken); - } - /** - * Cancels all existing subscriptions - */ - public unsubscribeAll(): void { - super._unsubscribeAll(); - } - /** - * Gets historical logs without creating a subscription - * @param tokenAddress An address of the token that emitted the logs. - * @param eventName The token contract event you would like to subscribe to. - * @param blockRange Block range to get logs from. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{_from: aUserAddressHex}` - * @return Array of logs that match the parameters - */ - public async getLogsAsync<ArgsType extends ERC20TokenEventArgs>( - tokenAddress: string, - eventName: ERC20TokenEvents, - blockRange: BlockRange, - indexFilterValues: IndexedFilterValues, - ): Promise<Array<LogWithDecodedArgs<ArgsType>>> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents); - assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const logs = await this._getLogsAsync<ArgsType>( - normalizedTokenAddress, - eventName, - blockRange, - indexFilterValues, - ERC20Token.compilerOutput.abi, - ); - return logs; - } - private async _getTokenContractAsync(tokenAddress: string): Promise<ERC20TokenContract> { - const normalizedTokenAddress = tokenAddress.toLowerCase(); - let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress]; - if (!_.isUndefined(tokenContract)) { - return tokenContract; - } - const contractInstance = new ERC20TokenContract( - this.abi, - normalizedTokenAddress, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - tokenContract = contractInstance; - this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract; - return tokenContract; - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts deleted file mode 100644 index 12758e191..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { ERC721ProxyContract } from '@0x/abi-gen-wrappers'; -import { ERC721Proxy } from '@0x/contract-artifacts'; -import { AssetProxyId } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { ContractAbi } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { assert } from '../utils/assert'; -import { _getDefaultContractAddresses } from '../utils/contract_addresses'; - -import { ContractWrapper } from './contract_wrapper'; - -/** - * This class includes the functionality related to interacting with the ERC721Proxy contract. - */ -export class ERC721ProxyWrapper extends ContractWrapper { - public abi: ContractAbi = ERC721Proxy.compilerOutput.abi; - public address: string; - private _erc721ProxyContractIfExists?: ERC721ProxyContract; - /** - * Instantiate ERC721ProxyWrapper - * @param web3Wrapper Web3Wrapper instance to use - * @param networkId Desired networkId - * @param address The address of the ERC721Proxy contract. If undefined, - * will default to the known address corresponding to the networkId. - */ - constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { - super(web3Wrapper, networkId); - this.address = _.isUndefined(address) ? _getDefaultContractAddresses(networkId).erc721Proxy : address; - } - /** - * Get the 4 bytes ID of this asset proxy - * @return Proxy id - */ - public async getProxyIdAsync(): Promise<AssetProxyId> { - const ERC721ProxyContractInstance = await this._getERC721ProxyContract(); - // Note(albrow): Below is a TSLint false positive. Code won't compile if - // you remove the type assertion. - /* tslint:disable-next-line:no-unnecessary-type-assertion */ - const proxyId = (await ERC721ProxyContractInstance.getProxyId.callAsync()) as AssetProxyId; - return proxyId; - } - /** - * Check if the Exchange contract address is authorized by the ERC721Proxy contract. - * @param exchangeContractAddress The hex encoded address of the Exchange contract to call. - * @return Whether the exchangeContractAddress is authorized. - */ - public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> { - assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress); - const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase(); - const ERC721ProxyContractInstance = await this._getERC721ProxyContract(); - const isAuthorized = await ERC721ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress); - return isAuthorized; - } - /** - * Get the list of all Exchange contract addresses authorized by the ERC721Proxy contract. - * @return The list of authorized addresses. - */ - public async getAuthorizedAddressesAsync(): Promise<string[]> { - const ERC721ProxyContractInstance = await this._getERC721ProxyContract(); - const authorizedAddresses = await ERC721ProxyContractInstance.getAuthorizedAddresses.callAsync(); - return authorizedAddresses; - } - private _getERC721ProxyContract(): ERC721ProxyContract { - if (!_.isUndefined(this._erc721ProxyContractIfExists)) { - return this._erc721ProxyContractIfExists; - } - const contractInstance = new ERC721ProxyContract( - this.abi, - this.address, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - this._erc721ProxyContractIfExists = contractInstance; - return this._erc721ProxyContractIfExists; - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts deleted file mode 100644 index 3bc7dc8e7..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts +++ /dev/null @@ -1,470 +0,0 @@ -import { ERC721TokenContract, ERC721TokenEventArgs, ERC721TokenEvents } from '@0x/abi-gen-wrappers'; -import { ERC721Token } from '@0x/contract-artifacts'; -import { schemas } from '@0x/json-schemas'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { methodOptsSchema } from '../schemas/method_opts_schema'; -import { txOptsSchema } from '../schemas/tx_opts_schema'; -import { - BlockRange, - ContractWrappersError, - EventCallback, - IndexedFilterValues, - MethodOpts, - TransactionOpts, -} from '../types'; -import { assert } from '../utils/assert'; -import { constants } from '../utils/constants'; -import { utils } from '../utils/utils'; - -import { ContractWrapper } from './contract_wrapper'; -import { ERC721ProxyWrapper } from './erc721_proxy_wrapper'; - -/** - * This class includes all the functionality related to interacting with ERC721 token contracts. - * All ERC721 method calls are supported, along with some convenience methods for getting/setting allowances - * to the 0x ERC721 Proxy smart contract. - */ -export class ERC721TokenWrapper extends ContractWrapper { - public abi: ContractAbi = ERC721Token.compilerOutput.abi; - private readonly _tokenContractsByAddress: { [address: string]: ERC721TokenContract }; - private readonly _erc721ProxyWrapper: ERC721ProxyWrapper; - /** - * Instantiate ERC721TokenWrapper - * @param web3Wrapper Web3Wrapper instance to use - * @param networkId Desired networkId - * @param erc721ProxyWrapper The ERC721ProxyWrapper instance to use - * @param blockPollingIntervalMs The block polling interval to use for active subscriptions - */ - constructor( - web3Wrapper: Web3Wrapper, - networkId: number, - erc721ProxyWrapper: ERC721ProxyWrapper, - blockPollingIntervalMs?: number, - ) { - super(web3Wrapper, networkId, blockPollingIntervalMs); - this._tokenContractsByAddress = {}; - this._erc721ProxyWrapper = erc721ProxyWrapper; - } - /** - * Count all NFTs assigned to an owner - * NFTs assigned to the zero address are considered invalid, and this function throws for queries about the zero address. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address whose balance you would like to check. - * @param methodOpts Optional arguments this method accepts. - * @return The number of NFTs owned by `ownerAddress`, possibly zero - */ - public async getTokenCountAsync( - tokenAddress: string, - ownerAddress: string, - methodOpts: MethodOpts = {}, - ): Promise<BigNumber> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.isETHAddressHex('ownerAddress', ownerAddress); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedOwnerAddress = ownerAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - - const txData = {}; - let balance = await tokenContract.balanceOf.callAsync(normalizedOwnerAddress, txData, methodOpts.defaultBlock); - // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber - balance = new BigNumber(balance); - return balance; - } - /** - * Find the owner of an NFT - * NFTs assigned to zero address are considered invalid, and queries about them do throw. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param tokenId The identifier for an NFT - * @param methodOpts Optional arguments this method accepts. - * @return The address of the owner of the NFT - */ - public async getOwnerOfAsync( - tokenAddress: string, - tokenId: BigNumber, - methodOpts: MethodOpts = {}, - ): Promise<string> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.isBigNumber('tokenId', tokenId); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - - const txData = {}; - try { - const tokenOwner = await tokenContract.ownerOf.callAsync(tokenId, txData, methodOpts.defaultBlock); - return tokenOwner; - } catch (err) { - throw new Error(ContractWrappersError.ERC721OwnerNotFound); - } - } - /** - * Query if an address is an authorized operator for all NFT's of `ownerAddress` - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address of the token owner. - * @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to check if approved. - * @param methodOpts Optional arguments this method accepts. - * @return True if `operatorAddress` is an approved operator for `ownerAddress`, false otherwise - */ - public async isApprovedForAllAsync( - tokenAddress: string, - ownerAddress: string, - operatorAddress: string, - methodOpts: MethodOpts = {}, - ): Promise<boolean> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.isETHAddressHex('ownerAddress', ownerAddress); - assert.isETHAddressHex('operatorAddress', operatorAddress); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedOwnerAddress = ownerAddress.toLowerCase(); - const normalizedOperatorAddress = operatorAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - - const txData = {}; - const isApprovedForAll = await tokenContract.isApprovedForAll.callAsync( - normalizedOwnerAddress, - normalizedOperatorAddress, - txData, - methodOpts.defaultBlock, - ); - return isApprovedForAll; - } - /** - * Query if 0x proxy is an authorized operator for all NFT's of `ownerAddress` - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address of the token owner. - * @param methodOpts Optional arguments this method accepts. - * @return True if `operatorAddress` is an approved operator for `ownerAddress`, false otherwise - */ - public async isProxyApprovedForAllAsync( - tokenAddress: string, - ownerAddress: string, - methodOpts: MethodOpts = {}, - ): Promise<boolean> { - const proxyAddress = this._erc721ProxyWrapper.address; - const isProxyApprovedForAll = await this.isApprovedForAllAsync( - tokenAddress, - ownerAddress, - proxyAddress, - methodOpts, - ); - return isProxyApprovedForAll; - } - /** - * Get the approved address for a single NFT. Returns undefined if no approval was set - * Throws if `_tokenId` is not a valid NFT - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param tokenId The identifier for an NFT - * @param methodOpts Optional arguments this method accepts. - * @return The approved address for this NFT, or the undefined if there is none - */ - public async getApprovedIfExistsAsync( - tokenAddress: string, - tokenId: BigNumber, - methodOpts: MethodOpts = {}, - ): Promise<string | undefined> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.isBigNumber('tokenId', tokenId); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - - const txData = {}; - const approvedAddress = await tokenContract.getApproved.callAsync(tokenId, txData, methodOpts.defaultBlock); - if (approvedAddress === constants.NULL_ADDRESS) { - return undefined; - } - return approvedAddress; - } - /** - * Checks if 0x proxy is approved for a single NFT - * Throws if `_tokenId` is not a valid NFT - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param tokenId The identifier for an NFT - * @param methodOpts Optional arguments this method accepts. - * @return True if 0x proxy is approved - */ - public async isProxyApprovedAsync( - tokenAddress: string, - tokenId: BigNumber, - methodOpts: MethodOpts = {}, - ): Promise<boolean> { - const proxyAddress = this._erc721ProxyWrapper.address; - const approvedAddress = await this.getApprovedIfExistsAsync(tokenAddress, tokenId, methodOpts); - const isProxyApproved = approvedAddress === proxyAddress; - return isProxyApproved; - } - /** - * Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets. - * Throws if `_tokenId` is not a valid NFT - * Emits the ApprovalForAll event. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address of the token owner. - * @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to set approval for. - * @param isApproved The boolean variable to set the approval to. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async setApprovalForAllAsync( - tokenAddress: string, - ownerAddress: string, - operatorAddress: string, - isApproved: boolean, - txOpts: TransactionOpts = {}, - ): Promise<string> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - await assert.isSenderAddressAsync('ownerAddress', ownerAddress, this._web3Wrapper); - assert.isETHAddressHex('operatorAddress', operatorAddress); - assert.isBoolean('isApproved', isApproved); - assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedOwnerAddress = ownerAddress.toLowerCase(); - const normalizedOperatorAddress = operatorAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - const txHash = await tokenContract.setApprovalForAll.sendTransactionAsync( - normalizedOperatorAddress, - isApproved, - utils.removeUndefinedProperties({ - gas: txOpts.gasLimit, - gasPrice: txOpts.gasPrice, - from: normalizedOwnerAddress, - nonce: txOpts.nonce, - }), - ); - return txHash; - } - /** - * Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets. - * Throws if `_tokenId` is not a valid NFT - * Emits the ApprovalForAll event. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param ownerAddress The hex encoded user Ethereum address of the token owner. - * @param operatorAddress The hex encoded user Ethereum address of the operator you'd like to set approval for. - * @param isApproved The boolean variable to set the approval to. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async setProxyApprovalForAllAsync( - tokenAddress: string, - ownerAddress: string, - isApproved: boolean, - txOpts: TransactionOpts = {}, - ): Promise<string> { - const proxyAddress = this._erc721ProxyWrapper.address; - const txHash = await this.setApprovalForAllAsync(tokenAddress, ownerAddress, proxyAddress, isApproved, txOpts); - return txHash; - } - /** - * Set or reaffirm the approved address for an NFT - * The zero address indicates there is no approved address. Throws unless `msg.sender` is the current NFT owner, - * or an authorized operator of the current owner. - * Throws if `_tokenId` is not a valid NFT - * Emits the Approval event. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param approvedAddress The hex encoded user Ethereum address you'd like to set approval for. - * @param tokenId The identifier for an NFT - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async setApprovalAsync( - tokenAddress: string, - approvedAddress: string, - tokenId: BigNumber, - txOpts: TransactionOpts = {}, - ): Promise<string> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.isETHAddressHex('approvedAddress', approvedAddress); - assert.isBigNumber('tokenId', tokenId); - assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedApprovedAddress = approvedAddress.toLowerCase(); - - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - const tokenOwnerAddress = await tokenContract.ownerOf.callAsync(tokenId); - await assert.isSenderAddressAsync('tokenOwnerAddress', tokenOwnerAddress, this._web3Wrapper); - const txHash = await tokenContract.approve.sendTransactionAsync( - normalizedApprovedAddress, - tokenId, - utils.removeUndefinedProperties({ - gas: txOpts.gasLimit, - gasPrice: txOpts.gasPrice, - from: tokenOwnerAddress, - nonce: txOpts.nonce, - }), - ); - return txHash; - } - /** - * Set or reaffirm 0x proxy as an approved address for an NFT - * Throws unless `msg.sender` is the current NFT owner, or an authorized operator of the current owner. - * Throws if `_tokenId` is not a valid NFT - * Emits the Approval event. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param tokenId The identifier for an NFT - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async setProxyApprovalAsync( - tokenAddress: string, - tokenId: BigNumber, - txOpts: TransactionOpts = {}, - ): Promise<string> { - const proxyAddress = this._erc721ProxyWrapper.address; - const txHash = await this.setApprovalAsync(tokenAddress, proxyAddress, tokenId, txOpts); - return txHash; - } - /** - * Enable or disable approval for a third party ("operator") to manage all of `ownerAddress`'s assets. - * Throws if `_tokenId` is not a valid NFT - * Emits the ApprovalForAll event. - * @param tokenAddress The hex encoded contract Ethereum address where the ERC721 token is deployed. - * @param receiverAddress The hex encoded Ethereum address of the user to send the NFT to. - * @param senderAddress The hex encoded Ethereum address of the user to send the NFT to. - * @param tokenId The identifier for an NFT - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async transferFromAsync( - tokenAddress: string, - receiverAddress: string, - senderAddress: string, - tokenId: BigNumber, - txOpts: TransactionOpts = {}, - ): Promise<string> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.isETHAddressHex('receiverAddress', receiverAddress); - await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); - assert.doesConformToSchema('txOpts', txOpts, txOptsSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const normalizedReceiverAddress = receiverAddress.toLowerCase(); - const normalizedSenderAddress = senderAddress.toLowerCase(); - const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress); - const ownerAddress = await this.getOwnerOfAsync(tokenAddress, tokenId); - if (normalizedSenderAddress !== ownerAddress) { - const isApprovedForAll = await this.isApprovedForAllAsync( - normalizedTokenAddress, - ownerAddress, - normalizedSenderAddress, - ); - if (!isApprovedForAll) { - const approvedAddress = await this.getApprovedIfExistsAsync(normalizedTokenAddress, tokenId); - if (approvedAddress !== normalizedSenderAddress) { - throw new Error(ContractWrappersError.ERC721NoApproval); - } - } - } - const txHash = await tokenContract.transferFrom.sendTransactionAsync( - ownerAddress, - normalizedReceiverAddress, - tokenId, - utils.removeUndefinedProperties({ - gas: txOpts.gasLimit, - gasPrice: txOpts.gasPrice, - from: normalizedSenderAddress, - nonce: txOpts.nonce, - }), - ); - return txHash; - } - /** - * Subscribe to an event type emitted by the Token contract. - * @param tokenAddress The hex encoded address where the ERC721 token is deployed. - * @param eventName The token contract event you would like to subscribe to. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` - * @param callback Callback that gets called when a log is added/removed - * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) - * @return Subscription token used later to unsubscribe - */ - public subscribe<ArgsType extends ERC721TokenEventArgs>( - tokenAddress: string, - eventName: ERC721TokenEvents, - indexFilterValues: IndexedFilterValues, - callback: EventCallback<ArgsType>, - isVerbose: boolean = false, - ): string { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - assert.isFunction('callback', callback); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const subscriptionToken = this._subscribe<ArgsType>( - normalizedTokenAddress, - eventName, - indexFilterValues, - ERC721Token.compilerOutput.abi, - callback, - isVerbose, - ); - return subscriptionToken; - } - /** - * Cancel a subscription - * @param subscriptionToken Subscription token returned by `subscribe()` - */ - public unsubscribe(subscriptionToken: string): void { - assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken); - this._unsubscribe(subscriptionToken); - } - /** - * Cancels all existing subscriptions - */ - public unsubscribeAll(): void { - super._unsubscribeAll(); - } - /** - * Gets historical logs without creating a subscription - * @param tokenAddress An address of the token that emitted the logs. - * @param eventName The token contract event you would like to subscribe to. - * @param blockRange Block range to get logs from. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{_from: aUserAddressHex}` - * @return Array of logs that match the parameters - */ - public async getLogsAsync<ArgsType extends ERC721TokenEventArgs>( - tokenAddress: string, - eventName: ERC721TokenEvents, - blockRange: BlockRange, - indexFilterValues: IndexedFilterValues, - ): Promise<Array<LogWithDecodedArgs<ArgsType>>> { - assert.isETHAddressHex('tokenAddress', tokenAddress); - assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents); - assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - const normalizedTokenAddress = tokenAddress.toLowerCase(); - const logs = await this._getLogsAsync<ArgsType>( - normalizedTokenAddress, - eventName, - blockRange, - indexFilterValues, - ERC721Token.compilerOutput.abi, - ); - return logs; - } - private async _getTokenContractAsync(tokenAddress: string): Promise<ERC721TokenContract> { - const normalizedTokenAddress = tokenAddress.toLowerCase(); - let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress]; - if (!_.isUndefined(tokenContract)) { - return tokenContract; - } - const contractInstance = new ERC721TokenContract( - this.abi, - normalizedTokenAddress, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - tokenContract = contractInstance; - this._tokenContractsByAddress[normalizedTokenAddress] = tokenContract; - return tokenContract; - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts deleted file mode 100644 index 6093f0f95..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { WETH9Contract, WETH9EventArgs, WETH9Events } from '@0x/abi-gen-wrappers'; -import { WETH9 } from '@0x/contract-artifacts'; -import { schemas } from '@0x/json-schemas'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { BlockRange, ContractWrappersError, EventCallback, IndexedFilterValues, TransactionOpts } from '../types'; -import { assert } from '../utils/assert'; -import { utils } from '../utils/utils'; - -import { ContractWrapper } from './contract_wrapper'; -import { ERC20TokenWrapper } from './erc20_token_wrapper'; - -/** - * This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract. - * The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back. - */ -export class EtherTokenWrapper extends ContractWrapper { - public abi: ContractAbi = WETH9.compilerOutput.abi; - private readonly _etherTokenContractsByAddress: { - [address: string]: WETH9Contract; - } = {}; - private readonly _erc20TokenWrapper: ERC20TokenWrapper; - /** - * Instantiate EtherTokenWrapper. - * @param web3Wrapper Web3Wrapper instance to use - * @param networkId Desired networkId - * @param erc20TokenWrapper The ERC20TokenWrapper instance to use - * @param blockPollingIntervalMs The block polling interval to use for active subscriptions - */ - constructor( - web3Wrapper: Web3Wrapper, - networkId: number, - erc20TokenWrapper: ERC20TokenWrapper, - blockPollingIntervalMs?: number, - ) { - super(web3Wrapper, networkId, blockPollingIntervalMs); - this._erc20TokenWrapper = erc20TokenWrapper; - } - /** - * Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens - * to the depositor address. These wrapped ETH tokens can be used in 0x trades and are redeemable for 1-to-1 - * for ETH. - * @param etherTokenAddress EtherToken address you wish to deposit into. - * @param amountInWei Amount of ETH in Wei the caller wishes to deposit. - * @param depositor The hex encoded user Ethereum address that would like to make the deposit. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async depositAsync( - etherTokenAddress: string, - amountInWei: BigNumber, - depositor: string, - txOpts: TransactionOpts = {}, - ): Promise<string> { - assert.isETHAddressHex('etherTokenAddress', etherTokenAddress); - assert.isValidBaseUnitAmount('amountInWei', amountInWei); - await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper); - const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase(); - const normalizedDepositorAddress = depositor.toLowerCase(); - - const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(normalizedDepositorAddress); - assert.assert(ethBalanceInWei.gte(amountInWei), ContractWrappersError.InsufficientEthBalanceForDeposit); - - const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress); - const txHash = await wethContract.deposit.sendTransactionAsync( - utils.removeUndefinedProperties({ - from: normalizedDepositorAddress, - value: amountInWei, - gas: txOpts.gasLimit, - gasPrice: txOpts.gasPrice, - nonce: txOpts.nonce, - }), - ); - return txHash; - } - /** - * Withdraw ETH to the withdrawer's address from the wrapped ETH smart contract in exchange for the - * equivalent number of wrapped ETH tokens. - * @param etherTokenAddress EtherToken address you wish to withdraw from. - * @param amountInWei Amount of ETH in Wei the caller wishes to withdraw. - * @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawal. - * @param txOpts Transaction parameters. - * @return Transaction hash. - */ - public async withdrawAsync( - etherTokenAddress: string, - amountInWei: BigNumber, - withdrawer: string, - txOpts: TransactionOpts = {}, - ): Promise<string> { - assert.isValidBaseUnitAmount('amountInWei', amountInWei); - assert.isETHAddressHex('etherTokenAddress', etherTokenAddress); - await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper); - const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase(); - const normalizedWithdrawerAddress = withdrawer.toLowerCase(); - - const WETHBalanceInBaseUnits = await this._erc20TokenWrapper.getBalanceAsync( - normalizedEtherTokenAddress, - normalizedWithdrawerAddress, - ); - assert.assert( - WETHBalanceInBaseUnits.gte(amountInWei), - ContractWrappersError.InsufficientWEthBalanceForWithdrawal, - ); - - const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress); - const txHash = await wethContract.withdraw.sendTransactionAsync( - amountInWei, - utils.removeUndefinedProperties({ - from: normalizedWithdrawerAddress, - gas: txOpts.gasLimit, - gasPrice: txOpts.gasPrice, - nonce: txOpts.nonce, - }), - ); - return txHash; - } - /** - * Gets historical logs without creating a subscription - * @param etherTokenAddress An address of the ether token that emitted the logs. - * @param eventName The ether token contract event you would like to subscribe to. - * @param blockRange Block range to get logs from. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{_owner: aUserAddressHex}` - * @return Array of logs that match the parameters - */ - public async getLogsAsync<ArgsType extends WETH9EventArgs>( - etherTokenAddress: string, - eventName: WETH9Events, - blockRange: BlockRange, - indexFilterValues: IndexedFilterValues, - ): Promise<Array<LogWithDecodedArgs<ArgsType>>> { - assert.isETHAddressHex('etherTokenAddress', etherTokenAddress); - const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase(); - assert.doesBelongToStringEnum('eventName', eventName, WETH9Events); - assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - const logs = await this._getLogsAsync<ArgsType>( - normalizedEtherTokenAddress, - eventName, - blockRange, - indexFilterValues, - WETH9.compilerOutput.abi, - ); - return logs; - } - /** - * Subscribe to an event type emitted by the Token contract. - * @param etherTokenAddress The hex encoded address where the ether token is deployed. - * @param eventName The ether token contract event you would like to subscribe to. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{_owner: aUserAddressHex}` - * @param callback Callback that gets called when a log is added/removed - * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) - * @return Subscription token used later to unsubscribe - */ - public subscribe<ArgsType extends WETH9EventArgs>( - etherTokenAddress: string, - eventName: WETH9Events, - indexFilterValues: IndexedFilterValues, - callback: EventCallback<ArgsType>, - isVerbose: boolean = false, - ): string { - assert.isETHAddressHex('etherTokenAddress', etherTokenAddress); - const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase(); - assert.doesBelongToStringEnum('eventName', eventName, WETH9Events); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - assert.isFunction('callback', callback); - const subscriptionToken = this._subscribe<ArgsType>( - normalizedEtherTokenAddress, - eventName, - indexFilterValues, - WETH9.compilerOutput.abi, - callback, - isVerbose, - ); - return subscriptionToken; - } - /** - * Cancel a subscription - * @param subscriptionToken Subscription token returned by `subscribe()` - */ - public unsubscribe(subscriptionToken: string): void { - assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken); - this._unsubscribe(subscriptionToken); - } - /** - * Cancels all existing subscriptions - */ - public unsubscribeAll(): void { - super._unsubscribeAll(); - } - private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<WETH9Contract> { - let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress]; - if (!_.isUndefined(etherTokenContract)) { - return etherTokenContract; - } - const contractInstance = new WETH9Contract( - this.abi, - etherTokenAddress, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - etherTokenContract = contractInstance; - this._etherTokenContractsByAddress[etherTokenAddress] = etherTokenContract; - return etherTokenContract; - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts deleted file mode 100644 index 49193f816..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts +++ /dev/null @@ -1,1231 +0,0 @@ -import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from '@0x/abi-gen-wrappers'; -import { Exchange } from '@0x/contract-artifacts'; -import { schemas } from '@0x/json-schemas'; -import { - assetDataUtils, - BalanceAndProxyAllowanceLazyStore, - ExchangeTransferSimulator, - OrderValidationUtils, -} from '@0x/order-utils'; -import { AssetProxyId, Order, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { BlockParamLiteral, ContractAbi, LogWithDecodedArgs } from 'ethereum-types'; -import * as _ from 'lodash'; - -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'; -import { validateOrderFillableOptsSchema } from '../schemas/validate_order_fillable_opts_schema'; -import { - BlockRange, - EventCallback, - ExchangeWrapperError, - IndexedFilterValues, - MethodOpts, - OrderInfo, - OrderTransactionOpts, - ValidateOrderFillableOpts, -} from '../types'; -import { assert } from '../utils/assert'; -import { _getDefaultContractAddresses } from '../utils/contract_addresses'; -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'; - -/** - * This class includes all the functionality related to calling methods, sending transactions and subscribing to - * events of the 0x V2 Exchange smart contract. - */ -export class ExchangeWrapper extends ContractWrapper { - public abi: ContractAbi = Exchange.compilerOutput.abi; - public address: string; - public zrxTokenAddress: string; - private _exchangeContractIfExists?: ExchangeContract; - private readonly _erc721TokenWrapper: ERC721TokenWrapper; - private readonly _erc20TokenWrapper: ERC20TokenWrapper; - /** - * Instantiate ExchangeWrapper - * @param web3Wrapper Web3Wrapper instance to use. - * @param networkId Desired networkId. - * @param erc20TokenWrapper ERC20TokenWrapper instance to use. - * @param erc721TokenWrapper ERC721TokenWrapper instance to use. - * @param address The address of the Exchange contract. If undefined, will - * default to the known address corresponding to the networkId. - * @param zrxTokenAddress The address of the ZRXToken contract. If - * undefined, will default to the known address corresponding to the - * networkId. - * @param blockPollingIntervalMs The block polling interval to use for active subscriptions. - */ - constructor( - web3Wrapper: Web3Wrapper, - networkId: number, - erc20TokenWrapper: ERC20TokenWrapper, - erc721TokenWrapper: ERC721TokenWrapper, - address?: string, - zrxTokenAddress?: string, - blockPollingIntervalMs?: number, - ) { - super(web3Wrapper, networkId, blockPollingIntervalMs); - this._erc20TokenWrapper = erc20TokenWrapper; - this._erc721TokenWrapper = erc721TokenWrapper; - this.address = _.isUndefined(address) ? _getDefaultContractAddresses(networkId).exchange : address; - this.zrxTokenAddress = _.isUndefined(zrxTokenAddress) - ? _getDefaultContractAddresses(networkId).zrxToken - : zrxTokenAddress; - } - /** - * Retrieve the address of an asset proxy by signature. - * @param proxyId The 4 bytes signature of an asset proxy - * @param methodOpts Optional arguments this method accepts. - * @return The address of an asset proxy for a given signature - */ - public async getAssetProxyBySignatureAsync(proxyId: AssetProxyId, methodOpts: MethodOpts = {}): Promise<string> { - assert.doesBelongToStringEnum('proxyId', proxyId, AssetProxyId); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const exchangeContract = await this._getExchangeContractAsync(); - - const txData = {}; - const assetProxy = await exchangeContract.getAssetProxy.callAsync(proxyId, txData, methodOpts.defaultBlock); - return assetProxy; - } - /** - * Retrieve the takerAssetAmount of an order that has already been filled. - * @param orderHash The hex encoded orderHash for which you would like to retrieve the filled takerAssetAmount. - * @param methodOpts Optional arguments this method accepts. - * @return The amount of the order (in taker asset base units) that has already been filled. - */ - public async getFilledTakerAssetAmountAsync(orderHash: string, methodOpts: MethodOpts = {}): Promise<BigNumber> { - assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const exchangeContract = await this._getExchangeContractAsync(); - - const txData = {}; - const filledTakerAssetAmountInBaseUnits = await exchangeContract.filled.callAsync( - orderHash, - txData, - methodOpts.defaultBlock, - ); - return filledTakerAssetAmountInBaseUnits; - } - /** - * Retrieve the exchange contract version - * @param methodOpts Optional arguments this method accepts. - * @return Version - */ - public async getVersionAsync(methodOpts: MethodOpts = {}): Promise<string> { - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const exchangeContract = await this._getExchangeContractAsync(); - - const txData = {}; - const version = await exchangeContract.VERSION.callAsync(txData, methodOpts.defaultBlock); - return version; - } - /** - * Retrieve the set order epoch for a given makerAddress & senderAddress pair. - * Orders can be bulk cancelled by setting the order epoch to a value lower then the salt value of orders one wishes to cancel. - * @param makerAddress Maker address - * @param senderAddress Sender address - * @param methodOpts Optional arguments this method accepts. - * @return Order epoch. Defaults to 0. - */ - public async getOrderEpochAsync( - makerAddress: string, - senderAddress: string, - methodOpts: MethodOpts = {}, - ): Promise<BigNumber> { - assert.isETHAddressHex('makerAddress', makerAddress); - assert.isETHAddressHex('senderAddress', senderAddress); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const exchangeContract = await this._getExchangeContractAsync(); - - const txData = {}; - const orderEpoch = await exchangeContract.orderEpoch.callAsync( - makerAddress, - senderAddress, - txData, - methodOpts.defaultBlock, - ); - return orderEpoch; - } - /** - * Check if an order has been cancelled. Order cancellations are binary - * @param orderHash The hex encoded orderHash for which you would like to retrieve the cancelled takerAmount. - * @param methodOpts Optional arguments this method accepts. - * @return Whether the order has been cancelled. - */ - public async isCancelledAsync(orderHash: string, methodOpts: MethodOpts = {}): Promise<boolean> { - assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const exchangeContract = await this._getExchangeContractAsync(); - - const txData = {}; - const isCancelled = await exchangeContract.cancelled.callAsync(orderHash, txData, methodOpts.defaultBlock); - return isCancelled; - } - /** - * Fills a signed order with an amount denominated in baseUnits of the taker asset. - * @param signedOrder An object that conforms to the SignedOrder interface. - * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. - * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async fillOrderAsync( - signedOrder: SignedOrder, - takerAssetFillAmount: BigNumber, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.fillOrder.callAsync(signedOrder, takerAssetFillAmount, signedOrder.signature, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - - const txHash = await exchangeInstance.fillOrder.sendTransactionAsync( - signedOrder, - takerAssetFillAmount, - signedOrder.signature, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * No-throw version of fillOrderAsync. This version will not throw if the fill fails. This allows the caller to save gas at the expense of not knowing the reason the fill failed. - * @param signedOrder An object that conforms to the SignedOrder interface. - * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. - * @param takerAddress The user Ethereum address who would like to fill this order. - * Must be available via the supplied Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async fillOrderNoThrowAsync( - signedOrder: SignedOrder, - takerAssetFillAmount: BigNumber, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.fillOrderNoThrow.callAsync( - signedOrder, - takerAssetFillAmount, - signedOrder.signature, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - } - const txHash = await exchangeInstance.fillOrderNoThrow.sendTransactionAsync( - signedOrder, - takerAssetFillAmount, - signedOrder.signature, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Attempts to fill a specific amount of an order. If the entire amount specified cannot be filled, - * the fill order is abandoned. - * @param signedOrder An object that conforms to the SignedOrder interface. - * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. - * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async fillOrKillOrderAsync( - signedOrder: SignedOrder, - takerAssetFillAmount: BigNumber, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.fillOrKillOrder.callAsync(signedOrder, takerAssetFillAmount, signedOrder.signature, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync( - signedOrder, - takerAssetFillAmount, - signedOrder.signature, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Executes a 0x transaction. Transaction messages exist for the purpose of calling methods on the Exchange contract - * in the context of another address (see [ZEIP18](https://github.com/0xProject/ZEIPs/issues/18)). - * This is especially useful for implementing filter contracts. - * @param salt Salt - * @param signerAddress Signer address - * @param data Transaction data - * @param signature Signature - * @param senderAddress Sender address - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async executeTransactionAsync( - salt: BigNumber, - signerAddress: string, - data: string, - signature: string, - senderAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.isBigNumber('salt', salt); - assert.isETHAddressHex('signerAddress', signerAddress); - assert.isHexString('data', data); - assert.isHexString('signature', signature); - await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedSenderAddress = senderAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.executeTransaction.callAsync(salt, signerAddress, data, signature, { - from: normalizedSenderAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.executeTransaction.sendTransactionAsync( - salt, - signerAddress, - data, - signature, - { - from: normalizedSenderAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Batch version of fillOrderAsync. Executes multiple fills atomically in a single transaction. - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. - * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async batchFillOrdersAsync( - signedOrders: SignedOrder[], - takerAssetFillAmounts: BigNumber[], - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - _.forEach(takerAssetFillAmounts, takerAssetFillAmount => - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), - ); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.batchFillOrders.callAsync(signedOrders, takerAssetFillAmounts, signatures, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.batchFillOrders.sendTransactionAsync( - signedOrders, - takerAssetFillAmounts, - signatures, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Synchronously executes multiple calls to fillOrder until total amount of makerAsset is bought by taker. - * @param signedOrders An array of signed orders to fill. - * @param makerAssetFillAmount Maker asset fill amount. - * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async marketBuyOrdersAsync( - signedOrders: SignedOrder[], - makerAssetFillAmount: BigNumber, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.marketBuyOrders.callAsync(signedOrders, makerAssetFillAmount, signatures, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.marketBuyOrders.sendTransactionAsync( - signedOrders, - makerAssetFillAmount, - signatures, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Synchronously executes multiple calls to fillOrder until total amount of makerAsset is bought by taker. - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmount Taker asset fill amount. - * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async marketSellOrdersAsync( - signedOrders: SignedOrder[], - takerAssetFillAmount: BigNumber, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.marketSellOrders.callAsync(signedOrders, takerAssetFillAmount, signatures, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.marketSellOrders.sendTransactionAsync( - signedOrders, - takerAssetFillAmount, - signatures, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * No throw version of marketBuyOrdersAsync - * @param signedOrders An array of signed orders to fill. - * @param makerAssetFillAmount Maker asset fill amount. - * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async marketBuyOrdersNoThrowAsync( - signedOrders: SignedOrder[], - makerAssetFillAmount: BigNumber, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.marketBuyOrdersNoThrow.callAsync(signedOrders, makerAssetFillAmount, signatures, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.marketBuyOrdersNoThrow.sendTransactionAsync( - signedOrders, - makerAssetFillAmount, - signatures, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * No throw version of marketSellOrdersAsync - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmount Taker asset fill amount. - * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async marketSellOrdersNoThrowAsync( - signedOrders: SignedOrder[], - takerAssetFillAmount: BigNumber, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.marketSellOrdersNoThrow.callAsync(signedOrders, takerAssetFillAmount, signatures, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.marketSellOrdersNoThrow.sendTransactionAsync( - signedOrders, - takerAssetFillAmount, - signatures, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * No throw version of batchFillOrdersAsync - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. - * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async batchFillOrdersNoThrowAsync( - signedOrders: SignedOrder[], - takerAssetFillAmounts: BigNumber[], - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - _.forEach(takerAssetFillAmounts, takerAssetFillAmount => - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), - ); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.batchFillOrdersNoThrow.callAsync(signedOrders, takerAssetFillAmounts, signatures, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.batchFillOrdersNoThrow.sendTransactionAsync( - signedOrders, - takerAssetFillAmounts, - signatures, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Batch version of fillOrKillOrderAsync. Executes multiple fills atomically in a single transaction. - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. - * @param takerAddress The user Ethereum address who would like to fill these orders. Must be available via the supplied - * Provider provided at instantiation. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async batchFillOrKillOrdersAsync( - signedOrders: SignedOrder[], - takerAssetFillAmounts: BigNumber[], - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - _.forEach(takerAssetFillAmounts, takerAssetFillAmount => - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), - ); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.batchFillOrKillOrders.callAsync(signedOrders, takerAssetFillAmounts, signatures, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync( - signedOrders, - takerAssetFillAmounts, - signatures, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Batch version of cancelOrderAsync. Executes multiple cancels atomically in a single transaction. - * @param orders An array of orders to cancel. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async batchCancelOrdersAsync( - orders: Array<Order | SignedOrder>, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('orders', orders, schemas.ordersSchema); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const makerAddresses = _.map(orders, order => order.makerAddress); - const makerAddress = makerAddresses[0]; - await assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper); - const normalizedMakerAddress = makerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.batchCancelOrders.callAsync(orders, { - from: normalizedMakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync(orders, { - from: normalizedMakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - return txHash; - } - /** - * Match two complementary orders that have a profitable spread. - * Each order is filled at their respective price point. However, the calculations are carried out as though - * the orders are both being filled at the right order's price point. - * The profit made by the left order goes to the taker (whoever matched the two orders). - * @param leftSignedOrder First order to match. - * @param rightSignedOrder Second order to match. - * @param takerAddress The address that sends the transaction and gets the spread. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async matchOrdersAsync( - leftSignedOrder: SignedOrder, - rightSignedOrder: SignedOrder, - takerAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('leftSignedOrder', leftSignedOrder, schemas.signedOrderSchema); - assert.doesConformToSchema('rightSignedOrder', rightSignedOrder, schemas.signedOrderSchema); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = takerAddress.toLowerCase(); - if ( - rightSignedOrder.makerAssetData !== leftSignedOrder.takerAssetData || - rightSignedOrder.takerAssetData !== leftSignedOrder.makerAssetData - ) { - throw new Error(ExchangeWrapperError.AssetDataMismatch); - } - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.matchOrders.callAsync( - leftSignedOrder, - rightSignedOrder, - leftSignedOrder.signature, - rightSignedOrder.signature, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - } - const txHash = await exchangeInstance.matchOrders.sendTransactionAsync( - leftSignedOrder, - rightSignedOrder, - leftSignedOrder.signature, - rightSignedOrder.signature, - { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Approves a hash on-chain using any valid signature type. - * After presigning a hash, the preSign signature type will become valid for that hash and signer. - * @param hash Hash to pre-sign - * @param signerAddress Address that should have signed the given hash. - * @param signature Proof that the hash has been signed by signer. - * @param senderAddress Address that should send the transaction. - * @param orderTransactionOpts Optional arguments this method accepts. - * @returns Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async preSignAsync( - hash: string, - signerAddress: string, - signature: string, - senderAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.isHexString('hash', hash); - assert.isETHAddressHex('signerAddress', signerAddress); - assert.isHexString('signature', signature); - await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedTakerAddress = senderAddress.toLowerCase(); - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.preSign.callAsync(hash, signerAddress, signature, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.preSign.sendTransactionAsync(hash, signerAddress, signature, { - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - return txHash; - } - /** - * Checks if the signature is valid. - * @param hash Hash to pre-sign - * @param signerAddress Address that should have signed the given hash. - * @param signature Proof that the hash has been signed by signer. - * @param methodOpts Optional arguments this method accepts. - * @returns If the signature is valid - */ - @decorators.asyncZeroExErrorHandler - public async isValidSignatureAsync( - hash: string, - signerAddress: string, - signature: string, - methodOpts: MethodOpts = {}, - ): Promise<boolean> { - assert.isHexString('hash', hash); - assert.isETHAddressHex('signerAddress', signerAddress); - assert.isHexString('signature', signature); - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - const exchangeInstance = await this._getExchangeContractAsync(); - const txData = {}; - const isValidSignature = await exchangeInstance.isValidSignature.callAsync( - hash, - signerAddress, - signature, - txData, - methodOpts.defaultBlock, - ); - return isValidSignature; - } - /** - * Checks if the validator is allowed by the signer. - * @param validatorAddress Address of a validator - * @param signerAddress Address of a signer - * @param methodOpts Optional arguments this method accepts. - * @returns If the validator is allowed - */ - @decorators.asyncZeroExErrorHandler - public async isAllowedValidatorAsync( - signerAddress: string, - validatorAddress: string, - methodOpts: MethodOpts = {}, - ): Promise<boolean> { - assert.isETHAddressHex('signerAddress', signerAddress); - assert.isETHAddressHex('validatorAddress', validatorAddress); - if (!_.isUndefined(methodOpts)) { - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - } - const normalizedSignerAddress = signerAddress.toLowerCase(); - const normalizedValidatorAddress = validatorAddress.toLowerCase(); - const exchangeInstance = await this._getExchangeContractAsync(); - const txData = {}; - const isValidSignature = await exchangeInstance.allowedValidators.callAsync( - normalizedSignerAddress, - normalizedValidatorAddress, - txData, - methodOpts.defaultBlock, - ); - return isValidSignature; - } - /** - * Check whether the hash is pre-signed on-chain. - * @param hash Hash to check if pre-signed - * @param signerAddress Address that should have signed the given hash. - * @param methodOpts Optional arguments this method accepts. - * @returns Whether the hash is pre-signed. - */ - @decorators.asyncZeroExErrorHandler - public async isPreSignedAsync(hash: string, signerAddress: string, methodOpts: MethodOpts = {}): Promise<boolean> { - assert.isHexString('hash', hash); - assert.isETHAddressHex('signerAddress', signerAddress); - if (!_.isUndefined(methodOpts)) { - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - } - const exchangeInstance = await this._getExchangeContractAsync(); - - const txData = {}; - const isPreSigned = await exchangeInstance.preSigned.callAsync( - hash, - signerAddress, - txData, - methodOpts.defaultBlock, - ); - return isPreSigned; - } - /** - * Checks if transaction is already executed. - * @param transactionHash Transaction hash to check - * @param signerAddress Address that should have signed the given hash. - * @param methodOpts Optional arguments this method accepts. - * @returns If transaction is already executed. - */ - @decorators.asyncZeroExErrorHandler - public async isTransactionExecutedAsync(transactionHash: string, methodOpts: MethodOpts = {}): Promise<boolean> { - assert.isHexString('transactionHash', transactionHash); - if (!_.isUndefined(methodOpts)) { - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - } - const exchangeInstance = await this._getExchangeContractAsync(); - const txData = {}; - const isExecuted = await exchangeInstance.transactions.callAsync( - transactionHash, - txData, - methodOpts.defaultBlock, - ); - return isExecuted; - } - /** - * Get order info - * @param order Order - * @param methodOpts Optional arguments this method accepts. - * @returns Order info - */ - @decorators.asyncZeroExErrorHandler - public async getOrderInfoAsync(order: Order | SignedOrder, methodOpts: MethodOpts = {}): Promise<OrderInfo> { - assert.doesConformToSchema('order', order, schemas.orderSchema); - if (!_.isUndefined(methodOpts)) { - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - } - const exchangeInstance = await this._getExchangeContractAsync(); - const txData = {}; - const orderInfo = await exchangeInstance.getOrderInfo.callAsync(order, txData, methodOpts.defaultBlock); - return orderInfo; - } - /** - * Get order info for multiple orders - * @param orders Orders - * @param methodOpts Optional arguments this method accepts. - * @returns Array of Order infos - */ - @decorators.asyncZeroExErrorHandler - public async getOrdersInfoAsync( - orders: Array<Order | SignedOrder>, - methodOpts: MethodOpts = {}, - ): Promise<OrderInfo[]> { - assert.doesConformToSchema('orders', orders, schemas.ordersSchema); - if (!_.isUndefined(methodOpts)) { - assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); - } - const exchangeInstance = await this._getExchangeContractAsync(); - const txData = {}; - const ordersInfo = await exchangeInstance.getOrdersInfo.callAsync(orders, txData, methodOpts.defaultBlock); - return ordersInfo; - } - /** - * Cancel a given order. - * @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async cancelOrderAsync( - order: Order | SignedOrder, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.doesConformToSchema('order', order, schemas.orderSchema); - await assert.isSenderAddressAsync('order.maker', order.makerAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedMakerAddress = order.makerAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.cancelOrder.callAsync(order, { - from: normalizedMakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync(order, { - from: normalizedMakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - return txHash; - } - /** - * Sets the signature validator approval - * @param validatorAddress Validator contract address. - * @param isApproved Boolean value to set approval to. - * @param senderAddress Sender address. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async setSignatureValidatorApprovalAsync( - validatorAddress: string, - isApproved: boolean, - senderAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.isETHAddressHex('validatorAddress', validatorAddress); - assert.isBoolean('isApproved', isApproved); - await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedSenderAddress = senderAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.setSignatureValidatorApproval.callAsync(validatorAddress, isApproved, { - from: normalizedSenderAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.setSignatureValidatorApproval.sendTransactionAsync( - validatorAddress, - isApproved, - { - from: normalizedSenderAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch - * and senderAddress equal to msg.sender (or null address if msg.sender == makerAddress). - * @param targetOrderEpoch Target order epoch. - * @param senderAddress Address that should send the transaction. - * @param orderTransactionOpts Optional arguments this method accepts. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async cancelOrdersUpToAsync( - targetOrderEpoch: BigNumber, - senderAddress: string, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - assert.isBigNumber('targetOrderEpoch', targetOrderEpoch); - await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - const normalizedSenderAddress = senderAddress.toLowerCase(); - - const exchangeInstance = await this._getExchangeContractAsync(); - if (orderTransactionOpts.shouldValidate) { - await exchangeInstance.cancelOrdersUpTo.callAsync(targetOrderEpoch, { - from: normalizedSenderAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - } - const txHash = await exchangeInstance.cancelOrdersUpTo.sendTransactionAsync(targetOrderEpoch, { - from: normalizedSenderAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }); - return txHash; - } - /** - * Subscribe to an event type emitted by the Exchange contract. - * @param eventName The exchange contract event you would like to subscribe to. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{maker: aUserAddressHex}` - * @param callback Callback that gets called when a log is added/removed - * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered) - * @return Subscription token used later to unsubscribe - */ - public subscribe<ArgsType extends ExchangeEventArgs>( - eventName: ExchangeEvents, - indexFilterValues: IndexedFilterValues, - callback: EventCallback<ArgsType>, - isVerbose: boolean = false, - ): string { - assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - assert.isFunction('callback', callback); - const subscriptionToken = this._subscribe<ArgsType>( - this.address, - eventName, - indexFilterValues, - Exchange.compilerOutput.abi, - callback, - isVerbose, - ); - return subscriptionToken; - } - /** - * Cancel a subscription - * @param subscriptionToken Subscription token returned by `subscribe()` - */ - public unsubscribe(subscriptionToken: string): void { - this._unsubscribe(subscriptionToken); - } - /** - * Cancels all existing subscriptions - */ - public unsubscribeAll(): void { - super._unsubscribeAll(); - } - /** - * Gets historical logs without creating a subscription - * @param eventName The exchange contract event you would like to subscribe to. - * @param blockRange Block range to get logs from. - * @param indexFilterValues An object where the keys are indexed args returned by the event and - * the value is the value you are interested in. E.g `{_from: aUserAddressHex}` - * @return Array of logs that match the parameters - */ - public async getLogsAsync<ArgsType extends ExchangeEventArgs>( - eventName: ExchangeEvents, - blockRange: BlockRange, - indexFilterValues: IndexedFilterValues, - ): Promise<Array<LogWithDecodedArgs<ArgsType>>> { - assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); - assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); - assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - const logs = await this._getLogsAsync<ArgsType>( - this.address, - eventName, - blockRange, - indexFilterValues, - Exchange.compilerOutput.abi, - ); - 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> { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.doesConformToSchema('opts', opts, validateOrderFillableOptsSchema); - - 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, this._web3Wrapper.getProvider()); - 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, this._web3Wrapper.getProvider()); - await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( - exchangeTradeSimulator, - this._web3Wrapper.getProvider(), - signedOrder, - fillTakerAssetAmount, - takerAddress, - this.getZRXAssetData(), - ); - } - /** - * Returns the ZRX asset data used by the exchange contract. - * @return ZRX asset data - */ - public getZRXAssetData(): string { - const zrxAssetData = assetDataUtils.encodeERC20AssetData(this.zrxTokenAddress); - return zrxAssetData; - } - /** - * Returns a Transaction Encoder. Transaction messages exist for the purpose of calling methods on the Exchange contract - * in the context of another address. - * @return TransactionEncoder - */ - public async transactionEncoderAsync(): Promise<TransactionEncoder> { - const exchangeInstance = await this._getExchangeContractAsync(); - const encoder = new TransactionEncoder(exchangeInstance); - return encoder; - } - // tslint:enable:no-unused-variable - private async _getExchangeContractAsync(): Promise<ExchangeContract> { - if (!_.isUndefined(this._exchangeContractIfExists)) { - return this._exchangeContractIfExists; - } - const contractInstance = new ExchangeContract( - this.abi, - this.address, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - this._exchangeContractIfExists = contractInstance; - return this._exchangeContractIfExists; - } -} // tslint:disable:max-file-line-count diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts deleted file mode 100644 index 5497f92b5..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts +++ /dev/null @@ -1,254 +0,0 @@ -import { ForwarderContract } from '@0x/abi-gen-wrappers'; -import { Forwarder } from '@0x/contract-artifacts'; -import { schemas } from '@0x/json-schemas'; -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { ContractAbi } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema'; -import { txOptsSchema } from '../schemas/tx_opts_schema'; -import { OrderTransactionOpts } from '../types'; -import { assert } from '../utils/assert'; -import { calldataOptimizationUtils } from '../utils/calldata_optimization_utils'; -import { constants } from '../utils/constants'; -import { _getDefaultContractAddresses } from '../utils/contract_addresses'; -import { decorators } from '../utils/decorators'; -import { utils } from '../utils/utils'; - -import { ContractWrapper } from './contract_wrapper'; - -/** - * This class includes the functionality related to interacting with the Forwarder contract. - */ -export class ForwarderWrapper extends ContractWrapper { - public abi: ContractAbi = Forwarder.compilerOutput.abi; - public address: string; - public zrxTokenAddress: string; - public etherTokenAddress: string; - private _forwarderContractIfExists?: ForwarderContract; - - /** - * Instantiate ForwarderWrapper - * @param web3Wrapper Web3Wrapper instance to use. - * @param networkId Desired networkId. - * @param address The address of the Exchange contract. If undefined, will - * default to the known address corresponding to the networkId. - * @param zrxTokenAddress The address of the ZRXToken contract. If - * undefined, will default to the known address corresponding to the - * networkId. - * @param etherTokenAddress The address of a WETH (Ether token) contract. If - * undefined, will default to the known address corresponding to the - * networkId. - */ - constructor( - web3Wrapper: Web3Wrapper, - networkId: number, - address?: string, - zrxTokenAddress?: string, - etherTokenAddress?: string, - ) { - super(web3Wrapper, networkId); - this.address = _.isUndefined(address) ? _getDefaultContractAddresses(networkId).exchange : address; - this.zrxTokenAddress = _.isUndefined(zrxTokenAddress) - ? _getDefaultContractAddresses(networkId).zrxToken - : zrxTokenAddress; - this.etherTokenAddress = _.isUndefined(etherTokenAddress) - ? _getDefaultContractAddresses(networkId).etherToken - : etherTokenAddress; - } - /** - * Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value. - * Any ZRX required to pay fees for primary orders will automatically be purchased by this contract. - * 5% of ETH value is reserved for paying fees to order feeRecipients (in ZRX) and forwarding contract feeRecipient (in ETH). - * Any ETH not spent will be refunded to sender. - * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders must specify the same makerAsset. - * All orders must specify WETH as the takerAsset - * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied - * Provider provided at instantiation. - * @param ethAmount The amount of eth to send with the transaction (in wei). - * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders must specify ZRX as makerAsset and WETH as takerAsset. - * Used to purchase ZRX for primary order fees. - * @param feePercentage The percentage of WETH sold that will payed as fee to forwarding contract feeRecipient. - * Defaults to 0. - * @param feeRecipientAddress The address that will receive ETH when signedFeeOrders are filled. - * @param orderTransactionOpts Transaction parameters. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async marketSellOrdersWithEthAsync( - signedOrders: SignedOrder[], - takerAddress: string, - ethAmount: BigNumber, - signedFeeOrders: SignedOrder[] = [], - feePercentage: number = 0, - feeRecipientAddress: string = constants.NULL_ADDRESS, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - // type assertions - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.isBigNumber('ethAmount', ethAmount); - assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); - assert.isNumber('feePercentage', feePercentage); - assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - // other assertions - assert.ordersCanBeUsedForForwarderContract(signedOrders, this.etherTokenAddress); - assert.feeOrdersCanBeUsedForForwarderContract(signedFeeOrders, this.zrxTokenAddress, this.etherTokenAddress); - // format feePercentage - const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage); - // lowercase input addresses - const normalizedTakerAddress = takerAddress.toLowerCase(); - const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); - // optimize orders - const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders); - const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders); - // compile signatures - const signatures = _.map(optimizedMarketOrders, order => order.signature); - const feeSignatures = _.map(optimizedFeeOrders, order => order.signature); - // get contract - const forwarderContractInstance = await this._getForwarderContractAsync(); - // validate transaction - if (orderTransactionOpts.shouldValidate) { - await forwarderContractInstance.marketSellOrdersWithEth.callAsync( - optimizedMarketOrders, - signatures, - optimizedFeeOrders, - feeSignatures, - formattedFeePercentage, - normalizedFeeRecipientAddress, - { - value: ethAmount, - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - } - // send transaction - const txHash = await forwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync( - optimizedMarketOrders, - signatures, - optimizedFeeOrders, - feeSignatures, - formattedFeePercentage, - feeRecipientAddress, - { - value: ethAmount, - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - /** - * Attempt to purchase makerAssetFillAmount of makerAsset by selling ethAmount provided with transaction. - * Any ZRX required to pay fees for primary orders will automatically be purchased by the contract. - * Any ETH not spent will be refunded to sender. - * @param signedOrders An array of objects that conform to the SignedOrder interface. All orders must specify the same makerAsset. - * All orders must specify WETH as the takerAsset - * @param makerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. - * @param takerAddress The user Ethereum address who would like to fill this order. Must be available via the supplied - * Provider provided at instantiation. - * @param ethAmount The amount of eth to send with the transaction (in wei). - * @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders must specify ZRX as makerAsset and WETH as takerAsset. - * Used to purchase ZRX for primary order fees. - * @param feePercentage The percentage of WETH sold that will payed as fee to forwarding contract feeRecipient. - * Defaults to 0. - * @param feeRecipientAddress The address that will receive ETH when signedFeeOrders are filled. - * @param orderTransactionOpts Transaction parameters. - * @return Transaction hash. - */ - @decorators.asyncZeroExErrorHandler - public async marketBuyOrdersWithEthAsync( - signedOrders: SignedOrder[], - makerAssetFillAmount: BigNumber, - takerAddress: string, - ethAmount: BigNumber, - signedFeeOrders: SignedOrder[] = [], - feePercentage: number = 0, - feeRecipientAddress: string = constants.NULL_ADDRESS, - orderTransactionOpts: OrderTransactionOpts = { shouldValidate: true }, - ): Promise<string> { - // type assertions - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); - await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); - assert.isBigNumber('ethAmount', ethAmount); - assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema); - assert.isNumber('feePercentage', feePercentage); - assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress); - assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); - // other assertions - assert.ordersCanBeUsedForForwarderContract(signedOrders, this.etherTokenAddress); - assert.feeOrdersCanBeUsedForForwarderContract(signedFeeOrders, this.zrxTokenAddress, this.etherTokenAddress); - // format feePercentage - const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage); - // lowercase input addresses - const normalizedTakerAddress = takerAddress.toLowerCase(); - const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase(); - // optimize orders - const optimizedMarketOrders = calldataOptimizationUtils.optimizeForwarderOrders(signedOrders); - const optimizedFeeOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(signedFeeOrders); - // compile signatures - const signatures = _.map(optimizedMarketOrders, order => order.signature); - const feeSignatures = _.map(optimizedFeeOrders, order => order.signature); - // get contract - const forwarderContractInstance = await this._getForwarderContractAsync(); - // validate transaction - if (orderTransactionOpts.shouldValidate) { - await forwarderContractInstance.marketBuyOrdersWithEth.callAsync( - optimizedMarketOrders, - makerAssetFillAmount, - signatures, - optimizedFeeOrders, - feeSignatures, - formattedFeePercentage, - normalizedFeeRecipientAddress, - { - value: ethAmount, - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - } - // send transaction - const txHash = await forwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync( - optimizedMarketOrders, - makerAssetFillAmount, - signatures, - optimizedFeeOrders, - feeSignatures, - formattedFeePercentage, - feeRecipientAddress, - { - value: ethAmount, - from: normalizedTakerAddress, - gas: orderTransactionOpts.gasLimit, - gasPrice: orderTransactionOpts.gasPrice, - nonce: orderTransactionOpts.nonce, - }, - ); - return txHash; - } - private async _getForwarderContractAsync(): Promise<ForwarderContract> { - if (!_.isUndefined(this._forwarderContractIfExists)) { - return this._forwarderContractIfExists; - } - const contractInstance = new ForwarderContract( - this.abi, - this.address, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - this._forwarderContractIfExists = contractInstance; - return this._forwarderContractIfExists; - } -} diff --git a/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts deleted file mode 100644 index c186e080e..000000000 --- a/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { OrderValidatorContract } from '@0x/abi-gen-wrappers'; -import { OrderValidator } from '@0x/contract-artifacts'; -import { schemas } from '@0x/json-schemas'; -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { ContractAbi } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { BalanceAndAllowance, OrderAndTraderInfo, TraderInfo } from '../types'; -import { assert } from '../utils/assert'; -import { _getDefaultContractAddresses } from '../utils/contract_addresses'; - -import { ContractWrapper } from './contract_wrapper'; - -/** - * This class includes the functionality related to interacting with the OrderValidator contract. - */ -export class OrderValidatorWrapper extends ContractWrapper { - public abi: ContractAbi = OrderValidator.compilerOutput.abi; - public address: string; - private _orderValidatorContractIfExists?: OrderValidatorContract; - /** - * Instantiate OrderValidatorWrapper - * @param web3Wrapper Web3Wrapper instance to use. - * @param networkId Desired networkId. - * @param address The address of the OrderValidator contract. If undefined, - * will default to the known address corresponding to the networkId. - */ - constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { - super(web3Wrapper, networkId); - this.address = _.isUndefined(address) ? _getDefaultContractAddresses(networkId).exchange : address; - } - /** - * 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; - } - private async _getOrderValidatorContractAsync(): Promise<OrderValidatorContract> { - if (!_.isUndefined(this._orderValidatorContractIfExists)) { - return this._orderValidatorContractIfExists; - } - const contractInstance = new OrderValidatorContract( - this.abi, - this.address, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - this._orderValidatorContractIfExists = contractInstance; - return this._orderValidatorContractIfExists; - } -} diff --git a/packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts b/packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts deleted file mode 100644 index c35b24664..000000000 --- a/packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0x/order-utils'; -import { BigNumber } from '@0x/utils'; -import { BlockParamLiteral } from 'ethereum-types'; -import * as _ from 'lodash'; - -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; - private readonly _erc721Token: ERC721TokenWrapper; - private readonly _stateLayer: BlockParamLiteral; - constructor(erc20Token: ERC20TokenWrapper, erc721Token: ERC721TokenWrapper, stateLayer: BlockParamLiteral) { - this._erc20Token = erc20Token; - this._erc721Token = erc721Token; - this._stateLayer = stateLayer; - } - public async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber> { - const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); - let balance: BigNumber | undefined; - if (assetDataUtils.isERC20AssetData(decodedAssetData)) { - balance = await this._erc20Token.getBalanceAsync(decodedAssetData.tokenAddress, userAddress, { - defaultBlock: this._stateLayer, - }); - } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) { - const tokenOwner = await this._erc721Token.getOwnerOfAsync( - decodedAssetData.tokenAddress, - decodedAssetData.tokenId, - { - defaultBlock: this._stateLayer, - }, - ); - balance = tokenOwner === userAddress ? new BigNumber(1) : new BigNumber(0); - } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { - // The `balance` for MultiAssetData is the total units of the entire `assetData` that are held by the `userAddress`. - for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) { - const nestedAmountElement = decodedAssetData.amounts[index]; - const nestedAssetBalance = (await this.getBalanceAsync( - nestedAssetDataElement, - userAddress, - )).dividedToIntegerBy(nestedAmountElement); - if (_.isUndefined(balance) || nestedAssetBalance.isLessThan(balance)) { - balance = nestedAssetBalance; - } - } - } - return balance as BigNumber; - } - public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber> { - const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); - let proxyAllowance: BigNumber | undefined; - if (assetDataUtils.isERC20AssetData(decodedAssetData)) { - proxyAllowance = await this._erc20Token.getProxyAllowanceAsync(decodedAssetData.tokenAddress, userAddress, { - defaultBlock: this._stateLayer, - }); - } else if (assetDataUtils.isERC721AssetData(decodedAssetData)) { - const isApprovedForAll = await this._erc721Token.isProxyApprovedForAllAsync( - decodedAssetData.tokenAddress, - userAddress, - { - defaultBlock: this._stateLayer, - }, - ); - if (isApprovedForAll) { - return new BigNumber(this._erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); - } else { - const isApproved = await this._erc721Token.isProxyApprovedAsync( - decodedAssetData.tokenAddress, - decodedAssetData.tokenId, - { - defaultBlock: this._stateLayer, - }, - ); - proxyAllowance = isApproved ? new BigNumber(1) : new BigNumber(0); - } - } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { - // The `proxyAllowance` for MultiAssetData is the total units of the entire `assetData` that the proxies have been approved to spend by the `userAddress`. - for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) { - const nestedAmountElement = decodedAssetData.amounts[index]; - const nestedAssetAllowance = (await this.getProxyAllowanceAsync( - nestedAssetDataElement, - userAddress, - )).dividedToIntegerBy(nestedAmountElement); - if (_.isUndefined(proxyAllowance) || nestedAssetAllowance.isLessThan(proxyAllowance)) { - proxyAllowance = nestedAssetAllowance; - } - } - } - return proxyAllowance as BigNumber; - } -} diff --git a/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts b/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts deleted file mode 100644 index 5d350916c..000000000 --- a/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts +++ /dev/null @@ -1,39 +0,0 @@ -// tslint:disable:no-unnecessary-type-assertion -import { AbstractOrderFilledCancelledFetcher, orderHashUtils } from '@0x/order-utils'; -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { BlockParamLiteral } from 'ethereum-types'; - -import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; - -export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher { - private readonly _exchange: ExchangeWrapper; - private readonly _stateLayer: BlockParamLiteral; - constructor(exchange: ExchangeWrapper, stateLayer: BlockParamLiteral) { - this._exchange = exchange; - this._stateLayer = stateLayer; - } - public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> { - const filledTakerAmount = this._exchange.getFilledTakerAssetAmountAsync(orderHash, { - defaultBlock: this._stateLayer, - }); - return filledTakerAmount; - } - public async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean> { - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - const isCancelled = await this._exchange.isCancelledAsync(orderHash); - const orderEpoch = await this._exchange.getOrderEpochAsync( - signedOrder.makerAddress, - signedOrder.senderAddress, - { - defaultBlock: this._stateLayer, - }, - ); - const isCancelledByOrderEpoch = orderEpoch > signedOrder.salt; - return isCancelled || isCancelledByOrderEpoch; - } - public getZRXAssetData(): string { - const zrxAssetData = this._exchange.getZRXAssetData(); - return zrxAssetData; - } -} diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts deleted file mode 100644 index 69bbe3c91..000000000 --- a/packages/contract-wrappers/src/index.ts +++ /dev/null @@ -1,101 +0,0 @@ -export { ContractAddresses } from '@0x/contract-addresses'; - -export { - WETH9Events, - WETH9WithdrawalEventArgs, - WETH9ApprovalEventArgs, - WETH9EventArgs, - WETH9DepositEventArgs, - WETH9TransferEventArgs, - ERC20TokenTransferEventArgs, - ERC20TokenApprovalEventArgs, - ERC20TokenEvents, - ERC20TokenEventArgs, - ERC721TokenApprovalEventArgs, - ERC721TokenApprovalForAllEventArgs, - ERC721TokenTransferEventArgs, - ERC721TokenEvents, - ERC721TokenEventArgs, - ExchangeCancelUpToEventArgs, - ExchangeAssetProxyRegisteredEventArgs, - ExchangeSignatureValidatorApprovalEventArgs, - ExchangeFillEventArgs, - ExchangeCancelEventArgs, - ExchangeEventArgs, - ExchangeEvents, -} from '@0x/abi-gen-wrappers'; - -export { ContractWrappers } from './contract_wrappers'; -export { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper'; -export { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper'; -export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; -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 { DutchAuctionWrapper } from './contract_wrappers/dutch_auction_wrapper'; - -export { TransactionEncoder } from './utils/transaction_encoder'; - -export { - ContractWrappersError, - ForwarderWrapperError, - IndexedFilterValues, - BlockRange, - ContractWrappersConfig, - MethodOpts, - OrderTransactionOpts, - TransactionOpts, - OrderStatus, - OrderInfo, - EventCallback, - DecodedLogEvent, - BalanceAndAllowance, - OrderAndTraderInfo, - TraderInfo, - ValidateOrderFillableOpts, - DutchAuctionData, -} from './types'; - -export { - AssetData, - ERC20AssetData, - ERC721AssetData, - SingleAssetData, - MultiAssetData, - MultiAssetDataWithRecursiveDecoding, - DutchAuctionDetails, - Order, - SignedOrder, - AssetProxyId, -} from '@0x/types'; - -export { - BlockParamLiteral, - BlockParam, - ContractEventArg, - Provider, - ContractAbi, - JSONRPCRequestPayload, - JSONRPCResponsePayload, - JSONRPCErrorCallback, - JSONRPCResponseError, - AbiDefinition, - LogWithDecodedArgs, - FunctionAbi, - EventAbi, - EventParameter, - DecodedLogArgs, - MethodAbi, - ConstructorAbi, - FallbackAbi, - DataItem, - ConstructorStateMutability, - StateMutability, -} from 'ethereum-types'; - -export { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher } from '@0x/order-utils'; - -export { AssetBalanceAndProxyAllowanceFetcher } from './fetchers/asset_balance_and_proxy_allowance_fetcher'; -export { OrderFilledCancelledFetcher } from './fetchers/order_filled_cancelled_fetcher'; diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_config_schema.ts deleted file mode 100644 index ae1ce668c..000000000 --- a/packages/contract-wrappers/src/schemas/contract_wrappers_config_schema.ts +++ /dev/null @@ -1,25 +0,0 @@ -export const ContractWrappersConfigSchema = { - id: '/ContractWrappersConfig', - properties: { - networkId: { - type: 'number', - }, - gasPrice: { $ref: '/numberSchema' }, - contractAddresses: { - type: 'object', - properties: { - erc20Proxy: { $ref: '/addressSchema' }, - erc721Proxy: { $ref: '/addressSchema' }, - zrxToken: { $ref: '/addressSchema' }, - etherToken: { $ref: '/addressSchema' }, - exchange: { $ref: '/addressSchema' }, - assetProxyOwner: { $ref: '/addressSchema' }, - forwarder: { $ref: '/addressSchema' }, - orderValidator: { $ref: '/addressSchema' }, - }, - }, - blockPollingIntervalMs: { type: 'number' }, - }, - type: 'object', - required: ['networkId'], -}; diff --git a/packages/contract-wrappers/src/schemas/method_opts_schema.ts b/packages/contract-wrappers/src/schemas/method_opts_schema.ts deleted file mode 100644 index 83003f818..000000000 --- a/packages/contract-wrappers/src/schemas/method_opts_schema.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const methodOptsSchema = { - id: '/MethodOpts', - properties: { - defaultBlock: { $ref: '/blockParamSchema' }, - }, - type: 'object', -}; diff --git a/packages/contract-wrappers/src/schemas/order_tx_opts_schema.ts b/packages/contract-wrappers/src/schemas/order_tx_opts_schema.ts deleted file mode 100644 index 31ad759d5..000000000 --- a/packages/contract-wrappers/src/schemas/order_tx_opts_schema.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const orderTxOptsSchema = { - id: '/OrderTxOpts', - allOf: [{ $ref: '/TxOpts' }], - properties: { - shouldValidate: { type: 'boolean' }, - }, - type: 'object', -}; diff --git a/packages/contract-wrappers/src/schemas/tx_opts_schema.ts b/packages/contract-wrappers/src/schemas/tx_opts_schema.ts deleted file mode 100644 index 1c1588db7..000000000 --- a/packages/contract-wrappers/src/schemas/tx_opts_schema.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const txOptsSchema = { - id: '/TxOpts', - properties: { - gasPrice: { $ref: '/numberSchema' }, - gasLimit: { type: 'number' }, - nonce: { type: 'number' }, - }, - type: 'object', -}; diff --git a/packages/contract-wrappers/src/schemas/validate_order_fillable_opts_schema.ts b/packages/contract-wrappers/src/schemas/validate_order_fillable_opts_schema.ts deleted file mode 100644 index 2e111af04..000000000 --- a/packages/contract-wrappers/src/schemas/validate_order_fillable_opts_schema.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const validateOrderFillableOptsSchema = { - id: '/ValidateOrderFillableOpts', - properties: { - expectedFillTakerTokenAmount: { $ref: '/wholeNumberSchema' }, - }, - type: 'object', -}; diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts deleted file mode 100644 index 29cf8b2c4..000000000 --- a/packages/contract-wrappers/src/types.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { - ERC20TokenEventArgs, - ERC20TokenEvents, - ERC721TokenEventArgs, - ERC721TokenEvents, - ExchangeEventArgs, - ExchangeEvents, - WETH9EventArgs, - WETH9Events, -} from '@0x/abi-gen-wrappers'; -import { ContractAddresses } from '@0x/contract-addresses'; -import { AssetData, OrderState, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -import { BlockParam, ContractEventArg, DecodedLogArgs, LogEntryEvent, LogWithDecodedArgs } from 'ethereum-types'; - -export enum ExchangeWrapperError { - AssetDataMismatch = 'ASSET_DATA_MISMATCH', -} - -export enum ForwarderWrapperError { - CompleteFillFailed = 'COMPLETE_FILL_FAILED', -} - -export enum ContractWrappersError { - ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK', - InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER', - InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER', - InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT', - InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL', - InvalidJump = 'INVALID_JUMP', - OutOfGas = 'OUT_OF_GAS', - SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND', - SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT', - ERC721OwnerNotFound = 'ERC_721_OWNER_NOT_FOUND', - ERC721NoApproval = 'ERC_721_NO_APPROVAL', - SignatureRequestDenied = 'SIGNATURE_REQUEST_DENIED', -} - -export enum InternalContractWrappersError { - NoAbiDecoder = 'NO_ABI_DECODER', -} - -export type LogEvent = LogEntryEvent; -export interface DecodedLogEvent<ArgsType extends DecodedLogArgs> { - isRemoved: boolean; - log: LogWithDecodedArgs<ArgsType>; -} - -export type EventCallback<ArgsType extends DecodedLogArgs> = ( - err: null | Error, - log?: DecodedLogEvent<ArgsType>, -) => void; - -export interface ContractEvent { - logIndex: number; - transactionIndex: number; - transactionHash: string; - blockHash: string; - blockNumber: number; - address: string; - type: string; - event: string; - args: ContractEventArgs; -} - -export type ContractEventArgs = ExchangeEventArgs | ERC20TokenEventArgs | ERC721TokenEventArgs | WETH9EventArgs; - -// [address, name, symbol, decimals, ipfsHash, swarmHash] -export type TokenMetadata = [string, string, string, number, string, string]; - -export interface Token { - name: string; - address: string; - symbol: string; - decimals: number; -} - -export interface TxOpts { - from: string; - gas?: number; - value?: BigNumber; - gasPrice?: BigNumber; -} - -export interface TokenAddressBySymbol { - [symbol: string]: string; -} - -export type ContractEvents = ERC20TokenEvents | ERC721TokenEvents | ExchangeEvents | WETH9Events; - -export interface IndexedFilterValues { - [index: string]: ContractEventArg; -} - -export interface BlockRange { - fromBlock: BlockParam; - toBlock: BlockParam; -} - -export interface OrderFillRequest { - signedOrder: SignedOrder; - takerAssetFillAmount: BigNumber; -} - -export type AsyncMethod = (...args: any[]) => Promise<any>; -export type SyncMethod = (...args: any[]) => any; - -/** - * networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 3-ropsten, 4-rinkeby, 42-kovan, 50-testrpc) - * gasPrice: Gas price to use with every transaction - * contractAddresses: The address of all contracts to use. Defaults to the known addresses based on networkId. - * blockPollingIntervalMs: The interval to use for block polling in event watching methods (defaults to 1000) - */ -export interface ContractWrappersConfig { - networkId: number; - gasPrice?: BigNumber; - contractAddresses?: ContractAddresses; - blockPollingIntervalMs?: number; -} - -/** - * expectedFillTakerTokenAmount: If specified, the validation method will ensure that the - * supplied order maker has a sufficient allowance/balance to fill this amount of the order's - * takerTokenAmount. If not specified, the validation method ensures that the maker has a sufficient - * allowance/balance to fill the entire remaining order amount. - */ -export interface ValidateOrderFillableOpts { - expectedFillTakerTokenAmount?: BigNumber; -} - -/** - * defaultBlock: The block up to which to query the blockchain state. Setting this to a historical block number - * let's the user query the blockchain's state at an arbitrary point in time. In order for this to work, the - * backing Ethereum node must keep the entire historical state of the chain (e.g setting `--pruning=archive` - * flag when running Parity). - */ -export interface MethodOpts { - defaultBlock?: BlockParam; -} - -/** - * gasPrice: Gas price in Wei to use for a transaction - * gasLimit: The amount of gas to send with a transaction (in Gwei) - * nonce: The nonce to use for a transaction. If not specified, it defaults to the next incremented nonce. - */ -export interface TransactionOpts { - gasPrice?: BigNumber; - gasLimit?: number; - nonce?: number; -} - -/** - * shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before - * broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default=true. - */ -export interface OrderTransactionOpts extends TransactionOpts { - shouldValidate?: boolean; -} - -export enum TradeSide { - Maker = 'maker', - Taker = 'taker', -} - -export enum TransferType { - Trade = 'trade', - Fee = 'fee', -} - -export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void; - -export interface OrderInfo { - orderStatus: OrderStatus; - orderHash: string; - orderTakerAssetFilledAmount: BigNumber; -} - -export enum OrderStatus { - Invalid = 0, - InvalidMakerAssetAmount, - InvalidTakerAssetAmount, - Fillable, - Expired, - FullyFilled, - 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; -} - -export enum DutchAuctionWrapperError { - AssetDataMismatch = 'ASSET_DATA_MISMATCH', -} - -export interface DutchAuctionData { - assetData: AssetData; - beginTimeSeconds: BigNumber; - beginAmount: BigNumber; -} diff --git a/packages/contract-wrappers/src/utils/assert.ts b/packages/contract-wrappers/src/utils/assert.ts deleted file mode 100644 index d30c6b29c..000000000 --- a/packages/contract-wrappers/src/utils/assert.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { assert as sharedAssert } from '@0x/assert'; -// HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here -import { Schema } from '@0x/json-schemas'; // tslint:disable-line:no-unused-variable -import { assetDataUtils, signatureUtils } from '@0x/order-utils'; -import { Order } from '@0x/types'; // tslint:disable-line:no-unused-variable -import { BigNumber } from '@0x/utils'; // tslint:disable-line:no-unused-variable -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { constants } from './constants'; - -export const assert = { - ...sharedAssert, - async isValidSignatureAsync( - provider: Provider, - orderHash: string, - signature: string, - signerAddress: string, - ): Promise<void> { - const isValid = await signatureUtils.isValidSignatureAsync(provider, orderHash, signature, signerAddress); - sharedAssert.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`); - }, - isValidSubscriptionToken(variableName: string, subscriptionToken: string): void { - const uuidRegex = new RegExp('^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$'); - const isValid = uuidRegex.test(subscriptionToken); - sharedAssert.assert(isValid, `Expected ${variableName} to be a valid subscription token`); - }, - async isSenderAddressAsync( - variableName: string, - senderAddressHex: string, - web3Wrapper: Web3Wrapper, - ): Promise<void> { - sharedAssert.isETHAddressHex(variableName, senderAddressHex); - const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex); - sharedAssert.assert( - isSenderAddressAvailable, - `Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`, - ); - }, - ordersCanBeUsedForForwarderContract(orders: Order[], etherTokenAddress: string): void { - sharedAssert.assert(!_.isEmpty(orders), 'Expected at least 1 signed order. Found no orders'); - assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'makerAssetData'); - assert.allTakerAssetDatasAreErc20Token(orders, etherTokenAddress); - assert.allTakerAddressesAreNull(orders); - }, - feeOrdersCanBeUsedForForwarderContract(orders: Order[], zrxTokenAddress: string, etherTokenAddress: string): void { - if (!_.isEmpty(orders)) { - assert.allMakerAssetDatasAreErc20Token(orders, zrxTokenAddress); - assert.allTakerAssetDatasAreErc20Token(orders, etherTokenAddress); - } - }, - allTakerAddressesAreNull(orders: Order[]): void { - assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'takerAddress', constants.NULL_ADDRESS); - }, - allMakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void { - assert.ordersHaveAtMostOneUniqueValueForProperty( - orders, - 'makerAssetData', - assetDataUtils.encodeERC20AssetData(tokenAddress), - ); - }, - allTakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void { - assert.ordersHaveAtMostOneUniqueValueForProperty( - orders, - 'takerAssetData', - assetDataUtils.encodeERC20AssetData(tokenAddress), - ); - }, - /* - * Asserts that all the orders have the same value for the provided propertyName - * If the value parameter is provided, this asserts that all orders have the prope - */ - ordersHaveAtMostOneUniqueValueForProperty(orders: Order[], propertyName: string, value?: any): void { - const allValues = _.map(orders, order => _.get(order, propertyName)); - sharedAssert.hasAtMostOneUniqueValue( - allValues, - `Expected all orders to have the same ${propertyName} field. Found the following ${propertyName} values: ${JSON.stringify( - allValues, - )}`, - ); - if (!_.isUndefined(value)) { - const firstValue = _.head(allValues); - sharedAssert.assert( - firstValue === value, - `Expected all orders to have a ${propertyName} field with value: ${value}. Found: ${firstValue}`, - ); - } - }, -}; diff --git a/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts b/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts deleted file mode 100644 index bee7acaa7..000000000 --- a/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { SignedOrder } from '@0x/types'; -import * as _ from 'lodash'; - -import { constants } from './constants'; - -export const calldataOptimizationUtils = { - /** - * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and - * all makerAssetData are '0x' except for that of the first order, which retains its original value - * @param orders An array of SignedOrder objects - * @returns optimized orders - */ - optimizeForwarderOrders(orders: SignedOrder[]): SignedOrder[] { - const optimizedOrders = _.map(orders, (order, index) => - transformOrder(order, { - makerAssetData: index === 0 ? order.makerAssetData : constants.NULL_BYTES, - takerAssetData: constants.NULL_BYTES, - }), - ); - return optimizedOrders; - }, - /** - * Takes an array of orders and outputs an array of equivalent orders where all takerAssetData are '0x' and - * all makerAssetData are '0x' - * @param orders An array of SignedOrder objects - * @returns optimized orders - */ - optimizeForwarderFeeOrders(orders: SignedOrder[]): SignedOrder[] { - const optimizedOrders = _.map(orders, (order, index) => - transformOrder(order, { - makerAssetData: constants.NULL_BYTES, - takerAssetData: constants.NULL_BYTES, - }), - ); - return optimizedOrders; - }, -}; - -const transformOrder = (order: SignedOrder, partialOrder: Partial<SignedOrder>) => { - return { - ...order, - ...partialOrder, - }; -}; diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts deleted file mode 100644 index 94afdc112..000000000 --- a/packages/contract-wrappers/src/utils/constants.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -export const constants = { - NULL_ADDRESS: '0x0000000000000000000000000000000000000000', - NULL_BYTES: '0x', - TESTRPC_NETWORK_ID: 50, - INVALID_JUMP_PATTERN: 'invalid JUMP at', - REVERT: 'revert', - OUT_OF_GAS_PATTERN: 'out of gas', - INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string', - // tslint:disable-next-line:custom-no-magic-numbers - 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, - METAMASK_USER_DENIED_SIGNATURE_PATTERN: 'User denied transaction signature', - TRUST_WALLET_USER_DENIED_SIGNATURE_PATTERN: 'cancelled', -}; diff --git a/packages/contract-wrappers/src/utils/contract_addresses.ts b/packages/contract-wrappers/src/utils/contract_addresses.ts deleted file mode 100644 index dc156e017..000000000 --- a/packages/contract-wrappers/src/utils/contract_addresses.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ContractAddresses, getContractAddressesForNetworkOrThrow, NetworkId } from '@0x/contract-addresses'; -import * as _ from 'lodash'; - -/** - * Returns the default contract addresses for the given networkId or throws with - * a context-specific error message if the networkId is not recognized. - */ -export function _getDefaultContractAddresses(networkId: number): ContractAddresses { - if (!(networkId in NetworkId)) { - throw new Error( - `No default contract addresses found for the given network id (${networkId}). If you want to use ContractWrappers on this network, you must manually pass in the contract address(es) to the constructor.`, - ); - } - return getContractAddressesForNetworkOrThrow(networkId); -} diff --git a/packages/contract-wrappers/src/utils/decorators.ts b/packages/contract-wrappers/src/utils/decorators.ts deleted file mode 100644 index 3acfa3a88..000000000 --- a/packages/contract-wrappers/src/utils/decorators.ts +++ /dev/null @@ -1,110 +0,0 @@ -import * as _ from 'lodash'; - -import { AsyncMethod, ContractWrappersError, SyncMethod } from '../types'; - -import { constants } from './constants'; - -type ErrorTransformer = (err: Error) => Error; - -const contractCallErrorTransformer = (error: Error) => { - if (_.includes(error.message, constants.INVALID_JUMP_PATTERN)) { - return new Error(ContractWrappersError.InvalidJump); - } - if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) { - return new Error(ContractWrappersError.OutOfGas); - } - if (_.includes(error.message, constants.REVERT)) { - const revertReason = error.message.split(constants.REVERT)[1].trim(); - return new Error(revertReason); - } - return error; -}; - -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 NULL_ADDRESS'; - return new Error(errMsg); - } - return error; -}; - -const signatureRequestErrorTransformer = (error: Error) => { - if ( - _.includes(error.message, constants.METAMASK_USER_DENIED_SIGNATURE_PATTERN) || - _.includes(error.message, constants.TRUST_WALLET_USER_DENIED_SIGNATURE_PATTERN) - ) { - const errMsg = ContractWrappersError.SignatureRequestDenied; - return new Error(errMsg); - } - return error; -}; - -/** - * Source: https://stackoverflow.com/a/29837695/3546986 - */ -const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => { - const asyncErrorHandlingDecorator = ( - _target: object, - _key: string | symbol, - descriptor: TypedPropertyDescriptor<AsyncMethod>, - ) => { - const originalMethod = descriptor.value as AsyncMethod; - - // Do not use arrow syntax here. Use a function expression in - // order to use the correct value of `this` in this method - // tslint:disable-next-line:only-arrow-functions - descriptor.value = async function(...args: any[]): Promise<any> { - try { - const result = await originalMethod.apply(this, args); // tslint:disable-line:no-invalid-this - return result; - } catch (error) { - const transformedError = errorTransformer(error); - throw transformedError; - } - }; - - return descriptor; - }; - - return asyncErrorHandlingDecorator; -}; - -const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => { - const syncErrorHandlingDecorator = ( - _target: object, - _key: string | symbol, - descriptor: TypedPropertyDescriptor<SyncMethod>, - ) => { - const originalMethod = descriptor.value as SyncMethod; - - // Do not use arrow syntax here. Use a function expression in - // order to use the correct value of `this` in this method - // tslint:disable-next-line:only-arrow-functions - descriptor.value = function(...args: any[]): any { - try { - const result = originalMethod.apply(this, args); // tslint:disable-line:no-invalid-this - return result; - } catch (error) { - const transformedError = errorTransformer(error); - throw transformedError; - } - }; - - return descriptor; - }; - - return syncErrorHandlingDecorator; -}; - -// _.flow(f, g) = f ∘ g -const zeroExErrorTransformer = _.flow( - schemaErrorTransformer, - contractCallErrorTransformer, - signatureRequestErrorTransformer, -); - -export const decorators = { - asyncZeroExErrorHandler: asyncErrorHandlerFactory(zeroExErrorTransformer), - syncZeroExErrorHandler: syncErrorHandlerFactory(zeroExErrorTransformer), -}; diff --git a/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts deleted file mode 100644 index 4b75ea386..000000000 --- a/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { ExchangeContractErrs } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store'; -import { TradeSide, TransferType } from '../types'; -import { constants } from '../utils/constants'; - -enum FailureReason { - Balance = 'balance', - ProxyAllowance = 'proxyAllowance', -} - -const ERR_MSG_MAPPING = { - [FailureReason.Balance]: { - [TradeSide.Maker]: { - [TransferType.Trade]: ExchangeContractErrs.InsufficientMakerBalance, - [TransferType.Fee]: ExchangeContractErrs.InsufficientMakerFeeBalance, - }, - [TradeSide.Taker]: { - [TransferType.Trade]: ExchangeContractErrs.InsufficientTakerBalance, - [TransferType.Fee]: ExchangeContractErrs.InsufficientTakerFeeBalance, - }, - }, - [FailureReason.ProxyAllowance]: { - [TradeSide.Maker]: { - [TransferType.Trade]: ExchangeContractErrs.InsufficientMakerAllowance, - [TransferType.Fee]: ExchangeContractErrs.InsufficientMakerFeeAllowance, - }, - [TradeSide.Taker]: { - [TransferType.Trade]: ExchangeContractErrs.InsufficientTakerAllowance, - [TransferType.Fee]: ExchangeContractErrs.InsufficientTakerFeeAllowance, - }, - }, -}; - -export class ExchangeTransferSimulator { - private readonly _store: AbstractBalanceAndProxyAllowanceLazyStore; - private static _throwValidationError( - failureReason: FailureReason, - tradeSide: TradeSide, - transferType: TransferType, - ): never { - const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType]; - throw new Error(errMsg); - } - constructor(store: AbstractBalanceAndProxyAllowanceLazyStore) { - this._store = store; - } - /** - * Simulates transferFrom call performed by a proxy - * @param tokenAddress Address of the token to be transferred - * @param from Owner of the transferred tokens - * @param to Recipient of the transferred tokens - * @param amountInBaseUnits The amount of tokens being transferred - * @param tradeSide Is Maker/Taker transferring - * @param transferType Is it a fee payment or a value transfer - */ - public async transferFromAsync( - tokenAddress: string, - from: string, - to: string, - amountInBaseUnits: BigNumber, - tradeSide: TradeSide, - transferType: TransferType, - ): Promise<void> { - // HACK: When simulating an open order (e.g taker is NULL_ADDRESS), we don't want to adjust balances/ - // allowances for the taker. We do however, want to increase the balance of the maker since the maker - // might be relying on those funds to fill subsequent orders or pay the order's fees. - if (from === constants.NULL_ADDRESS && tradeSide === TradeSide.Taker) { - await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits); - return; - } - const balance = await this._store.getBalanceAsync(tokenAddress, from); - const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from); - if (proxyAllowance.isLessThan(amountInBaseUnits)) { - ExchangeTransferSimulator._throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType); - } - if (balance.isLessThan(amountInBaseUnits)) { - ExchangeTransferSimulator._throwValidationError(FailureReason.Balance, tradeSide, transferType); - } - await this._decreaseProxyAllowanceAsync(tokenAddress, from, amountInBaseUnits); - await this._decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits); - await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits); - } - private async _decreaseProxyAllowanceAsync( - tokenAddress: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise<void> { - const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress); - if (!proxyAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { - this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits)); - } - } - private async _increaseBalanceAsync( - tokenAddress: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise<void> { - const balance = await this._store.getBalanceAsync(tokenAddress, userAddress); - this._store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits)); - } - private async _decreaseBalanceAsync( - tokenAddress: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise<void> { - const balance = await this._store.getBalanceAsync(tokenAddress, userAddress); - this._store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits)); - } -} diff --git a/packages/contract-wrappers/src/utils/filter_utils.ts b/packages/contract-wrappers/src/utils/filter_utils.ts deleted file mode 100644 index c05be062c..000000000 --- a/packages/contract-wrappers/src/utils/filter_utils.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { ContractAbi, EventAbi, FilterObject, LogEntry } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as jsSHA3 from 'js-sha3'; -import * as _ from 'lodash'; -import * as uuid from 'uuid/v4'; - -import { BlockRange, ContractEvents, IndexedFilterValues } from '../types'; - -const TOPIC_LENGTH = 32; - -export const filterUtils = { - generateUUID(): string { - return uuid(); - }, - getFilter( - address: string, - eventName: ContractEvents, - indexFilterValues: IndexedFilterValues, - abi: ContractAbi, - blockRange?: BlockRange, - ): FilterObject { - const eventAbi = _.find(abi, { name: eventName }) as EventAbi; - const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi); - const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature)); - const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues); - const topics = [topicForEventSignature, ...topicsForIndexedArgs]; - let filter: FilterObject = { - address, - topics, - }; - if (!_.isUndefined(blockRange)) { - filter = { - ...blockRange, - ...filter, - }; - } - return filter; - }, - getEventSignatureFromAbiByName(eventAbi: EventAbi): string { - const types = _.map(eventAbi.inputs, 'type'); - const signature = `${eventAbi.name}(${types.join(',')})`; - return signature; - }, - getTopicsForIndexedArgs(abi: EventAbi, indexFilterValues: IndexedFilterValues): Array<string | null> { - const topics: Array<string | null> = []; - for (const eventInput of abi.inputs) { - if (!eventInput.indexed) { - continue; - } - if (_.isUndefined(indexFilterValues[eventInput.name])) { - // Null is a wildcard topic in a JSON-RPC call - topics.push(null); - } else { - const value = indexFilterValues[eventInput.name] as string; - const buffer = ethUtil.toBuffer(value); - const paddedBuffer = ethUtil.setLengthLeft(buffer, TOPIC_LENGTH); - const topic = ethUtil.bufferToHex(paddedBuffer); - topics.push(topic); - } - } - return topics; - }, - matchesFilter(log: LogEntry, filter: FilterObject): boolean { - if (!_.isUndefined(filter.address) && log.address !== filter.address) { - return false; - } - if (!_.isUndefined(filter.topics)) { - return filterUtils.doesMatchTopics(log.topics, filter.topics); - } - return true; - }, - doesMatchTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean { - const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils)); - const doesMatchTopics = _.every(matchesTopic); - return doesMatchTopics; - }, - matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean { - if (_.isArray(filterTopic)) { - return _.includes(filterTopic, logTopic); - } - if (_.isString(filterTopic)) { - return filterTopic === logTopic; - } - // null topic is a wildcard - return true; - }, -}; diff --git a/packages/contract-wrappers/src/utils/transaction_encoder.ts b/packages/contract-wrappers/src/utils/transaction_encoder.ts deleted file mode 100644 index 0cf08a8fe..000000000 --- a/packages/contract-wrappers/src/utils/transaction_encoder.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { ExchangeContract } from '@0x/abi-gen-wrappers'; - -import { schemas } from '@0x/json-schemas'; -import { eip712Utils } from '@0x/order-utils'; -import { Order, SignedOrder } from '@0x/types'; -import { BigNumber, signTypedDataUtils } from '@0x/utils'; -import _ = require('lodash'); - -import { assert } from './assert'; - -/** - * Transaction Encoder. Transaction messages exist for the purpose of calling methods on the Exchange contract - * in the context of another address. For example, UserA can encode and sign a fillOrder transaction and UserB - * can submit this to the blockchain. The Exchange context executes as if UserA had directly submitted this transaction. - */ -export class TransactionEncoder { - private readonly _exchangeInstance: ExchangeContract; - constructor(exchangeInstance: ExchangeContract) { - this._exchangeInstance = exchangeInstance; - } - /** - * Encodes the transaction data for use with the Exchange contract. - * @param data The ABI Encoded 0x Exchange method. I.e fillOrder - * @param salt A random value to provide uniqueness and prevent replay attacks. - * @param signerAddress The address which will sign this transaction. - * @return An unsigned hex encoded transaction for use in 0x Exchange executeTransaction. - */ - public getTransactionHex(data: string, salt: BigNumber, signerAddress: string): string { - const exchangeAddress = this._getExchangeContract().address; - const executeTransactionData = { - salt, - signerAddress, - data, - }; - const typedData = eip712Utils.createZeroExTransactionTypedData(executeTransactionData, exchangeAddress); - const eip712MessageBuffer = signTypedDataUtils.generateTypedDataHash(typedData); - const messageHex = `0x${eip712MessageBuffer.toString('hex')}`; - return messageHex; - } - /** - * Encodes a fillOrder transaction. - * @param signedOrder An object that conforms to the SignedOrder interface. - * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. - * @return Hex encoded abi of the function call. - */ - public fillOrderTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); - const abiEncodedData = this._getExchangeContract().fillOrder.getABIEncodedTransactionData( - signedOrder, - takerAssetFillAmount, - signedOrder.signature, - ); - return abiEncodedData; - } - /** - * Encodes a fillOrderNoThrow transaction. - * @param signedOrder An object that conforms to the SignedOrder interface. - * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. - * @return Hex encoded abi of the function call. - */ - public fillOrderNoThrowTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); - const abiEncodedData = this._getExchangeContract().fillOrderNoThrow.getABIEncodedTransactionData( - signedOrder, - takerAssetFillAmount, - signedOrder.signature, - ); - return abiEncodedData; - } - /** - * Encodes a fillOrKillOrder transaction. - * @param signedOrder An object that conforms to the SignedOrder interface. - * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill. - * @return Hex encoded abi of the function call. - */ - public fillOrKillOrderTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string { - assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount); - const abiEncodedData = this._getExchangeContract().fillOrKillOrder.getABIEncodedTransactionData( - signedOrder, - takerAssetFillAmount, - signedOrder.signature, - ); - return abiEncodedData; - } - /** - * Encodes a batchFillOrders transaction. - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. - * @return Hex encoded abi of the function call. - */ - public batchFillOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - _.forEach(takerAssetFillAmounts, takerAssetFillAmount => - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), - ); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - const abiEncodedData = this._getExchangeContract().batchFillOrders.getABIEncodedTransactionData( - signedOrders, - takerAssetFillAmounts, - signatures, - ); - return abiEncodedData; - } - /** - * Encodes a batchFillOrKillOrders transaction. - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. - * @return Hex encoded abi of the function call. - */ - public batchFillOrKillOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - _.forEach(takerAssetFillAmounts, takerAssetFillAmount => - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), - ); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - const abiEncodedData = this._getExchangeContract().batchFillOrKillOrders.getABIEncodedTransactionData( - signedOrders, - takerAssetFillAmounts, - signatures, - ); - return abiEncodedData; - } - /** - * Encodes a batchFillOrdersNoThrow transaction. - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill. - * @return Hex encoded abi of the function call. - */ - public batchFillOrdersNoThrowTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - _.forEach(takerAssetFillAmounts, takerAssetFillAmount => - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount), - ); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - const abiEncodedData = this._getExchangeContract().batchFillOrdersNoThrow.getABIEncodedTransactionData( - signedOrders, - takerAssetFillAmounts, - signatures, - ); - return abiEncodedData; - } - /** - * Encodes a batchCancelOrders transaction. - * @param signedOrders An array of orders to cancel. - * @return Hex encoded abi of the function call. - */ - public batchCancelOrdersTx(signedOrders: SignedOrder[]): string { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - const abiEncodedData = this._getExchangeContract().batchCancelOrders.getABIEncodedTransactionData(signedOrders); - return abiEncodedData; - } - /** - * Encodes a cancelOrdersUpTo transaction. - * @param targetOrderEpoch Target order epoch. - * @return Hex encoded abi of the function call. - */ - public cancelOrdersUpToTx(targetOrderEpoch: BigNumber): string { - assert.isBigNumber('targetOrderEpoch', targetOrderEpoch); - const abiEncodedData = this._getExchangeContract().cancelOrdersUpTo.getABIEncodedTransactionData( - targetOrderEpoch, - ); - return abiEncodedData; - } - /** - * Encodes a cancelOrder transaction. - * @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel. - * @return Hex encoded abi of the function call. - */ - public cancelOrderTx(order: Order | SignedOrder): string { - assert.doesConformToSchema('order', order, schemas.orderSchema); - const abiEncodedData = this._getExchangeContract().cancelOrder.getABIEncodedTransactionData(order); - return abiEncodedData; - } - /** - * Encodes a marketSellOrders transaction. - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmount Taker asset fill amount. - * @return Hex encoded abi of the function call. - */ - public marketSellOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): string { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - const abiEncodedData = this._getExchangeContract().marketSellOrders.getABIEncodedTransactionData( - signedOrders, - takerAssetFillAmount, - signatures, - ); - return abiEncodedData; - } - /** - * Encodes a marketSellOrdersNoThrow transaction. - * @param signedOrders An array of signed orders to fill. - * @param takerAssetFillAmount Taker asset fill amount. - * @return Hex encoded abi of the function call. - */ - public marketSellOrdersNoThrowTx(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): string { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - const abiEncodedData = this._getExchangeContract().marketSellOrdersNoThrow.getABIEncodedTransactionData( - signedOrders, - takerAssetFillAmount, - signatures, - ); - return abiEncodedData; - } - /** - * Encodes a maketBuyOrders transaction. - * @param signedOrders An array of signed orders to fill. - * @param makerAssetFillAmount Maker asset fill amount. - * @return Hex encoded abi of the function call. - */ - public marketBuyOrdersTx(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): string { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - const abiEncodedData = this._getExchangeContract().marketBuyOrders.getABIEncodedTransactionData( - signedOrders, - makerAssetFillAmount, - signatures, - ); - return abiEncodedData; - } - /** - * Encodes a maketBuyOrdersNoThrow transaction. - * @param signedOrders An array of signed orders to fill. - * @param makerAssetFillAmount Maker asset fill amount. - * @return Hex encoded abi of the function call. - */ - public marketBuyOrdersNoThrowTx(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): string { - assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema); - assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount); - const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); - const abiEncodedData = this._getExchangeContract().marketBuyOrdersNoThrow.getABIEncodedTransactionData( - signedOrders, - makerAssetFillAmount, - signatures, - ); - return abiEncodedData; - } - /** - * Encodes a preSign transaction. - * @param hash Hash to pre-sign - * @param signerAddress Address that should have signed the given hash. - * @param signature Proof that the hash has been signed by signer. - * @return Hex encoded abi of the function call. - */ - public preSignTx(hash: string, signerAddress: string, signature: string): string { - assert.isHexString('hash', hash); - assert.isETHAddressHex('signerAddress', signerAddress); - assert.isHexString('signature', signature); - const abiEncodedData = this._getExchangeContract().preSign.getABIEncodedTransactionData( - hash, - signerAddress, - signature, - ); - return abiEncodedData; - } - /** - * Encodes a setSignatureValidatorApproval transaction. - * @param validatorAddress Validator contract address. - * @param isApproved Boolean value to set approval to. - * @return Hex encoded abi of the function call. - */ - public setSignatureValidatorApprovalTx(validatorAddress: string, isApproved: boolean): string { - assert.isETHAddressHex('validatorAddress', validatorAddress); - assert.isBoolean('isApproved', isApproved); - const abiEncodedData = this._getExchangeContract().setSignatureValidatorApproval.getABIEncodedTransactionData( - validatorAddress, - isApproved, - ); - return abiEncodedData; - } - private _getExchangeContract(): ExchangeContract { - return this._exchangeInstance; - } -} diff --git a/packages/contract-wrappers/src/utils/utils.ts b/packages/contract-wrappers/src/utils/utils.ts deleted file mode 100644 index ab69385e7..000000000 --- a/packages/contract-wrappers/src/utils/utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; - -import { constants } from './constants'; - -export const utils = { - getCurrentUnixTimestampSec(): BigNumber { - const milisecondsInSecond = 1000; - return new BigNumber(Date.now() / milisecondsInSecond).integerValue(); - }, - getCurrentUnixTimestampMs(): BigNumber { - return new BigNumber(Date.now()); - }, - numberPercentageToEtherTokenAmountPercentage(percentage: number): BigNumber { - return Web3Wrapper.toBaseUnitAmount(constants.ONE_AMOUNT, constants.ETHER_TOKEN_DECIMALS).multipliedBy( - percentage, - ); - }, - removeUndefinedProperties<T extends object>(obj: T): Partial<T> { - return _.pickBy(obj); - }, -}; diff --git a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts deleted file mode 100644 index 6cb8a669e..000000000 --- a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { orderFactory } from '@0x/order-utils/lib/src/order_factory'; -import * as chai from 'chai'; -import * as _ from 'lodash'; -import 'mocha'; - -import { calldataOptimizationUtils } from '../src/utils/calldata_optimization_utils'; -import { constants } from '../src/utils/constants'; - -import { chaiSetup } from './utils/chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; - -// utility for generating a set of order objects with mostly NULL values -// except for a specified makerAssetData and takerAssetData -const FAKE_ORDERS_COUNT = 5; -const generateFakeOrders = (makerAssetData: string, takerAssetData: string) => - _.map(_.range(FAKE_ORDERS_COUNT), index => { - const order = orderFactory.createOrder( - constants.NULL_ADDRESS, - constants.ZERO_AMOUNT, - makerAssetData, - constants.ZERO_AMOUNT, - takerAssetData, - constants.NULL_ADDRESS, - ); - return { - ...order, - signature: 'dummy signature', - }; - }); - -describe('calldataOptimizationUtils', () => { - const fakeMakerAssetData = 'fakeMakerAssetData'; - const fakeTakerAssetData = 'fakeTakerAssetData'; - const orders = generateFakeOrders(fakeMakerAssetData, fakeTakerAssetData); - describe('#optimizeForwarderOrders', () => { - it('should make makerAssetData `0x` unless first order', () => { - const optimizedOrders = calldataOptimizationUtils.optimizeForwarderOrders(orders); - expect(optimizedOrders[0].makerAssetData).to.equal(fakeMakerAssetData); - const ordersWithoutHead = _.slice(optimizedOrders, 1); - _.forEach(ordersWithoutHead, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES)); - }); - it('should make all takerAssetData `0x`', () => { - const optimizedOrders = calldataOptimizationUtils.optimizeForwarderOrders(orders); - _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES)); - }); - }); - describe('#optimizeForwarderFeeOrders', () => { - it('should make all makerAssetData `0x`', () => { - const optimizedOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(orders); - _.forEach(optimizedOrders, order => expect(order.makerAssetData).to.equal(constants.NULL_BYTES)); - }); - it('should make all takerAssetData `0x`', () => { - const optimizedOrders = calldataOptimizationUtils.optimizeForwarderFeeOrders(orders); - _.forEach(optimizedOrders, order => expect(order.takerAssetData).to.equal(constants.NULL_BYTES)); - }); - }); -}); diff --git a/packages/contract-wrappers/test/dutch_auction_wrapper_test.ts b/packages/contract-wrappers/test/dutch_auction_wrapper_test.ts deleted file mode 100644 index d7a6ca015..000000000 --- a/packages/contract-wrappers/test/dutch_auction_wrapper_test.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { expectTransactionFailedAsync, getLatestBlockTimestampAsync } from '@0x/contracts-test-utils'; -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { assetDataUtils } from '@0x/order-utils'; -import { RevertReason, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { ContractWrappers } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { DutchAuctionUtils } from './utils/dutch_auction_utils'; -import { migrateOnceAsync } from './utils/migrate'; -import { tokenUtils } from './utils/token_utils'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -// tslint:disable:custom-no-magic-numbers -describe('DutchAuctionWrapper', () => { - const makerAssetAmount = new BigNumber(5); - const auctionEndTakerAmount = new BigNumber(10); - const auctionBeginTakerAmount = auctionEndTakerAmount.times(2); - const tenMinutesInSeconds = 10 * 60; - let contractWrappers: ContractWrappers; - let exchangeContractAddress: string; - let userAddresses: string[]; - let makerAddress: string; - let takerAddress: string; - let makerTokenAddress: string; - let takerTokenAddress: string; - let buyOrder: SignedOrder; - let sellOrder: SignedOrder; - let makerTokenAssetData: string; - let takerTokenAssetData: string; - let auctionBeginTimeSeconds: BigNumber; - let auctionEndTimeSeconds: BigNumber; - before(async () => { - // setup contract wrappers & addresses - const contractAddresses = await migrateOnceAsync(); - await blockchainLifecycle.startAsync(); - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - exchangeContractAddress = contractWrappers.exchange.address; - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - [, makerAddress, takerAddress] = userAddresses; - [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - // construct asset data for tokens being swapped - [makerTokenAssetData, takerTokenAssetData] = [ - assetDataUtils.encodeERC20AssetData(makerTokenAddress), - assetDataUtils.encodeERC20AssetData(takerTokenAddress), - ]; - // setup auction details in maker asset data - const currentBlockTimestamp: number = await getLatestBlockTimestampAsync(); - auctionBeginTimeSeconds = new BigNumber(currentBlockTimestamp - tenMinutesInSeconds); - auctionEndTimeSeconds = new BigNumber(currentBlockTimestamp + tenMinutesInSeconds); - // create auction orders - const coinbase = userAddresses[0]; - const dutchAuctionUtils = new DutchAuctionUtils( - web3Wrapper, - coinbase, - exchangeContractAddress, - contractWrappers.erc20Proxy.address, - ); - sellOrder = await dutchAuctionUtils.createSignedSellOrderAsync( - auctionBeginTimeSeconds, - auctionEndTimeSeconds, - auctionBeginTakerAmount, - auctionEndTakerAmount, - makerAssetAmount, - makerTokenAssetData, - takerTokenAssetData, - makerAddress, - constants.NULL_ADDRESS, - ); - buyOrder = await dutchAuctionUtils.createSignedBuyOrderAsync(sellOrder, takerAddress); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#matchOrdersAsync', () => { - it('should match two orders', async () => { - const txHash = await contractWrappers.dutchAuction.matchOrdersAsync(buyOrder, sellOrder, takerAddress); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - it('should throw when invalid transaction and shouldValidate is true', async () => { - // request match with bad buy/sell orders - const badSellOrder = buyOrder; - const badBuyOrder = sellOrder; - return expectTransactionFailedAsync( - contractWrappers.dutchAuction.matchOrdersAsync(badBuyOrder, badSellOrder, takerAddress, { - shouldValidate: true, - }), - RevertReason.InvalidAssetData, - ); - }); - }); - - describe('#getAuctionDetailsAsync', () => { - it('should get auction details', async () => { - // get auction details - const auctionDetails = await contractWrappers.dutchAuction.getAuctionDetailsAsync(sellOrder); - // run some basic sanity checks on the return value - expect(auctionDetails.beginTimeSeconds, 'auctionDetails.beginTimeSeconds').to.be.bignumber.equal( - auctionBeginTimeSeconds, - ); - expect(auctionDetails.beginAmount, 'auctionDetails.beginAmount').to.be.bignumber.equal( - auctionBeginTakerAmount, - ); - expect(auctionDetails.endTimeSeconds, 'auctionDetails.endTimeSeconds').to.be.bignumber.equal( - auctionEndTimeSeconds, - ); - }); - }); -}); diff --git a/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts b/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts deleted file mode 100644 index d8dfa4204..000000000 --- a/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as chai from 'chai'; - -import { ContractWrappers } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -import { provider } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('ERC20ProxyWrapper', () => { - let contractWrappers: ContractWrappers; - before(async () => { - const contractAddresses = await migrateOnceAsync(); - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - }); - describe('#isAuthorizedAsync', () => { - it('should return false if the address is not authorized', async () => { - const isAuthorized = await contractWrappers.erc20Proxy.isAuthorizedAsync(constants.NULL_ADDRESS); - expect(isAuthorized).to.be.false(); - }); - }); - describe('#getAuthorizedAddressesAsync', () => { - it('should return the list of authorized addresses', async () => { - const authorizedAddresses = await contractWrappers.erc20Proxy.getAuthorizedAddressesAsync(); - for (const authorizedAddress of authorizedAddresses) { - const isAuthorized = await contractWrappers.erc20Proxy.isAuthorizedAsync(authorizedAddress); - expect(isAuthorized).to.be.true(); - } - }); - }); -}); diff --git a/packages/contract-wrappers/test/erc20_wrapper_test.ts b/packages/contract-wrappers/test/erc20_wrapper_test.ts deleted file mode 100644 index 15d3a9ead..000000000 --- a/packages/contract-wrappers/test/erc20_wrapper_test.ts +++ /dev/null @@ -1,634 +0,0 @@ -import { ContractAddresses } from '@0x/contract-addresses'; -import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils'; -import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0x/subproviders'; -import { DoneCallback } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import { Provider } from 'ethereum-types'; -import 'mocha'; - -import { - BlockParamLiteral, - BlockRange, - ContractWrappers, - ContractWrappersConfig, - ContractWrappersError, - DecodedLogEvent, - ERC20TokenApprovalEventArgs, - ERC20TokenEvents, - ERC20TokenTransferEventArgs, -} from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -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('ERC20Wrapper', () => { - let contractWrappers: ContractWrappers; - let contractAddresses: ContractAddresses; - let userAddresses: string[]; - let tokens: string[]; - let coinbase: string; - let addressWithoutFunds: string; - let config: ContractWrappersConfig; - - before(async () => { - contractAddresses = await migrateOnceAsync(); - config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - tokens = tokenUtils.getDummyERC20TokenAddresses(); - coinbase = userAddresses[0]; - addressWithoutFunds = userAddresses[1]; - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#transferAsync', () => { - let tokenAddress: string; - let transferAmount: BigNumber; - before(() => { - tokenAddress = tokens[0]; - transferAmount = new BigNumber(42); - }); - it('should successfully transfer tokens', async () => { - const fromAddress = coinbase; - const toAddress = addressWithoutFunds; - const preBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress); - expect(preBalance).to.be.bignumber.equal(0); - await contractWrappers.erc20Token.transferAsync(tokenAddress, fromAddress, toAddress, transferAmount); - const postBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress); - return expect(postBalance).to.be.bignumber.equal(transferAmount); - }); - it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => { - const fromAddress = addressWithoutFunds; - const toAddress = coinbase; - return expect( - contractWrappers.erc20Token.transferAsync(tokenAddress, fromAddress, toAddress, transferAmount), - ).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer); - }); - }); - describe('#transferFromAsync', () => { - let tokenAddress: string; - let toAddress: string; - let senderAddress: string; - before(async () => { - tokenAddress = tokens[0]; - toAddress = addressWithoutFunds; - senderAddress = userAddresses[2]; - }); - it('should fail to transfer tokens if fromAddress has insufficient allowance set', async () => { - const fromAddress = coinbase; - const transferAmount = new BigNumber(42); - - const fromAddressBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, fromAddress); - expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount); - - const fromAddressAllowance = await contractWrappers.erc20Token.getAllowanceAsync( - tokenAddress, - fromAddress, - toAddress, - ); - expect(fromAddressAllowance).to.be.bignumber.equal(0); - - return expect( - contractWrappers.erc20Token.transferFromAsync( - tokenAddress, - fromAddress, - toAddress, - senderAddress, - transferAmount, - ), - ).to.be.rejectedWith(ContractWrappersError.InsufficientAllowanceForTransfer); - }); - it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress', async () => { - const fromAddress = coinbase; - const transferAmount = new BigNumber(42); - - await contractWrappers.erc20Token.setAllowanceAsync(tokenAddress, fromAddress, toAddress, transferAmount); - - return expect( - contractWrappers.erc20Token.transferFromAsync( - tokenAddress, - fromAddress, - toAddress, - senderAddress, - transferAmount, - ), - ).to.be.rejectedWith(ContractWrappersError.InsufficientAllowanceForTransfer); - }); - it('should fail to transfer tokens if fromAddress has insufficient balance', async () => { - const fromAddress = addressWithoutFunds; - const transferAmount = new BigNumber(42); - - const fromAddressBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, fromAddress); - expect(fromAddressBalance).to.be.bignumber.equal(0); - - await contractWrappers.erc20Token.setAllowanceAsync( - tokenAddress, - fromAddress, - senderAddress, - transferAmount, - ); - const fromAddressAllowance = await contractWrappers.erc20Token.getAllowanceAsync( - tokenAddress, - fromAddress, - senderAddress, - ); - expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount); - - return expect( - contractWrappers.erc20Token.transferFromAsync( - tokenAddress, - fromAddress, - toAddress, - senderAddress, - transferAmount, - ), - ).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer); - }); - it('should successfully transfer tokens', async () => { - const fromAddress = coinbase; - - const preBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress); - expect(preBalance).to.be.bignumber.equal(0); - - const transferAmount = new BigNumber(42); - await contractWrappers.erc20Token.setAllowanceAsync( - tokenAddress, - fromAddress, - senderAddress, - transferAmount, - ); - - await contractWrappers.erc20Token.transferFromAsync( - tokenAddress, - fromAddress, - toAddress, - senderAddress, - transferAmount, - ); - const postBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress); - return expect(postBalance).to.be.bignumber.equal(transferAmount); - }); - }); - describe('#getBalanceAsync', () => { - describe('With provider with accounts', () => { - it('should return the balance for an existing ERC20 token', async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - const balance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, ownerAddress); - const expectedBalance = new BigNumber('1000000000000000000000000000'); - return expect(balance).to.be.bignumber.equal(expectedBalance); - }); - it('should return a balance of 0 for a non-existent owner address', async () => { - const tokenAddress = tokens[0]; - const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593'; - const balance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, nonExistentOwner); - const expectedBalance = new BigNumber(0); - return expect(balance).to.be.bignumber.equal(expectedBalance); - }); - }); - describe('With provider without accounts', () => { - let zeroExContractWithoutAccounts: ContractWrappers; - before(async () => { - const emptyWalletProvider = addEmptyWalletSubprovider(provider); - zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config); - }); - it('should return balance even when called with provider instance without addresses', async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - const balance = await zeroExContractWithoutAccounts.erc20Token.getBalanceAsync( - tokenAddress, - ownerAddress, - ); - const expectedBalance = new BigNumber('1000000000000000000000000000'); - return expect(balance).to.be.bignumber.equal(expectedBalance); - }); - }); - }); - describe('#setAllowanceAsync', () => { - it("should set the spender's allowance", async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - const spenderAddress = addressWithoutFunds; - - const allowanceBeforeSet = await contractWrappers.erc20Token.getAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - ); - const expectedAllowanceBeforeAllowanceSet = new BigNumber(0); - expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet); - - const amountInBaseUnits = new BigNumber(50); - await contractWrappers.erc20Token.setAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - amountInBaseUnits, - ); - - const allowanceAfterSet = await contractWrappers.erc20Token.getAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - ); - const expectedAllowanceAfterAllowanceSet = amountInBaseUnits; - return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet); - }); - }); - describe('#setUnlimitedAllowanceAsync', () => { - it("should set the unlimited spender's allowance", async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - const spenderAddress = addressWithoutFunds; - - await contractWrappers.erc20Token.setUnlimitedAllowanceAsync(tokenAddress, ownerAddress, spenderAddress); - const allowance = await contractWrappers.erc20Token.getAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - ); - return expect(allowance).to.be.bignumber.equal( - contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - ); - }); - it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => { - const transferAmount = new BigNumber(5); - const zrxAddress = contractAddresses.zrxToken; - const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses; - await contractWrappers.erc20Token.setAllowanceAsync( - zrxAddress, - coinbase, - userWithNormalAllowance, - transferAmount, - ); - await contractWrappers.erc20Token.setUnlimitedAllowanceAsync( - zrxAddress, - coinbase, - userWithUnlimitedAllowance, - ); - - const initBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance); - const initBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync( - userWithUnlimitedAllowance, - ); - - await contractWrappers.erc20Token.transferFromAsync( - zrxAddress, - coinbase, - userWithNormalAllowance, - userWithNormalAllowance, - transferAmount, - ); - await contractWrappers.erc20Token.transferFromAsync( - zrxAddress, - coinbase, - userWithUnlimitedAllowance, - userWithUnlimitedAllowance, - transferAmount, - ); - - const finalBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance); - const finalBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync( - userWithUnlimitedAllowance, - ); - - const normalGasCost = initBalanceWithNormalAllowance.minus(finalBalanceWithNormalAllowance); - const unlimitedGasCost = initBalanceWithUnlimitedAllowance.minus(finalBalanceWithUnlimitedAllowance); - - // In theory the gas cost with unlimited allowance should be smaller, but with testrpc it's actually bigger. - // This needs to be investigated in ethereumjs-vm. This test is essentially a repro. - // TODO: Make this test pass with inverted assertion. - expect(unlimitedGasCost.toNumber()).to.be.gt(normalGasCost.toNumber()); - }); - }); - describe('#getAllowanceAsync', () => { - describe('With provider with accounts', () => { - it('should get the proxy allowance', async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - const spenderAddress = addressWithoutFunds; - - const amountInBaseUnits = new BigNumber(50); - await contractWrappers.erc20Token.setAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - amountInBaseUnits, - ); - - const allowance = await contractWrappers.erc20Token.getAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - ); - const expectedAllowance = amountInBaseUnits; - return expect(allowance).to.be.bignumber.equal(expectedAllowance); - }); - it('should return 0 if no allowance set yet', async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - const spenderAddress = addressWithoutFunds; - const allowance = await contractWrappers.erc20Token.getAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - ); - const expectedAllowance = new BigNumber(0); - return expect(allowance).to.be.bignumber.equal(expectedAllowance); - }); - }); - describe('With provider without accounts', () => { - let zeroExContractWithoutAccounts: ContractWrappers; - before(async () => { - const emptyWalletProvider = addEmptyWalletSubprovider(provider); - zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config); - }); - it('should get the proxy allowance', async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - const spenderAddress = addressWithoutFunds; - - const amountInBaseUnits = new BigNumber(50); - await contractWrappers.erc20Token.setAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - amountInBaseUnits, - ); - - const allowance = await zeroExContractWithoutAccounts.erc20Token.getAllowanceAsync( - tokenAddress, - ownerAddress, - spenderAddress, - ); - const expectedAllowance = amountInBaseUnits; - return expect(allowance).to.be.bignumber.equal(expectedAllowance); - }); - }); - }); - describe('#getProxyAllowanceAsync', () => { - it('should get the proxy allowance', async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - - const amountInBaseUnits = new BigNumber(50); - await contractWrappers.erc20Token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amountInBaseUnits); - - const allowance = await contractWrappers.erc20Token.getProxyAllowanceAsync(tokenAddress, ownerAddress); - const expectedAllowance = amountInBaseUnits; - return expect(allowance).to.be.bignumber.equal(expectedAllowance); - }); - }); - describe('#setProxyAllowanceAsync', () => { - it('should set the proxy allowance', async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - - const allowanceBeforeSet = await contractWrappers.erc20Token.getProxyAllowanceAsync( - tokenAddress, - ownerAddress, - ); - const expectedAllowanceBeforeAllowanceSet = new BigNumber(0); - expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet); - - const amountInBaseUnits = new BigNumber(50); - await contractWrappers.erc20Token.setProxyAllowanceAsync(tokenAddress, ownerAddress, amountInBaseUnits); - - const allowanceAfterSet = await contractWrappers.erc20Token.getProxyAllowanceAsync( - tokenAddress, - ownerAddress, - ); - const expectedAllowanceAfterAllowanceSet = amountInBaseUnits; - return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet); - }); - }); - describe('#setUnlimitedProxyAllowanceAsync', () => { - it('should set the unlimited proxy allowance', async () => { - const tokenAddress = tokens[0]; - const ownerAddress = coinbase; - - await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, ownerAddress); - const allowance = await contractWrappers.erc20Token.getProxyAllowanceAsync(tokenAddress, ownerAddress); - return expect(allowance).to.be.bignumber.equal( - contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - ); - }); - }); - describe('#subscribe', () => { - const indexFilterValues = {}; - let tokenAddress: string; - const transferAmount = new BigNumber(42); - const allowanceAmount = new BigNumber(42); - before(() => { - tokenAddress = tokens[0]; - }); - afterEach(() => { - contractWrappers.erc20Token.unsubscribeAll(); - }); - // Hack: Mocha does not allow a test to be both async and have a `done` callback - // Since we need to await the receipt of the event in the `subscribe` callback, - // we do need both. A hack is to make the top-level a sync fn w/ a done callback and then - // wrap the rest of the test in an async block - // Source: https://github.com/mochajs/mocha/issues/2407 - it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ERC20TokenTransferEventArgs>) => { - expect(logEvent.isRemoved).to.be.false(); - expect(logEvent.log.logIndex).to.be.equal(0); - expect(logEvent.log.transactionIndex).to.be.equal(0); - expect(logEvent.log.blockNumber).to.be.a('number'); - const args = logEvent.log.args; - expect(args._from).to.be.equal(coinbase); - expect(args._to).to.be.equal(addressWithoutFunds); - expect(args._value).to.be.bignumber.equal(transferAmount); - }, - ); - contractWrappers.erc20Token.subscribe( - tokenAddress, - ERC20TokenEvents.Transfer, - indexFilterValues, - callback, - ); - await contractWrappers.erc20Token.transferAsync( - tokenAddress, - coinbase, - addressWithoutFunds, - transferAmount, - ); - })().catch(done); - }); - it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => { - expect(logEvent).to.not.be.undefined(); - expect(logEvent.isRemoved).to.be.false(); - const args = logEvent.log.args; - expect(args._owner).to.be.equal(coinbase); - expect(args._spender).to.be.equal(addressWithoutFunds); - expect(args._value).to.be.bignumber.equal(allowanceAmount); - }, - ); - contractWrappers.erc20Token.subscribe( - tokenAddress, - ERC20TokenEvents.Approval, - indexFilterValues, - callback, - ); - await contractWrappers.erc20Token.setAllowanceAsync( - tokenAddress, - coinbase, - addressWithoutFunds, - allowanceAmount, - ); - })().catch(done); - }); - it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { - (async () => { - const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( - (_logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => { - done(new Error('Expected this subscription to have been cancelled')); - }, - ); - contractWrappers.erc20Token.subscribe( - tokenAddress, - ERC20TokenEvents.Transfer, - indexFilterValues, - callbackNeverToBeCalled, - ); - const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.unsubscribeAll(); - contractWrappers.erc20Token.subscribe( - tokenAddress, - ERC20TokenEvents.Transfer, - indexFilterValues, - callbackToBeCalled, - ); - await contractWrappers.erc20Token.transferAsync( - tokenAddress, - coinbase, - addressWithoutFunds, - transferAmount, - ); - })().catch(done); - }); - it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { - (async () => { - const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( - (_logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => { - done(new Error('Expected this subscription to have been cancelled')); - }, - ); - const subscriptionToken = contractWrappers.erc20Token.subscribe( - tokenAddress, - ERC20TokenEvents.Transfer, - indexFilterValues, - callbackNeverToBeCalled, - ); - contractWrappers.erc20Token.unsubscribe(subscriptionToken); - await contractWrappers.erc20Token.transferAsync( - tokenAddress, - coinbase, - addressWithoutFunds, - transferAmount, - ); - done(); - })().catch(done); - }); - }); - describe('#getLogsAsync', () => { - let tokenAddress: string; - let tokenTransferProxyAddress: string; - const blockRange: BlockRange = { - fromBlock: 0, - toBlock: BlockParamLiteral.Latest, - }; - let txHash: string; - before(() => { - tokenAddress = tokens[0]; - tokenTransferProxyAddress = contractWrappers.erc20Proxy.address; - }); - it('should get logs with decoded args emitted by Approval', async () => { - txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const eventName = ERC20TokenEvents.Approval; - const indexFilterValues = {}; - const logs = await contractWrappers.erc20Token.getLogsAsync<ERC20TokenApprovalEventArgs>( - tokenAddress, - eventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(1); - const args = logs[0].args; - expect(logs[0].event).to.be.equal(eventName); - expect(args._owner).to.be.equal(coinbase); - expect(args._spender).to.be.equal(tokenTransferProxyAddress); - expect(args._value).to.be.bignumber.equal(contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); - }); - it('should only get the logs with the correct event name', async () => { - txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const differentEventName = ERC20TokenEvents.Transfer; - const indexFilterValues = {}; - const logs = await contractWrappers.erc20Token.getLogsAsync( - tokenAddress, - differentEventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(0); - }); - it('should only get the logs with the correct indexed fields', async () => { - txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync( - tokenAddress, - addressWithoutFunds, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const eventName = ERC20TokenEvents.Approval; - const indexFilterValues = { - _owner: coinbase, - }; - const logs = await contractWrappers.erc20Token.getLogsAsync<ERC20TokenApprovalEventArgs>( - tokenAddress, - eventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(1); - const args = logs[0].args; - expect(args._owner).to.be.equal(coinbase); - }); - }); -}); -// tslint:disable:max-file-line-count - -function addEmptyWalletSubprovider(p: Provider): Provider { - const providerEngine = new Web3ProviderEngine(); - providerEngine.addProvider(new EmptyWalletSubprovider()); - const currentSubproviders = (p as any)._providers; - for (const subprovider of currentSubproviders) { - providerEngine.addProvider(subprovider); - } - providerEngine.start(); - return providerEngine; -} diff --git a/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts b/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts deleted file mode 100644 index 9b0fe8817..000000000 --- a/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as chai from 'chai'; - -import { ContractWrappers } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -import { provider } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('ERC721ProxyWrapper', () => { - let contractWrappers: ContractWrappers; - before(async () => { - const contractAddresses = await migrateOnceAsync(); - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - }); - describe('#isAuthorizedAsync', () => { - it('should return false if the address is not authorized', async () => { - const isAuthorized = await contractWrappers.erc721Proxy.isAuthorizedAsync(constants.NULL_ADDRESS); - expect(isAuthorized).to.be.false(); - }); - }); - describe('#getAuthorizedAddressesAsync', () => { - it('should return the list of authorized addresses', async () => { - const authorizedAddresses = await contractWrappers.erc721Proxy.getAuthorizedAddressesAsync(); - for (const authorizedAddress of authorizedAddresses) { - const isAuthorized = await contractWrappers.erc721Proxy.isAuthorizedAsync(authorizedAddress); - expect(isAuthorized).to.be.true(); - } - }); - }); -}); diff --git a/packages/contract-wrappers/test/erc721_wrapper_test.ts b/packages/contract-wrappers/test/erc721_wrapper_test.ts deleted file mode 100644 index a7f1e4c41..000000000 --- a/packages/contract-wrappers/test/erc721_wrapper_test.ts +++ /dev/null @@ -1,466 +0,0 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils'; -import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0x/subproviders'; -import { DoneCallback } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import { Provider } from 'ethereum-types'; -import 'mocha'; - -import { - BlockParamLiteral, - BlockRange, - ContractWrappers, - ContractWrappersConfig, - ContractWrappersError, - DecodedLogEvent, - ERC721TokenApprovalEventArgs, - ERC721TokenApprovalForAllEventArgs, - ERC721TokenEvents, - ERC721TokenTransferEventArgs, -} from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -import { tokenUtils } from './utils/token_utils'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -describe('ERC721Wrapper', () => { - let contractWrappers: ContractWrappers; - let userAddresses: string[]; - let tokens: string[]; - let ownerAddress: string; - let tokenAddress: string; - let anotherOwnerAddress: string; - let operatorAddress: string; - let approvedAddress: string; - let receiverAddress: string; - let config: ContractWrappersConfig; - - before(async () => { - const contractAddresses = await migrateOnceAsync(); - config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - tokens = tokenUtils.getDummyERC721TokenAddresses(); - tokenAddress = tokens[0]; - [ownerAddress, operatorAddress, anotherOwnerAddress, approvedAddress, receiverAddress] = userAddresses; - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#transferFromAsync', () => { - it('should fail to transfer NFT if fromAddress has no approvals set', async () => { - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - return expect( - contractWrappers.erc721Token.transferFromAsync(tokenAddress, receiverAddress, approvedAddress, tokenId), - ).to.be.rejectedWith(ContractWrappersError.ERC721NoApproval); - }); - it('should successfully transfer tokens when sender is an approved address', async () => { - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - let txHash = await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const owner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId); - expect(owner).to.be.equal(ownerAddress); - txHash = await contractWrappers.erc721Token.transferFromAsync( - tokenAddress, - receiverAddress, - approvedAddress, - tokenId, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const newOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId); - expect(newOwner).to.be.equal(receiverAddress); - }); - it('should successfully transfer tokens when sender is an approved operator', async () => { - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - const isApprovedForAll = true; - let txHash = await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - isApprovedForAll, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const owner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId); - expect(owner).to.be.equal(ownerAddress); - txHash = await contractWrappers.erc721Token.transferFromAsync( - tokenAddress, - receiverAddress, - operatorAddress, - tokenId, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const newOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId); - expect(newOwner).to.be.equal(receiverAddress); - }); - }); - describe('#getTokenCountAsync', () => { - describe('With provider with accounts', () => { - it('should return the count for an existing ERC721 token', async () => { - let tokenCount = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, ownerAddress); - expect(tokenCount).to.be.bignumber.equal(0); - await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - tokenCount = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, ownerAddress); - expect(tokenCount).to.be.bignumber.equal(1); - }); - it('should return a balance of 0 for a non-existent owner address', async () => { - const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593'; - const balance = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, nonExistentOwner); - const expectedBalance = new BigNumber(0); - return expect(balance).to.be.bignumber.equal(expectedBalance); - }); - }); - describe('With provider without accounts', () => { - let zeroExContractWithoutAccounts: ContractWrappers; - before(async () => { - const emptyWalletProvider = addEmptyWalletSubprovider(provider); - zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config); - }); - it('should return balance even when called with provider instance without addresses', async () => { - const balance = await zeroExContractWithoutAccounts.erc721Token.getTokenCountAsync( - tokenAddress, - ownerAddress, - ); - return expect(balance).to.be.bignumber.equal(0); - }); - }); - }); - describe('#getOwnerOfAsync', () => { - it('should return the owner for an existing ERC721 token', async () => { - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - const tokenOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId); - expect(tokenOwner).to.be.bignumber.equal(ownerAddress); - }); - it('should return undefined not 0 for a non-existent ERC721', async () => { - const fakeTokenId = new BigNumber(42); - return expect(contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, fakeTokenId)).to.be.rejectedWith( - ContractWrappersError.ERC721OwnerNotFound, - ); - }); - }); - describe('#setApprovalForAllAsync/isApprovedForAllAsync', () => { - it('should check if operator address is approved', async () => { - let isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - ); - expect(isApprovedForAll).to.be.false(); - // set - isApprovedForAll = true; - let txHash = await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - isApprovedForAll, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - ); - expect(isApprovedForAll).to.be.true(); - // unset - txHash = await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - false, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - isApprovedForAll = await contractWrappers.erc721Token.isApprovedForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - ); - expect(isApprovedForAll).to.be.false(); - }); - }); - describe('#setProxyApprovalForAllAsync/isProxyApprovedForAllAsync', () => { - it('should check if proxy address is approved', async () => { - let isApprovedForAll = true; - const txHash = await contractWrappers.erc721Token.setProxyApprovalForAllAsync( - tokenAddress, - ownerAddress, - isApprovedForAll, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - isApprovedForAll = await contractWrappers.erc721Token.isProxyApprovedForAllAsync( - tokenAddress, - ownerAddress, - ); - expect(isApprovedForAll).to.be.true(); - }); - }); - describe('#setApprovalAsync/getApprovedIfExistsAsync', () => { - it("should set the spender's approval", async () => { - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - - const approvalBeforeSet = await contractWrappers.erc721Token.getApprovedIfExistsAsync( - tokenAddress, - tokenId, - ); - expect(approvalBeforeSet).to.be.undefined(); - await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId); - const approvalAfterSet = await contractWrappers.erc721Token.getApprovedIfExistsAsync(tokenAddress, tokenId); - expect(approvalAfterSet).to.be.equal(approvedAddress); - }); - }); - describe('#setProxyApprovalAsync/isProxyApprovedAsync', () => { - it('should set the proxy approval', async () => { - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - - const isProxyApprovedBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync( - tokenAddress, - tokenId, - ); - expect(isProxyApprovedBeforeSet).to.be.false(); - await contractWrappers.erc721Token.setProxyApprovalAsync(tokenAddress, tokenId); - const isProxyApprovedAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync( - tokenAddress, - tokenId, - ); - expect(isProxyApprovedAfterSet).to.be.true(); - }); - }); - describe('#subscribe', () => { - const indexFilterValues = {}; - afterEach(() => { - contractWrappers.erc721Token.unsubscribeAll(); - }); - // Hack: Mocha does not allow a test to be both async and have a `done` callback - // Since we need to await the receipt of the event in the `subscribe` callback, - // we do need both. A hack is to make the top-level a sync fn w/ a done callback and then - // wrap the rest of the test in an async block - // Source: https://github.com/mochajs/mocha/issues/2407 - it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ERC721TokenTransferEventArgs>) => { - expect(logEvent.isRemoved).to.be.false(); - expect(logEvent.log.logIndex).to.be.equal(0); - expect(logEvent.log.transactionIndex).to.be.equal(0); - expect(logEvent.log.blockNumber).to.be.a('number'); - const args = logEvent.log.args; - expect(args._from).to.be.equal(ownerAddress); - expect(args._to).to.be.equal(receiverAddress); - expect(args._tokenId).to.be.bignumber.equal(tokenId); - }, - ); - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - const isApprovedForAll = true; - await web3Wrapper.awaitTransactionSuccessAsync( - await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - isApprovedForAll, - ), - constants.AWAIT_TRANSACTION_MINED_MS, - ); - contractWrappers.erc721Token.subscribe( - tokenAddress, - ERC721TokenEvents.Transfer, - indexFilterValues, - callback, - ); - await web3Wrapper.awaitTransactionSuccessAsync( - await contractWrappers.erc721Token.transferFromAsync( - tokenAddress, - receiverAddress, - operatorAddress, - tokenId, - ), - constants.AWAIT_TRANSACTION_MINED_MS, - ); - })().catch(done); - }); - it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ERC721TokenApprovalEventArgs>) => { - expect(logEvent).to.not.be.undefined(); - expect(logEvent.isRemoved).to.be.false(); - const args = logEvent.log.args; - expect(args._owner).to.be.equal(ownerAddress); - expect(args._approved).to.be.equal(approvedAddress); - expect(args._tokenId).to.be.bignumber.equal(tokenId); - }, - ); - contractWrappers.erc721Token.subscribe( - tokenAddress, - ERC721TokenEvents.Approval, - indexFilterValues, - callback, - ); - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - await web3Wrapper.awaitTransactionSuccessAsync( - await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId), - constants.AWAIT_TRANSACTION_MINED_MS, - ); - })().catch(done); - }); - it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { - (async () => { - const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ERC721TokenApprovalEventArgs>) => { - done(new Error('Expected this subscription to have been cancelled')); - }, - ); - contractWrappers.erc721Token.subscribe( - tokenAddress, - ERC721TokenEvents.Transfer, - indexFilterValues, - callbackNeverToBeCalled, - ); - const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.unsubscribeAll(); - contractWrappers.erc721Token.subscribe( - tokenAddress, - ERC721TokenEvents.Approval, - indexFilterValues, - callbackToBeCalled, - ); - const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress); - await web3Wrapper.awaitTransactionSuccessAsync( - await contractWrappers.erc721Token.setApprovalAsync(tokenAddress, approvedAddress, tokenId), - constants.AWAIT_TRANSACTION_MINED_MS, - ); - done(); - })().catch(done); - }); - it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { - (async () => { - const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ERC721TokenApprovalForAllEventArgs>) => { - done(new Error('Expected this subscription to have been cancelled')); - }, - ); - const subscriptionToken = contractWrappers.erc721Token.subscribe( - tokenAddress, - ERC721TokenEvents.ApprovalForAll, - indexFilterValues, - callbackNeverToBeCalled, - ); - contractWrappers.erc721Token.unsubscribe(subscriptionToken); - - const isApproved = true; - await web3Wrapper.awaitTransactionSuccessAsync( - await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - isApproved, - ), - constants.AWAIT_TRANSACTION_MINED_MS, - ); - done(); - })().catch(done); - }); - }); - describe('#getLogsAsync', () => { - const blockRange: BlockRange = { - fromBlock: 0, - toBlock: BlockParamLiteral.Latest, - }; - let txHash: string; - it('should get logs with decoded args emitted by ApprovalForAll', async () => { - const isApprovedForAll = true; - txHash = await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - isApprovedForAll, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const eventName = ERC721TokenEvents.ApprovalForAll; - const indexFilterValues = {}; - const logs = await contractWrappers.erc721Token.getLogsAsync<ERC721TokenApprovalForAllEventArgs>( - tokenAddress, - eventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(1); - const args = logs[0].args; - expect(logs[0].event).to.be.equal(eventName); - expect(args._owner).to.be.equal(ownerAddress); - expect(args._operator).to.be.equal(operatorAddress); - expect(args._approved).to.be.equal(isApprovedForAll); - }); - it('should only get the logs with the correct event name', async () => { - const isApprovedForAll = true; - txHash = await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - isApprovedForAll, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const differentEventName = ERC721TokenEvents.Transfer; - const indexFilterValues = {}; - const logs = await contractWrappers.erc721Token.getLogsAsync( - tokenAddress, - differentEventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(0); - }); - it('should only get the logs with the correct indexed fields', async () => { - const isApprovedForAll = true; - txHash = await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - ownerAddress, - operatorAddress, - isApprovedForAll, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - txHash = await contractWrappers.erc721Token.setApprovalForAllAsync( - tokenAddress, - anotherOwnerAddress, - operatorAddress, - isApprovedForAll, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const eventName = ERC721TokenEvents.ApprovalForAll; - const indexFilterValues = { - _owner: anotherOwnerAddress, - }; - const logs = await contractWrappers.erc721Token.getLogsAsync<ERC721TokenApprovalForAllEventArgs>( - tokenAddress, - eventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(1); - const args = logs[0].args; - expect(args._owner).to.be.equal(anotherOwnerAddress); - }); - }); -}); -// tslint:disable:max-file-line-count - -function addEmptyWalletSubprovider(p: Provider): Provider { - const providerEngine = new Web3ProviderEngine(); - providerEngine.addProvider(new EmptyWalletSubprovider()); - const currentSubproviders = (p as any)._providers; - for (const subprovider of currentSubproviders) { - providerEngine.addProvider(subprovider); - } - providerEngine.start(); - return providerEngine; -} diff --git a/packages/contract-wrappers/test/ether_token_wrapper_test.ts b/packages/contract-wrappers/test/ether_token_wrapper_test.ts deleted file mode 100644 index cc2419aa2..000000000 --- a/packages/contract-wrappers/test/ether_token_wrapper_test.ts +++ /dev/null @@ -1,437 +0,0 @@ -import { ContractAddresses } from '@0x/contract-addresses'; -import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils'; -import { DoneCallback } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as chai from 'chai'; -import 'mocha'; - -import { - BlockParamLiteral, - BlockRange, - ContractWrappers, - ContractWrappersError, - WETH9ApprovalEventArgs, - WETH9DepositEventArgs, - WETH9Events, - WETH9TransferEventArgs, - WETH9WithdrawalEventArgs, -} from '../src'; -import { DecodedLogEvent } from '../src/types'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -// Since the address depositing/withdrawing ETH/WETH also needs to pay gas costs for the transaction, -// a small amount of ETH will be used to pay this gas cost. We therefore check that the difference between -// the expected balance and actual balance (given the amount of ETH deposited), only deviates by the amount -// required to pay gas costs. -const MAX_REASONABLE_GAS_COST_IN_WEI = 62517; - -describe('EtherTokenWrapper', () => { - let contractWrappers: ContractWrappers; - let contractAddresses: ContractAddresses; - let userAddresses: string[]; - let addressWithETH: string; - let wethContractAddress: string; - let depositWeiAmount: BigNumber; - const decimalPlaces = 7; - let addressWithoutFunds: string; - const gasPrice = new BigNumber(1); - const transferAmount = new BigNumber(42); - const allowanceAmount = new BigNumber(42); - const depositAmount = new BigNumber(42); - const withdrawalAmount = new BigNumber(42); - before(async () => { - contractAddresses = await migrateOnceAsync(); - const config = { - gasPrice, - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - addressWithETH = userAddresses[0]; - wethContractAddress = contractAddresses.etherToken; - depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5)); - addressWithoutFunds = userAddresses[1]; - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#getContractAddressIfExists', async () => { - it('should return contract address if connected to a known network', () => { - const contractAddressIfExists = contractAddresses.etherToken; - expect(contractAddressIfExists).to.not.be.undefined(); - }); - it('should throw if connected to a private network and contract addresses are not specified', () => { - const UNKNOWN_NETWORK_NETWORK_ID = 10; - expect( - () => - new ContractWrappers(provider, { - networkId: UNKNOWN_NETWORK_NETWORK_ID, - } as any), - ).to.throw(); - }); - }); - describe('#depositAsync', () => { - it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => { - const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync( - wethContractAddress, - addressWithETH, - ); - expect(preETHBalance).to.be.bignumber.gt(0); - expect(preWETHBalance).to.be.bignumber.equal(0); - - const txHash = await contractWrappers.etherToken.depositAsync( - wethContractAddress, - depositWeiAmount, - addressWithETH, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - - const postETHBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const postWETHBalanceInBaseUnits = await contractWrappers.erc20Token.getBalanceAsync( - wethContractAddress, - addressWithETH, - ); - - expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(depositWeiAmount); - const remainingETHInWei = preETHBalance.minus(depositWeiAmount); - const gasCost = remainingETHInWei.minus(postETHBalanceInWei); - expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); - }); - it('should throw if user has insufficient ETH balance for deposit', async () => { - const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); - - const extraETHBalance = Web3Wrapper.toWei(new BigNumber(5)); - const overETHBalanceinWei = preETHBalance.plus(extraETHBalance); - - return expect( - contractWrappers.etherToken.depositAsync(wethContractAddress, overETHBalanceinWei, addressWithETH), - ).to.be.rejectedWith(ContractWrappersError.InsufficientEthBalanceForDeposit); - }); - }); - describe('#withdrawAsync', () => { - it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => { - const ETHBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); - - await contractWrappers.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH); - - const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount); - const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync( - wethContractAddress, - addressWithETH, - ); - let gasCost = expectedPreETHBalance.minus(preETHBalance); - expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); - expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount); - - const txHash = await contractWrappers.etherToken.withdrawAsync( - wethContractAddress, - depositWeiAmount, - addressWithETH, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - - const postETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const postWETHBalanceInBaseUnits = await contractWrappers.erc20Token.getBalanceAsync( - wethContractAddress, - addressWithETH, - ); - - expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(0); - const expectedETHBalance = preETHBalance.plus(depositWeiAmount).integerValue(decimalPlaces); - gasCost = expectedETHBalance.minus(postETHBalance); - expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); - }); - it('should throw if user has insufficient WETH balance for withdrawal', async () => { - const preWETHBalance = await contractWrappers.erc20Token.getBalanceAsync( - wethContractAddress, - addressWithETH, - ); - expect(preWETHBalance).to.be.bignumber.equal(0); - - // tslint:disable-next-line:custom-no-magic-numbers - const overWETHBalance = preWETHBalance.plus(999999999); - - return expect( - contractWrappers.etherToken.withdrawAsync(wethContractAddress, overWETHBalance, addressWithETH), - ).to.be.rejectedWith(ContractWrappersError.InsufficientWEthBalanceForWithdrawal); - }); - }); - describe('#subscribe', () => { - const indexFilterValues = {}; - let etherTokenAddress: string; - before(async () => { - etherTokenAddress = contractAddresses.etherToken; - }); - afterEach(() => { - contractWrappers.etherToken.unsubscribeAll(); - }); - // Hack: Mocha does not allow a test to be both async and have a `done` callback - // Since we need to await the receipt of the event in the `subscribe` callback, - // we do need both. A hack is to make the top-level async fn w/ a done callback and then - // wrap the rest of the test in an async block - // Source: https://github.com/mochajs/mocha/issues/2407 - it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<WETH9TransferEventArgs>) => { - expect(logEvent).to.not.be.undefined(); - expect(logEvent.isRemoved).to.be.false(); - expect(logEvent.log.logIndex).to.be.equal(0); - expect(logEvent.log.transactionIndex).to.be.equal(0); - expect(logEvent.log.blockNumber).to.be.a('number'); - const args = logEvent.log.args; - expect(args._from).to.be.equal(addressWithETH); - expect(args._to).to.be.equal(addressWithoutFunds); - expect(args._value).to.be.bignumber.equal(transferAmount); - }, - ); - await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); - contractWrappers.etherToken.subscribe( - etherTokenAddress, - WETH9Events.Transfer, - indexFilterValues, - callback, - ); - await contractWrappers.erc20Token.transferAsync( - etherTokenAddress, - addressWithETH, - addressWithoutFunds, - transferAmount, - ); - })().catch(done); - }); - it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => { - expect(logEvent).to.not.be.undefined(); - expect(logEvent.isRemoved).to.be.false(); - const args = logEvent.log.args; - expect(args._owner).to.be.equal(addressWithETH); - expect(args._spender).to.be.equal(addressWithoutFunds); - expect(args._value).to.be.bignumber.equal(allowanceAmount); - }, - ); - contractWrappers.etherToken.subscribe( - etherTokenAddress, - WETH9Events.Approval, - indexFilterValues, - callback, - ); - await contractWrappers.erc20Token.setAllowanceAsync( - etherTokenAddress, - addressWithETH, - addressWithoutFunds, - allowanceAmount, - ); - })().catch(done); - }); - it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<WETH9DepositEventArgs>) => { - expect(logEvent).to.not.be.undefined(); - expect(logEvent.isRemoved).to.be.false(); - const args = logEvent.log.args; - expect(args._owner).to.be.equal(addressWithETH); - expect(args._value).to.be.bignumber.equal(depositAmount); - }, - ); - contractWrappers.etherToken.subscribe( - etherTokenAddress, - WETH9Events.Deposit, - indexFilterValues, - callback, - ); - await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); - })().catch(done); - }); - it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<WETH9WithdrawalEventArgs>) => { - expect(logEvent).to.not.be.undefined(); - expect(logEvent.isRemoved).to.be.false(); - const args = logEvent.log.args; - expect(args._owner).to.be.equal(addressWithETH); - expect(args._value).to.be.bignumber.equal(depositAmount); - }, - ); - await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); - contractWrappers.etherToken.subscribe( - etherTokenAddress, - WETH9Events.Withdrawal, - indexFilterValues, - callback, - ); - await contractWrappers.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH); - })().catch(done); - }); - it('should cancel outstanding subscriptions when contractWrappers.unsubscribeAll is called', (done: DoneCallback) => { - (async () => { - const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( - (_logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => { - done(new Error('Expected this subscription to have been cancelled')); - }, - ); - contractWrappers.etherToken.subscribe( - etherTokenAddress, - WETH9Events.Transfer, - indexFilterValues, - callbackNeverToBeCalled, - ); - const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.unsubscribeAll(); - await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); - contractWrappers.etherToken.subscribe( - etherTokenAddress, - WETH9Events.Transfer, - indexFilterValues, - callbackToBeCalled, - ); - await contractWrappers.erc20Token.transferAsync( - etherTokenAddress, - addressWithETH, - addressWithoutFunds, - transferAmount, - ); - })().catch(done); - }); - it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { - (async () => { - const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( - (_logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => { - done(new Error('Expected this subscription to have been cancelled')); - }, - ); - await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); - const subscriptionToken = contractWrappers.etherToken.subscribe( - etherTokenAddress, - WETH9Events.Transfer, - indexFilterValues, - callbackNeverToBeCalled, - ); - contractWrappers.etherToken.unsubscribe(subscriptionToken); - await contractWrappers.erc20Token.transferAsync( - etherTokenAddress, - addressWithETH, - addressWithoutFunds, - transferAmount, - ); - done(); - })().catch(done); - }); - }); - describe('#getLogsAsync', () => { - let etherTokenAddress: string; - let erc20ProxyAddress: string; - let blockRange: BlockRange; - let txHash: string; - before(async () => { - addressWithETH = userAddresses[0]; - etherTokenAddress = contractAddresses.etherToken; - erc20ProxyAddress = contractWrappers.erc20Proxy.address; - // Start the block range after all migrations to avoid unexpected logs - const currentBlock: number = await web3Wrapper.getBlockNumberAsync(); - const fromBlock = currentBlock + 1; - blockRange = { - fromBlock, - toBlock: BlockParamLiteral.Latest, - }; - }); - it('should get logs with decoded args emitted by Approval', async () => { - txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync( - etherTokenAddress, - addressWithETH, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const eventName = WETH9Events.Approval; - const indexFilterValues = {}; - const logs = await contractWrappers.etherToken.getLogsAsync<WETH9ApprovalEventArgs>( - etherTokenAddress, - eventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(1); - const args = logs[0].args; - expect(logs[0].event).to.be.equal(eventName); - expect(args._owner).to.be.equal(addressWithETH); - expect(args._spender).to.be.equal(erc20ProxyAddress); - expect(args._value).to.be.bignumber.equal(contractWrappers.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); - }); - it('should get logs with decoded args emitted by Deposit', async () => { - await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); - const eventName = WETH9Events.Deposit; - const indexFilterValues = {}; - const logs = await contractWrappers.etherToken.getLogsAsync<WETH9DepositEventArgs>( - etherTokenAddress, - eventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(1); - const args = logs[0].args; - expect(logs[0].event).to.be.equal(eventName); - expect(args._owner).to.be.equal(addressWithETH); - expect(args._value).to.be.bignumber.equal(depositAmount); - }); - it('should only get the logs with the correct event name', async () => { - txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync( - etherTokenAddress, - addressWithETH, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const differentEventName = WETH9Events.Transfer; - const indexFilterValues = {}; - const logs = await contractWrappers.etherToken.getLogsAsync( - etherTokenAddress, - differentEventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(0); - }); - it('should only get the logs with the correct indexed fields', async () => { - txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync( - etherTokenAddress, - addressWithETH, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync( - etherTokenAddress, - addressWithoutFunds, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const eventName = WETH9Events.Approval; - const indexFilterValues = { - _owner: addressWithETH, - }; - const logs = await contractWrappers.etherToken.getLogsAsync<WETH9ApprovalEventArgs>( - etherTokenAddress, - eventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(1); - const args = logs[0].args; - expect(args._owner).to.be.equal(addressWithETH); - }); - }); -}); diff --git a/packages/contract-wrappers/test/exchange_wrapper_test.ts b/packages/contract-wrappers/test/exchange_wrapper_test.ts deleted file mode 100644 index a1d60dc6e..000000000 --- a/packages/contract-wrappers/test/exchange_wrapper_test.ts +++ /dev/null @@ -1,528 +0,0 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0x/dev-utils'; -import { FillScenarios } from '@0x/fill-scenarios'; -import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; -import { DoneCallback, RevertReason, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import { BlockParamLiteral } from 'ethereum-types'; -import 'mocha'; - -import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src'; -import { DecodedLogEvent } from '../src/types'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -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('ExchangeWrapper', () => { - let contractWrappers: ContractWrappers; - let userAddresses: string[]; - let zrxTokenAddress: string; - let fillScenarios: FillScenarios; - let exchangeContractAddress: string; - let makerTokenAddress: string; - let takerTokenAddress: string; - let makerAddress: string; - let anotherMakerAddress: string; - let takerAddress: string; - let makerAssetData: string; - let takerAssetData: string; - let txHash: string; - const fillableAmount = new BigNumber(5); - const takerTokenFillAmount = new BigNumber(5); - let signedOrder: SignedOrder; - let anotherSignedOrder: SignedOrder; - - before(async () => { - const contractAddresses = await migrateOnceAsync(); - await blockchainLifecycle.startAsync(); - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - exchangeContractAddress = contractWrappers.exchange.address; - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; - fillScenarios = new FillScenarios( - provider, - userAddresses, - zrxTokenAddress, - exchangeContractAddress, - contractWrappers.erc20Proxy.address, - contractWrappers.erc721Proxy.address, - ); - [, makerAddress, takerAddress, , anotherMakerAddress] = userAddresses; - [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - [makerAssetData, takerAssetData] = [ - assetDataUtils.encodeERC20AssetData(makerTokenAddress), - assetDataUtils.encodeERC20AssetData(takerTokenAddress), - ]; - signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerAssetData, - takerAssetData, - makerAddress, - takerAddress, - fillableAmount, - ); - anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerAssetData, - takerAssetData, - makerAddress, - takerAddress, - fillableAmount, - ); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('fill order(s)', () => { - describe('#fillOrderAsync', () => { - it('should fill a valid order', async () => { - txHash = await contractWrappers.exchange.fillOrderAsync( - signedOrder, - takerTokenFillAmount, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#fillOrderNoThrowAsync', () => { - it('should fill a valid order', async () => { - txHash = await contractWrappers.exchange.fillOrderNoThrowAsync( - signedOrder, - takerTokenFillAmount, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder); - expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled); - }); - }); - describe('#fillOrKillOrderAsync', () => { - it('should fill or kill a valid order', async () => { - txHash = await contractWrappers.exchange.fillOrKillOrderAsync( - signedOrder, - takerTokenFillAmount, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#batchFillOrdersAsync', () => { - it('should fill a batch of valid orders', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount]; - txHash = await contractWrappers.exchange.batchFillOrdersAsync( - signedOrders, - takerAssetFillAmounts, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#marketBuyOrdersAsync', () => { - it('should maker buy', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const makerAssetFillAmount = takerTokenFillAmount; - txHash = await contractWrappers.exchange.marketBuyOrdersAsync( - signedOrders, - makerAssetFillAmount, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#marketBuyOrdersNoThrowAsync', () => { - it('should no throw maker buy', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const makerAssetFillAmount = takerTokenFillAmount; - txHash = await contractWrappers.exchange.marketBuyOrdersNoThrowAsync( - signedOrders, - makerAssetFillAmount, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder); - expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled); - }); - }); - describe('#marketSellOrdersAsync', () => { - it('should maker sell', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const takerAssetFillAmount = takerTokenFillAmount; - txHash = await contractWrappers.exchange.marketSellOrdersAsync( - signedOrders, - takerAssetFillAmount, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#marketSellOrdersNoThrowAsync', () => { - it('should no throw maker sell', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const takerAssetFillAmount = takerTokenFillAmount; - txHash = await contractWrappers.exchange.marketSellOrdersNoThrowAsync( - signedOrders, - takerAssetFillAmount, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder); - expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled); - }); - }); - describe('#batchFillOrdersNoThrowAsync', () => { - it('should fill a batch of valid orders', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount]; - txHash = await contractWrappers.exchange.batchFillOrdersNoThrowAsync( - signedOrders, - takerAssetFillAmounts, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - let orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder); - expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled); - orderInfo = await contractWrappers.exchange.getOrderInfoAsync(anotherSignedOrder); - expect(orderInfo.orderStatus).to.be.equal(OrderStatus.FullyFilled); - }); - }); - describe('#batchFillOrKillOrdersAsync', () => { - it('should fill or kill a batch of valid orders', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount]; - txHash = await contractWrappers.exchange.batchFillOrKillOrdersAsync( - signedOrders, - takerAssetFillAmounts, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#matchOrdersAsync', () => { - it('should match two valid ordersr', async () => { - const matchingSignedOrder = await fillScenarios.createFillableSignedOrderAsync( - takerAssetData, - makerAssetData, - makerAddress, - takerAddress, - fillableAmount, - ); - txHash = await contractWrappers.exchange.matchOrdersAsync( - signedOrder, - matchingSignedOrder, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - }); - describe('cancel order(s)', () => { - describe('#cancelOrderAsync', () => { - it('should cancel a valid order', async () => { - txHash = await contractWrappers.exchange.cancelOrderAsync(signedOrder); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#batchCancelOrdersAsync', () => { - it('should cancel a batch of valid orders', async () => { - const orders = [signedOrder, anotherSignedOrder]; - txHash = await contractWrappers.exchange.batchCancelOrdersAsync(orders); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#cancelOrdersUpTo/getOrderEpochAsync', () => { - it('should cancel orders up to target order epoch', async () => { - const targetOrderEpoch = new BigNumber(42); - txHash = await contractWrappers.exchange.cancelOrdersUpToAsync(targetOrderEpoch, makerAddress); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const orderEpoch = await contractWrappers.exchange.getOrderEpochAsync( - makerAddress, - constants.NULL_ADDRESS, - ); - expect(orderEpoch).to.be.bignumber.equal(targetOrderEpoch.plus(1)); - }); - }); - }); - describe('#getZRXAssetData', () => { - it('should get the asset data', () => { - const ZRX_ASSET_DATA = contractWrappers.exchange.getZRXAssetData(); - const ASSET_DATA_HEX_LENGTH = 74; - expect(ZRX_ASSET_DATA).to.have.length(ASSET_DATA_HEX_LENGTH); - }); - }); - describe('#getOrderInfoAsync', () => { - it('should get the order info', async () => { - const orderInfo = await contractWrappers.exchange.getOrderInfoAsync(signedOrder); - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - expect(orderInfo.orderHash).to.be.equal(orderHash); - }); - }); - describe('#getOrdersInfoAsync', () => { - it('should get the orders info', async () => { - const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]); - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - expect(ordersInfo[0].orderHash).to.be.equal(orderHash); - const anotherOrderHash = orderHashUtils.getOrderHashHex(anotherSignedOrder); - expect(ordersInfo[1].orderHash).to.be.equal(anotherOrderHash); - }); - }); - describe('#validateOrderFillableOrThrowAsync', () => { - it('should throw if signature is invalid', async () => { - const signedOrderWithInvalidSignature = { - ...signedOrder, - signature: - '0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403', - }; - - expect( - contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrderWithInvalidSignature), - ).to.eventually.to.be.rejectedWith(RevertReason.InvalidOrderSignature); - }); - }); - describe('#isValidSignature', () => { - it('should check if the signature is valid', async () => { - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - let isValid = await contractWrappers.exchange.isValidSignatureAsync( - orderHash, - signedOrder.makerAddress, - signedOrder.signature, - ); - expect(isValid).to.be.true(); - isValid = await contractWrappers.exchange.isValidSignatureAsync( - orderHash, - signedOrder.takerAddress, - signedOrder.signature, - ); - expect(isValid).to.be.false(); - }); - }); - describe('#isAllowedValidatorAsync', () => { - it('should check if the validator is allowed', async () => { - const signerAddress = makerAddress; - const validatorAddress = constants.NULL_ADDRESS; - const isAllowed = await contractWrappers.exchange.isAllowedValidatorAsync(signerAddress, validatorAddress); - expect(isAllowed).to.be.false(); - }); - }); - describe('#setSignatureValidatorApproval', () => { - it('should set signature validator approval', async () => { - const validatorAddress = constants.NULL_ADDRESS; - const isApproved = true; - const senderAddress = makerAddress; - txHash = await contractWrappers.exchange.setSignatureValidatorApprovalAsync( - validatorAddress, - isApproved, - senderAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }); - }); - describe('#isTransactionExecutedAsync', () => { - it('should check if the transaction is executed', async () => { - const transactionHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; - const isExecuted = await contractWrappers.exchange.isTransactionExecutedAsync(transactionHash); - expect(isExecuted).to.be.false(); - }); - }); - describe('#getAssetProxyBySignatureAsync', () => { - it('should fill or kill a valid order', async () => { - const erc20ProxyId = await contractWrappers.erc20Proxy.getProxyIdAsync(); - const erc20ProxyAddressById = await contractWrappers.exchange.getAssetProxyBySignatureAsync(erc20ProxyId); - const erc20ProxyAddress = contractWrappers.erc20Proxy.address; - expect(erc20ProxyAddressById).to.be.equal(erc20ProxyAddress); - const erc721ProxyId = await contractWrappers.erc721Proxy.getProxyIdAsync(); - const erc721ProxyAddressById = await contractWrappers.exchange.getAssetProxyBySignatureAsync(erc721ProxyId); - const erc721ProxyAddress = contractWrappers.erc721Proxy.address; - expect(erc721ProxyAddressById).to.be.equal(erc721ProxyAddress); - }); - }); - describe('#preSignAsync/isPreSignedAsync', () => { - it('should preSign the hash', async () => { - const senderAddress = takerAddress; - const hash = orderHashUtils.getOrderHashHex(signedOrder); - const signerAddress = signedOrder.makerAddress; - let isPreSigned = await contractWrappers.exchange.isPreSignedAsync(hash, signerAddress); - expect(isPreSigned).to.be.false(); - txHash = await contractWrappers.exchange.preSignAsync( - hash, - signerAddress, - signedOrder.signature, - senderAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - isPreSigned = await contractWrappers.exchange.isPreSignedAsync(hash, signerAddress); - expect(isPreSigned).to.be.true(); - }); - }); - describe('#getVersionAsync', () => { - it('should return version the hash', async () => { - const version = await contractWrappers.exchange.getVersionAsync(); - const VERSION = '2.0.0'; - expect(version).to.be.equal(VERSION); - }); - }); - describe('#subscribe', () => { - const indexFilterValues = {}; - const takerTokenFillAmountInBaseUnits = new BigNumber(1); - beforeEach(async () => { - signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerAssetData, - takerAssetData, - makerAddress, - takerAddress, - fillableAmount, - ); - }); - afterEach(async () => { - contractWrappers.exchange.unsubscribeAll(); - }); - // Hack: Mocha does not allow a test to be both async and have a `done` callback - // Since we need to await the receipt of the event in the `subscribe` callback, - // we do need both. A hack is to make the top-level a sync fn w/ a done callback and then - // wrap the rest of the test in an async block - // Source: https://github.com/mochajs/mocha/issues/2407 - it('Should receive the Fill event when an order is filled', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ExchangeFillEventArgs>) => { - expect(logEvent.log.event).to.be.equal(ExchangeEvents.Fill); - }, - ); - contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callback); - await contractWrappers.exchange.fillOrderAsync( - signedOrder, - takerTokenFillAmountInBaseUnits, - takerAddress, - ); - })().catch(done); - }); - it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => { - (async () => { - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ExchangeCancelEventArgs>) => { - expect(logEvent.log.event).to.be.equal(ExchangeEvents.Cancel); - }, - ); - contractWrappers.exchange.subscribe(ExchangeEvents.Cancel, indexFilterValues, callback); - await contractWrappers.exchange.cancelOrderAsync(signedOrder); - })().catch(done); - }); - it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { - (async () => { - const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ExchangeFillEventArgs>) => { - done(new Error('Expected this subscription to have been cancelled')); - }, - ); - contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callbackNeverToBeCalled); - - contractWrappers.unsubscribeAll(); - - const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( - (logEvent: DecodedLogEvent<ExchangeFillEventArgs>) => { - expect(logEvent.log.event).to.be.equal(ExchangeEvents.Fill); - }, - ); - contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callback); - await contractWrappers.exchange.fillOrderAsync( - signedOrder, - takerTokenFillAmountInBaseUnits, - takerAddress, - ); - })().catch(done); - }); - it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { - (async () => { - const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( - (_logEvent: DecodedLogEvent<ExchangeFillEventArgs>) => { - done(new Error('Expected this subscription to have been cancelled')); - }, - ); - const subscriptionToken = contractWrappers.exchange.subscribe( - ExchangeEvents.Fill, - indexFilterValues, - callbackNeverToBeCalled, - ); - contractWrappers.exchange.unsubscribe(subscriptionToken); - await contractWrappers.exchange.fillOrderAsync( - signedOrder, - takerTokenFillAmountInBaseUnits, - takerAddress, - ); - done(); - })().catch(done); - }); - }); - describe('#getLogsAsync', () => { - const blockRange = { - fromBlock: 0, - toBlock: BlockParamLiteral.Latest, - }; - it('should get logs with decoded args emitted by Fill', async () => { - txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress); - const eventName = ExchangeEvents.Fill; - const indexFilterValues = {}; - const logs = await contractWrappers.exchange.getLogsAsync(eventName, blockRange, indexFilterValues); - expect(logs).to.have.length(1); - expect(logs[0].event).to.be.equal(eventName); - }); - it('should only get the logs with the correct event name', async () => { - txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const differentEventName = ExchangeEvents.Cancel; - const indexFilterValues = {}; - const logs = await contractWrappers.exchange.getLogsAsync( - differentEventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(0); - }); - it('should only get the logs with the correct indexed fields', async () => { - txHash = await contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const signedOrderWithAnotherMakerAddress = await fillScenarios.createFillableSignedOrderAsync( - makerAssetData, - takerAssetData, - anotherMakerAddress, - takerAddress, - fillableAmount, - ); - txHash = await contractWrappers.exchange.fillOrderAsync( - signedOrderWithAnotherMakerAddress, - takerTokenFillAmount, - takerAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - - const eventName = ExchangeEvents.Fill; - const indexFilterValues = { - makerAddress: anotherMakerAddress, - }; - const logs = await contractWrappers.exchange.getLogsAsync<ExchangeFillEventArgs>( - eventName, - blockRange, - indexFilterValues, - ); - expect(logs).to.have.length(1); - const args = logs[0].args; - expect(args.makerAddress).to.be.equal(anotherMakerAddress); - }); - }); -}); // tslint:disable:max-file-line-count diff --git a/packages/contract-wrappers/test/forwarder_wrapper_test.ts b/packages/contract-wrappers/test/forwarder_wrapper_test.ts deleted file mode 100644 index 0d197eced..000000000 --- a/packages/contract-wrappers/test/forwarder_wrapper_test.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { FillScenarios } from '@0x/fill-scenarios'; -import { assetDataUtils } from '@0x/order-utils'; -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { ContractWrappers, OrderStatus } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -import { tokenUtils } from './utils/token_utils'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -// tslint:disable:custom-no-magic-numbers -describe('ForwarderWrapper', () => { - const fillableAmount = new BigNumber(5); - let contractWrappers: ContractWrappers; - let fillScenarios: FillScenarios; - let exchangeContractAddress: string; - let zrxTokenAddress: string; - let userAddresses: string[]; - let makerAddress: string; - let takerAddress: string; - let makerTokenAddress: string; - let takerTokenAddress: string; - let makerAssetData: string; - let takerAssetData: string; - let signedOrder: SignedOrder; - let anotherSignedOrder: SignedOrder; - before(async () => { - const contractAddresses = await migrateOnceAsync(); - await blockchainLifecycle.startAsync(); - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - exchangeContractAddress = contractWrappers.exchange.address; - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; - fillScenarios = new FillScenarios( - provider, - userAddresses, - zrxTokenAddress, - exchangeContractAddress, - contractWrappers.erc20Proxy.address, - contractWrappers.erc721Proxy.address, - ); - [, makerAddress, takerAddress] = userAddresses; - [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - takerTokenAddress = contractWrappers.forwarder.etherTokenAddress; - [makerAssetData, takerAssetData] = [ - assetDataUtils.encodeERC20AssetData(makerTokenAddress), - assetDataUtils.encodeERC20AssetData(takerTokenAddress), - ]; - signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerAssetData, - takerAssetData, - makerAddress, - constants.NULL_ADDRESS, - fillableAmount, - ); - anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerAssetData, - takerAssetData, - makerAddress, - constants.NULL_ADDRESS, - fillableAmount, - ); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#marketBuyOrdersWithEthAsync', () => { - it('should market buy orders with eth', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(anotherSignedOrder.makerAssetAmount); - const txHash = await contractWrappers.forwarder.marketBuyOrdersWithEthAsync( - signedOrders, - makerAssetFillAmount, - takerAddress, - makerAssetFillAmount, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]); - expect(ordersInfo[0].orderStatus).to.be.equal(OrderStatus.FullyFilled); - expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.FullyFilled); - }); - it('should throw when invalid transaction and shouldValidate is true', async () => { - const signedOrders = [signedOrder]; - // request more makerAsset than what is available - const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(100); - return expect( - contractWrappers.forwarder.marketBuyOrdersWithEthAsync( - signedOrders, - makerAssetFillAmount, - takerAddress, - makerAssetFillAmount, - [], - 0, - constants.NULL_ADDRESS, - { - shouldValidate: true, - }, - ), - ).to.be.rejectedWith('COMPLETE_FILL_FAILED'); - }); - }); - describe('#marketSellOrdersWithEthAsync', () => { - it('should market sell orders with eth', async () => { - const signedOrders = [signedOrder, anotherSignedOrder]; - const makerAssetFillAmount = signedOrder.makerAssetAmount.plus(anotherSignedOrder.makerAssetAmount); - const txHash = await contractWrappers.forwarder.marketSellOrdersWithEthAsync( - signedOrders, - takerAddress, - makerAssetFillAmount, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - const ordersInfo = await contractWrappers.exchange.getOrdersInfoAsync([signedOrder, anotherSignedOrder]); - expect(ordersInfo[0].orderStatus).to.be.equal(OrderStatus.FullyFilled); - expect(ordersInfo[1].orderStatus).to.be.equal(OrderStatus.Fillable); - expect(ordersInfo[1].orderTakerAssetFilledAmount).to.be.bignumber.equal(new BigNumber(4)); // only 95% of ETH is sold - }); - it('should throw when invalid transaction and shouldValidate is true', async () => { - // create an order with fees, we try to fill it but we do not provide enough ETH to cover the fees - const signedOrderWithFee = await fillScenarios.createFillableSignedOrderWithFeesAsync( - makerAssetData, - takerAssetData, - constants.ZERO_AMOUNT, - new BigNumber(100), - makerAddress, - constants.NULL_ADDRESS, - fillableAmount, - constants.NULL_ADDRESS, - ); - const signedOrders = [signedOrderWithFee]; - const makerAssetFillAmount = signedOrder.makerAssetAmount; - return expect( - contractWrappers.forwarder.marketSellOrdersWithEthAsync( - signedOrders, - takerAddress, - makerAssetFillAmount, - [], - 0, - constants.NULL_ADDRESS, - { - shouldValidate: true, - }, - ), - ).to.be.rejectedWith('COMPLETE_FILL_FAILED'); - }); - }); -}); diff --git a/packages/contract-wrappers/test/global_hooks.ts b/packages/contract-wrappers/test/global_hooks.ts deleted file mode 100644 index e23739b59..000000000 --- a/packages/contract-wrappers/test/global_hooks.ts +++ /dev/null @@ -1,6 +0,0 @@ -before('set up mocha', async function(): Promise<void> { - // HACK: Since the migrations take longer then our global mocha timeout limit - // we manually increase it for this before hook. - const mochaTestTimeoutMs = 50000; - this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this -}); diff --git a/packages/contract-wrappers/test/order_validator_wrapper_test.ts b/packages/contract-wrappers/test/order_validator_wrapper_test.ts deleted file mode 100644 index c61c05d31..000000000 --- a/packages/contract-wrappers/test/order_validator_wrapper_test.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { ContractAddresses } from '@0x/contract-addresses'; -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { FillScenarios } from '@0x/fill-scenarios'; -import { assetDataUtils } from '@0x/order-utils'; -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import * as _ from 'lodash'; -import 'mocha'; - -import { ContractWrappers, OrderStatus } from '../src'; -import { OrderInfo, TraderInfo } from '../src/types'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -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 fillableAmount = new BigNumber(5); - 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; - let contractAddresses: ContractAddresses; - - before(async () => { - contractAddresses = await migrateOnceAsync(); - await blockchainLifecycle.startAsync(); - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - exchangeContractAddress = contractWrappers.exchange.address; - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; - zrxTokenAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress); - fillScenarios = new FillScenarios( - provider, - userAddresses, - zrxTokenAddress, - exchangeContractAddress, - contractWrappers.erc20Proxy.address, - contractWrappers.erc721Proxy.address, - ); - [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; - [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - takerTokenAddress = contractAddresses.etherToken; - [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)); - }); - }); -}); diff --git a/packages/contract-wrappers/test/revert_validation_test.ts b/packages/contract-wrappers/test/revert_validation_test.ts deleted file mode 100644 index efd5dd61f..000000000 --- a/packages/contract-wrappers/test/revert_validation_test.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { BlockchainLifecycle, devConstants, web3Factory } from '@0x/dev-utils'; -import { FillScenarios } from '@0x/fill-scenarios'; -import { runMigrationsAsync } from '@0x/migrations'; -import { assetDataUtils } from '@0x/order-utils'; -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as chai from 'chai'; -import 'mocha'; - -import { ContractWrappers } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { tokenUtils } from './utils/token_utils'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('Revert Validation ExchangeWrapper', () => { - let contractWrappers: ContractWrappers; - let userAddresses: string[]; - let fillScenarios: FillScenarios; - let makerTokenAddress: string; - let takerTokenAddress: string; - let makerAddress: string; - let takerAddress: string; - let makerAssetData: string; - let takerAssetData: string; - let txHash: string; - let blockchainLifecycle: BlockchainLifecycle; - let web3Wrapper: Web3Wrapper; - const fillableAmount = new BigNumber(5); - const takerTokenFillAmount = new BigNumber(5); - let signedOrder: SignedOrder; - before(async () => { - // vmErrorsOnRPCResponse is useful for quick feedback and testing during development - // but is not the default behaviour in production. Here we ensure our failure cases - // are handled in an environment which behaves similar to production - const provider = web3Factory.getRpcProvider({ - shouldUseInProcessGanache: true, - shouldThrowErrorsOnGanacheRPCResponse: false, - }); - web3Wrapper = new Web3Wrapper(provider); - blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - // Re-deploy the artifacts in this provider, rather than in the default provider exposed in - // the beforeAll hook. This is due to the fact that the default provider enabled vmErrorsOnRPCResponse - // and we are explicity testing with vmErrorsOnRPCResponse disabled. - const txDefaults = { - gas: devConstants.GAS_LIMIT, - from: devConstants.TESTRPC_FIRST_ADDRESS, - }; - await blockchainLifecycle.startAsync(); - const contractAddresses = await runMigrationsAsync(provider, txDefaults); - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - fillScenarios = new FillScenarios( - provider, - userAddresses, - contractAddresses.zrxToken, - contractAddresses.exchange, - contractAddresses.erc20Proxy, - contractAddresses.erc721Proxy, - ); - [, makerAddress, takerAddress] = userAddresses; - [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - [makerAssetData, takerAssetData] = [ - assetDataUtils.encodeERC20AssetData(makerTokenAddress), - assetDataUtils.encodeERC20AssetData(takerTokenAddress), - ]; - signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerAssetData, - takerAssetData, - makerAddress, - takerAddress, - fillableAmount, - ); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#fillOrderAsync', () => { - it('should throw the revert reason when shouldValidate is true and a fill would revert', async () => { - // Create a scenario where the fill will revert - const makerTokenBalance = await contractWrappers.erc20Token.getBalanceAsync( - makerTokenAddress, - makerAddress, - ); - // Transfer all of the tokens from maker to create a failure scenario - txHash = await contractWrappers.erc20Token.transferAsync( - makerTokenAddress, - makerAddress, - takerAddress, - makerTokenBalance, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - return expect( - contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress, { - shouldValidate: true, - }), - ).to.be.rejectedWith('TRANSFER_FAILED'); - }); - }); -}); diff --git a/packages/contract-wrappers/test/subscription_test.ts b/packages/contract-wrappers/test/subscription_test.ts deleted file mode 100644 index 0fa6af40d..000000000 --- a/packages/contract-wrappers/test/subscription_test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { DoneCallback } from '@0x/types'; -import * as _ from 'lodash'; -import 'mocha'; -import * as Sinon from 'sinon'; - -import { - ContractWrappers, - ContractWrappersConfig, - DecodedLogEvent, - ERC20TokenApprovalEventArgs, - ERC20TokenEvents, -} from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -import { tokenUtils } from './utils/token_utils'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -describe('SubscriptionTest', () => { - let contractWrappers: ContractWrappers; - let config: ContractWrappersConfig; - - before(async () => { - const contractAddresses = await migrateOnceAsync(); - config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - }; - contractWrappers = new ContractWrappers(provider, config); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#subscribe', () => { - const indexFilterValues = {}; - let tokenAddress: string; - let stubs: Sinon.SinonStub[] = []; - before(() => { - const tokenAddresses = tokenUtils.getDummyERC20TokenAddresses(); - tokenAddress = tokenAddresses[0]; - }); - afterEach(() => { - contractWrappers.erc20Token.unsubscribeAll(); - _.each(stubs, s => s.restore()); - stubs = []; - }); - it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => { - (async () => { - const callback = (err: Error | null, _logEvent?: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => - _.noop.bind(_); - contractWrappers.erc20Token.subscribe( - tokenAddress, - ERC20TokenEvents.Approval, - indexFilterValues, - callback, - ); - stubs = [ - Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockIfExistsAsync').throws( - new Error('JSON RPC error'), - ), - ]; - contractWrappers.erc20Token.unsubscribeAll(); - done(); - })().catch(done); - }); - }); -}); diff --git a/packages/contract-wrappers/test/transaction_encoder_test.ts b/packages/contract-wrappers/test/transaction_encoder_test.ts deleted file mode 100644 index ef9eb2cf3..000000000 --- a/packages/contract-wrappers/test/transaction_encoder_test.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { BlockchainLifecycle } from '@0x/dev-utils'; -import { FillScenarios } from '@0x/fill-scenarios'; -import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils, signatureUtils } from '@0x/order-utils'; -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import 'mocha'; - -import { ContractWrappers } from '../src'; -import { TransactionEncoder } from '../src/utils/transaction_encoder'; - -import { constants } from './utils/constants'; -import { migrateOnceAsync } from './utils/migrate'; -import { tokenUtils } from './utils/token_utils'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; - -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -describe('TransactionEncoder', () => { - let contractWrappers: ContractWrappers; - let userAddresses: string[]; - let fillScenarios: FillScenarios; - let exchangeContractAddress: string; - let makerTokenAddress: string; - let takerTokenAddress: string; - let coinbase: string; - let makerAddress: string; - let senderAddress: string; - let takerAddress: string; - let makerAssetData: string; - let takerAssetData: string; - let txHash: string; - const fillableAmount = new BigNumber(5); - const takerTokenFillAmount = new BigNumber(5); - let signedOrder: SignedOrder; - - before(async () => { - const contractAddresses = await migrateOnceAsync(); - await blockchainLifecycle.startAsync(); - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - contractAddresses, - blockPollingIntervalMs: 10, - }; - contractWrappers = new ContractWrappers(provider, config); - exchangeContractAddress = contractWrappers.exchange.address; - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - const zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; - fillScenarios = new FillScenarios( - provider, - userAddresses, - zrxTokenAddress, - exchangeContractAddress, - contractWrappers.erc20Proxy.address, - contractWrappers.erc721Proxy.address, - ); - [coinbase, makerAddress, takerAddress, senderAddress] = userAddresses; - [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - [makerAssetData, takerAssetData] = [ - assetDataUtils.encodeERC20AssetData(makerTokenAddress), - assetDataUtils.encodeERC20AssetData(takerTokenAddress), - ]; - signedOrder = await fillScenarios.createFillableSignedOrderAsync( - makerAssetData, - takerAssetData, - makerAddress, - takerAddress, - fillableAmount, - ); - }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('encode and executeTransaction', () => { - const executeTransactionOrThrowAsync = async ( - encoder: TransactionEncoder, - data: string, - signerAddress: string = takerAddress, - ): Promise<void> => { - const salt = generatePseudoRandomSalt(); - const encodedTransaction = encoder.getTransactionHex(data, salt, signerAddress); - const signature = await signatureUtils.ecSignHashAsync(provider, encodedTransaction, signerAddress); - txHash = await contractWrappers.exchange.executeTransactionAsync( - salt, - signerAddress, - data, - signature, - senderAddress, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - }; - describe('#fillOrderTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.fillOrderTx(signedOrder, takerTokenFillAmount); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#fillOrderNoThrowTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.fillOrderNoThrowTx(signedOrder, takerTokenFillAmount); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#fillOrKillOrderTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.fillOrKillOrderTx(signedOrder, takerTokenFillAmount); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#marketSellOrdersTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.marketSellOrdersTx([signedOrder], takerTokenFillAmount); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#marketSellOrdersNoThrowTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.marketSellOrdersNoThrowTx([signedOrder], takerTokenFillAmount); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#marketBuyOrdersTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.marketBuyOrdersTx([signedOrder], fillableAmount); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#marketBuyOrdersNoThrowTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.marketBuyOrdersNoThrowTx([signedOrder], fillableAmount); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#preSignTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - const signature = signedOrder.signature; - const data = encoder.preSignTx(orderHash, makerAddress, signature); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#setSignatureValidatorApprovalTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const isApproved = true; - const data = encoder.setSignatureValidatorApprovalTx(senderAddress, isApproved); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#batchFillOrdersTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.batchFillOrdersTx([signedOrder], [takerTokenFillAmount]); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#batchFillOrKillOrdersTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.batchFillOrKillOrdersTx([signedOrder], [takerTokenFillAmount]); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#batchFillOrdersNoThrowTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.batchFillOrdersNoThrowTx([signedOrder], [takerTokenFillAmount]); - await executeTransactionOrThrowAsync(encoder, data); - }); - }); - describe('#batchCancelOrdersTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.batchCancelOrdersTx([signedOrder]); - const signerAddress = makerAddress; - await executeTransactionOrThrowAsync(encoder, data, signerAddress); - }); - }); - describe('#cancelOrderTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const data = encoder.cancelOrderTx(signedOrder); - const signerAddress = makerAddress; - await executeTransactionOrThrowAsync(encoder, data, signerAddress); - }); - }); - describe('#cancelOrdersUpToTx', () => { - it('should successfully execute the transaction', async () => { - const encoder = await contractWrappers.exchange.transactionEncoderAsync(); - const targetEpoch = signedOrder.salt; - const data = encoder.cancelOrdersUpToTx(targetEpoch); - const signerAddress = makerAddress; - await executeTransactionOrThrowAsync(encoder, data, signerAddress); - }); - }); - }); -}); diff --git a/packages/contract-wrappers/test/utils/chai_setup.ts b/packages/contract-wrappers/test/utils/chai_setup.ts deleted file mode 100644 index 1a8733093..000000000 --- a/packages/contract-wrappers/test/utils/chai_setup.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as chai from 'chai'; -import chaiAsPromised = require('chai-as-promised'); -import ChaiBigNumber = require('chai-bignumber'); -import * as dirtyChai from 'dirty-chai'; - -export const chaiSetup = { - configure(): void { - chai.config.includeStack = true; - chai.use(ChaiBigNumber()); - chai.use(dirtyChai); - chai.use(chaiAsPromised); - }, -}; diff --git a/packages/contract-wrappers/test/utils/constants.ts b/packages/contract-wrappers/test/utils/constants.ts deleted file mode 100644 index ca6c574e4..000000000 --- a/packages/contract-wrappers/test/utils/constants.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -export const constants = { - NULL_ADDRESS: '0x0000000000000000000000000000000000000000', - ROPSTEN_NETWORK_ID: 3, - KOVAN_NETWORK_ID: 42, - TESTRPC_NETWORK_ID: 50, - AWAIT_TRANSACTION_MINED_MS: 0, - KOVAN_RPC_URL: 'https://kovan.infura.io/', - ROPSTEN_RPC_URL: 'https://ropsten.infura.io/', - ZRX_DECIMALS: 18, - DUMMY_TOKEN_NAME: '', - DUMMY_TOKEN_SYMBOL: '', - DUMMY_TOKEN_DECIMALS: 18, - DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(10 ** 27), // tslint:disable-line:custom-no-magic-numbers - NUM_DUMMY_ERC20_TO_DEPLOY: 3, - NUM_DUMMY_ERC721_TO_DEPLOY: 1, - ZERO_AMOUNT: new BigNumber(0), -}; diff --git a/packages/contract-wrappers/test/utils/dutch_auction_utils.ts b/packages/contract-wrappers/test/utils/dutch_auction_utils.ts deleted file mode 100644 index 8e2aef217..000000000 --- a/packages/contract-wrappers/test/utils/dutch_auction_utils.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { DummyERC20TokenContract } from '@0x/abi-gen-wrappers'; -import * as artifacts from '@0x/contract-artifacts'; -import { assetDataUtils } from '@0x/order-utils'; -import { orderFactory } from '@0x/order-utils/lib/src/order_factory'; -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; - -import { DutchAuctionWrapper } from '../../src/contract_wrappers/dutch_auction_wrapper'; - -import { constants } from './constants'; - -export class DutchAuctionUtils { - private readonly _web3Wrapper: Web3Wrapper; - private readonly _coinbase: string; - private readonly _exchangeAddress: string; - private readonly _erc20ProxyAddress: string; - - constructor(web3Wrapper: Web3Wrapper, coinbase: string, exchangeAddress: string, erc20ProxyAddress: string) { - this._web3Wrapper = web3Wrapper; - this._coinbase = coinbase; - this._exchangeAddress = exchangeAddress; - this._erc20ProxyAddress = erc20ProxyAddress; - } - public async createSignedSellOrderAsync( - auctionBeginTimeSections: BigNumber, - acutionEndTimeSeconds: BigNumber, - auctionBeginTakerAssetAmount: BigNumber, - auctionEndTakerAssetAmount: BigNumber, - makerAssetAmount: BigNumber, - makerAssetData: string, - takerAssetData: string, - makerAddress: string, - takerAddress: string, - senderAddress?: string, - makerFee?: BigNumber, - takerFee?: BigNumber, - feeRecipientAddress?: string, - ): Promise<SignedOrder> { - // Notes on sell order: - // - The `takerAssetAmount` is set to the `auctionEndTakerAssetAmount`, which is the lowest amount the - // the seller can expect to receive - // - The `makerAssetData` is overloaded to include the auction begin time and begin taker asset amount - const makerAssetDataWithAuctionDetails = DutchAuctionWrapper.encodeDutchAuctionAssetData( - makerAssetData, - auctionBeginTimeSections, - auctionBeginTakerAssetAmount, - ); - const signedOrder = await orderFactory.createSignedOrderAsync( - this._web3Wrapper.getProvider(), - makerAddress, - makerAssetAmount, - makerAssetDataWithAuctionDetails, - auctionEndTakerAssetAmount, - takerAssetData, - this._exchangeAddress, - { - takerAddress, - senderAddress, - makerFee, - takerFee, - feeRecipientAddress, - expirationTimeSeconds: acutionEndTimeSeconds, - }, - ); - const erc20AssetData = assetDataUtils.decodeERC20AssetData(makerAssetData); - await this._increaseERC20BalanceAndAllowanceAsync(erc20AssetData.tokenAddress, makerAddress, makerAssetAmount); - return signedOrder; - } - public async createSignedBuyOrderAsync( - sellOrder: SignedOrder, - buyerAddress: string, - senderAddress?: string, - makerFee?: BigNumber, - takerFee?: BigNumber, - feeRecipientAddress?: string, - expirationTimeSeconds?: BigNumber, - ): Promise<SignedOrder> { - const dutchAuctionData = DutchAuctionWrapper.decodeDutchAuctionData(sellOrder.makerAssetData); - // Notes on buy order: - // - The `makerAssetAmount` is set to `dutchAuctionData.beginAmount`, which is - // the highest amount the buyer would have to pay out at any point during the auction. - // - The `takerAssetAmount` is set to the seller's `makerAssetAmount`, as the buyer - // receives the entire amount being sold by the seller. - // - The `makerAssetData`/`takerAssetData` are reversed from the sell order - const signedOrder = await orderFactory.createSignedOrderAsync( - this._web3Wrapper.getProvider(), - buyerAddress, - dutchAuctionData.beginAmount, - sellOrder.takerAssetData, - sellOrder.makerAssetAmount, - sellOrder.makerAssetData, - sellOrder.exchangeAddress, - { - senderAddress, - makerFee, - takerFee, - feeRecipientAddress, - expirationTimeSeconds, - }, - ); - const buyerERC20AssetData = assetDataUtils.decodeERC20AssetData(sellOrder.takerAssetData); - await this._increaseERC20BalanceAndAllowanceAsync( - buyerERC20AssetData.tokenAddress, - buyerAddress, - dutchAuctionData.beginAmount, - ); - return signedOrder; - } - private async _increaseERC20BalanceAndAllowanceAsync( - tokenAddress: string, - address: string, - amount: BigNumber, - ): Promise<void> { - if (amount.isZero() || address === constants.NULL_ADDRESS) { - return; // noop - } - await Promise.all([ - this._increaseERC20BalanceAsync(tokenAddress, address, amount), - this._increaseERC20AllowanceAsync(tokenAddress, address, amount), - ]); - } - private async _increaseERC20BalanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> { - const erc20Token = new DummyERC20TokenContract( - artifacts.DummyERC20Token.compilerOutput.abi, - tokenAddress, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - const txHash = await erc20Token.transfer.sendTransactionAsync(address, amount, { - from: this._coinbase, - }); - await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - } - private async _increaseERC20AllowanceAsync( - tokenAddress: string, - address: string, - amount: BigNumber, - ): Promise<void> { - const erc20Token = new DummyERC20TokenContract( - artifacts.DummyERC20Token.compilerOutput.abi, - tokenAddress, - this._web3Wrapper.getProvider(), - this._web3Wrapper.getContractDefaults(), - ); - const oldMakerAllowance = await erc20Token.allowance.callAsync(address, this._erc20ProxyAddress); - const newMakerAllowance = oldMakerAllowance.plus(amount); - const txHash = await erc20Token.approve.sendTransactionAsync(this._erc20ProxyAddress, newMakerAllowance, { - from: address, - }); - await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - } -} diff --git a/packages/contract-wrappers/test/utils/migrate.ts b/packages/contract-wrappers/test/utils/migrate.ts deleted file mode 100644 index 665ce0faa..000000000 --- a/packages/contract-wrappers/test/utils/migrate.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ContractAddresses } from '@0x/contract-addresses'; -import { devConstants } from '@0x/dev-utils'; -import { runMigrationsOnceAsync } from '@0x/migrations'; - -import { provider } from './web3_wrapper'; - -/** - * Configures and runs the migrations exactly once. Any subsequent times this is - * called, it returns the cached addresses. - * @returns The addresses of contracts that were deployed during the migrations. - */ -export async function migrateOnceAsync(): Promise<ContractAddresses> { - const txDefaults = { - gas: devConstants.GAS_LIMIT, - from: devConstants.TESTRPC_FIRST_ADDRESS, - }; - return runMigrationsOnceAsync(provider, txDefaults); -} diff --git a/packages/contract-wrappers/test/utils/token_utils.ts b/packages/contract-wrappers/test/utils/token_utils.ts deleted file mode 100644 index e390d2775..000000000 --- a/packages/contract-wrappers/test/utils/token_utils.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { DummyERC721TokenContract } from '@0x/abi-gen-wrappers'; -import { DummyERC721Token } from '@0x/contract-artifacts'; -import { generatePseudoRandomSalt } from '@0x/order-utils'; -import { BigNumber } from '@0x/utils'; - -import { provider, txDefaults, web3Wrapper } from './web3_wrapper'; - -// Those addresses come from migrations. They're deterministic so it's relatively safe to hard-code them here. -// Before we were fetching them from the TokenRegistry but now we can't as it's deprecated and removed. -// TODO(albrow): Import these from the migrations package instead of hard-coding them. -const DUMMY_ERC_20_ADRESSES = [ - '0x34d402f14d58e001d8efbe6585051bf9706aa064', - '0x25b8fe1de9daf8ba351890744ff28cf7dfa8f5e3', - '0xcdb594a32b1cc3479d8746279712c39d18a07fc0', - '0x1e2f9e10d02a6b8f8f69fcbf515e75039d2ea30d', - '0xbe0037eaf2d64fe5529bca93c18c9702d3930376', -]; - -const DUMMY_ERC_721_ADRESSES = ['0x07f96aa816c1f244cbc6ef114bb2b023ba54a2eb']; - -export const tokenUtils = { - getDummyERC20TokenAddresses(): string[] { - return DUMMY_ERC_20_ADRESSES; - }, - getDummyERC721TokenAddresses(): string[] { - return DUMMY_ERC_721_ADRESSES; - }, - async mintDummyERC721Async(address: string, tokenOwner: string): Promise<BigNumber> { - const erc721 = new DummyERC721TokenContract(DummyERC721Token.compilerOutput.abi, address, provider, txDefaults); - const tokenId = generatePseudoRandomSalt(); - const txHash = await erc721.mint.sendTransactionAsync(tokenOwner, tokenId); - web3Wrapper.awaitTransactionSuccessAsync(txHash); - return tokenId; - }, -}; diff --git a/packages/contract-wrappers/test/utils/web3_wrapper.ts b/packages/contract-wrappers/test/utils/web3_wrapper.ts deleted file mode 100644 index 4e86ebeba..000000000 --- a/packages/contract-wrappers/test/utils/web3_wrapper.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { devConstants, web3Factory } from '@0x/dev-utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { Provider } from 'ethereum-types'; - -const txDefaults = { - from: devConstants.TESTRPC_FIRST_ADDRESS, - gas: devConstants.GAS_LIMIT, -}; -const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true }); -const web3Wrapper = new Web3Wrapper(provider); - -export { provider, web3Wrapper, txDefaults }; diff --git a/packages/contract-wrappers/tsconfig.json b/packages/contract-wrappers/tsconfig.json deleted file mode 100644 index 2ee711adc..000000000 --- a/packages/contract-wrappers/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig", - "compilerOptions": { - "outDir": "lib", - "rootDir": "." - }, - "include": ["./src/**/*", "./test/**/*"] -} diff --git a/packages/contract-wrappers/tslint.json b/packages/contract-wrappers/tslint.json deleted file mode 100644 index dd9053357..000000000 --- a/packages/contract-wrappers/tslint.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["@0x/tslint-config"] -} diff --git a/packages/contract-wrappers/typedoc-tsconfig.json b/packages/contract-wrappers/typedoc-tsconfig.json deleted file mode 100644 index c9b0af1ae..000000000 --- a/packages/contract-wrappers/typedoc-tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../typedoc-tsconfig", - "compilerOptions": { - "outDir": "lib" - }, - "include": ["./src/**/*", "./test/**/*"] -} |