diff options
author | August Skare <post@augustskare.no> | 2018-11-13 16:52:41 +0800 |
---|---|---|
committer | August Skare <post@augustskare.no> | 2018-11-13 16:52:41 +0800 |
commit | e43988aa44225ef66c95d0b26764de57b3d26c3a (patch) | |
tree | 5f2bdff05e3e6a336b600bcb7a766da4793afc76 /packages/contract-wrappers | |
parent | ee91f56bbe69534885da47f58a81302bf3c37f28 (diff) | |
parent | c41622c20aea8ba89dc9899ff8b3ab6f22f53503 (diff) | |
download | dexon-sol-tools-e43988aa44225ef66c95d0b26764de57b3d26c3a.tar dexon-sol-tools-e43988aa44225ef66c95d0b26764de57b3d26c3a.tar.gz dexon-sol-tools-e43988aa44225ef66c95d0b26764de57b3d26c3a.tar.bz2 dexon-sol-tools-e43988aa44225ef66c95d0b26764de57b3d26c3a.tar.lz dexon-sol-tools-e43988aa44225ef66c95d0b26764de57b3d26c3a.tar.xz dexon-sol-tools-e43988aa44225ef66c95d0b26764de57b3d26c3a.tar.zst dexon-sol-tools-e43988aa44225ef66c95d0b26764de57b3d26c3a.zip |
Merge branch 'development' into dev-tools-pages
Diffstat (limited to 'packages/contract-wrappers')
52 files changed, 753 insertions, 936 deletions
diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index 0770b6c0d..0ab5e5d08 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -1,13 +1,85 @@ [ { - "version": "2.1.0", + "version": "4.0.0", "changes": [ { - "note": "Add optional validation to the forwarder wrapper methods" + "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 } ] }, { + "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": [ { diff --git a/packages/contract-wrappers/CHANGELOG.md b/packages/contract-wrappers/CHANGELOG.md index 60675ddbe..1fe903dd9 100644 --- a/packages/contract-wrappers/CHANGELOG.md +++ b/packages/contract-wrappers/CHANGELOG.md @@ -5,6 +5,23 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## 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 @@ -51,7 +68,7 @@ CHANGELOG * 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 13, 2018_ +## v1.0.1-rc.3 - _August 14, 2018_ * Added strict encoding/decoding checks for sendTransaction and call (#915) * Add ForwarderWrapper (#934) diff --git a/packages/contract-wrappers/README.md b/packages/contract-wrappers/README.md index 6153f798e..36f2f48fb 100644 --- a/packages/contract-wrappers/README.md +++ b/packages/contract-wrappers/README.md @@ -1,4 +1,4 @@ -## @0xproject/contract-wrappers +## @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. @@ -9,20 +9,20 @@ Smart TS wrappers for 0x smart contracts. The wrappers have simplified interface **Install** ```bash -npm install @0xproject/contract-wrappers --save +npm install @0x/contract-wrappers --save ``` **Import** ```javascript -import { ContractWrappers } from '@0xproject/contract-wrappers'; +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/@0xproject/typescript-typings/types", "node_modules/@types"], + "typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"], } ``` @@ -51,13 +51,13 @@ yarn install To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory: ```bash -PKG=@0xproject/contract-wrappers yarn build +PKG=@0x/contract-wrappers yarn build ``` Or continuously rebuild on change: ```bash -PKG=@0xproject/contract-wrappers yarn watch +PKG=@0x/contract-wrappers yarn watch ``` ```bash diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json index 35f27d77c..cb69bbd33 100644 --- a/packages/contract-wrappers/package.json +++ b/packages/contract-wrappers/package.json @@ -1,6 +1,6 @@ { - "name": "@0xproject/contract-wrappers", - "version": "2.0.2", + "name": "@0x/contract-wrappers", + "version": "3.0.1", "description": "Smart TS wrappers for 0x smart contracts", "keywords": [ "0xproject", @@ -11,24 +11,19 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "build": "yarn pre_build && tsc -b", + "build": "tsc -b", "build:ci": "yarn build", - "pre_build": "run-s update_artifacts generate_contract_wrappers copy_artifacts", - "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder|OrderValidator).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers", - "lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*", + "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", - "update_artifacts": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-trimmed/$i.json src/artifacts; done;", - "copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts", - "clean": "shx rm -rf _bundles lib test_temp test/artifacts src/contract_wrappers/generated src/artifacts generated_docs", + "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": { - "contracts_v2": "AssetProxyOwner Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder OrderValidator DummyERC20Token DummyERC721Token", "postpublish": { "assets": [] } @@ -42,11 +37,10 @@ "node": ">=6.0.0" }, "devDependencies": { - "@0xproject/abi-gen": "^1.0.13", - "@0xproject/dev-utils": "^1.0.12", - "@0xproject/migrations": "^1.0.14", - "@0xproject/subproviders": "^2.0.7", - "@0xproject/tslint-config": "^1.0.8", + "@0x/dev-utils": "^1.0.14", + "@0x/migrations": "^2.0.1", + "@0x/subproviders": "^2.1.1", + "@0x/tslint-config": "^1.0.10", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/node": "*", @@ -56,7 +50,6 @@ "chai": "^4.0.1", "chai-as-promised": "^7.1.0", "chai-bignumber": "^2.0.1", - "copyfiles": "^2.0.0", "dirty-chai": "^2.0.1", "make-promises-safe": "^1.1.0", "mocha": "^4.1.0", @@ -67,21 +60,23 @@ "sinon": "^4.0.0", "source-map-support": "^0.5.0", "tslint": "5.11.0", - "typedoc": "0.12.0", + "typedoc": "0.13.0", "typescript": "3.0.1", "web3-provider-engine": "14.0.6" }, "dependencies": { - "@0xproject/assert": "^1.0.13", - "@0xproject/base-contract": "^3.0.1", - "@0xproject/fill-scenarios": "^1.0.7", - "@0xproject/json-schemas": "^1.0.7", - "@0xproject/order-utils": "^1.0.7", - "@0xproject/types": "^1.1.4", - "@0xproject/typescript-typings": "^3.0.2", - "@0xproject/utils": "^2.0.2", - "@0xproject/web3-wrapper": "^3.0.3", - "ethereum-types": "^1.0.11", + "@0x/abi-gen-wrappers": "^1.0.2", + "@0x/assert": "^1.0.15", + "@0x/contract-addresses": "^1.1.0", + "@0x/contract-artifacts": "^1.1.0", + "@0x/fill-scenarios": "^1.0.9", + "@0x/json-schemas": "^2.0.1", + "@0x/order-utils": "^2.0.1", + "@0x/types": "^1.2.1", + "@0x/typescript-typings": "^3.0.4", + "@0x/utils": "^2.0.4", + "@0x/web3-wrapper": "^3.1.1", + "ethereum-types": "^1.1.2", "ethereumjs-blockstream": "6.0.0", "ethereumjs-util": "^5.1.1", "ethers": "~4.0.4", 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 index 1f139f1ef..b095c8e79 100644 --- 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 @@ -1,4 +1,4 @@ -import { BigNumber } from '@0xproject/utils'; +import { BigNumber } from '@0x/utils'; export abstract class AbstractBalanceAndProxyAllowanceLazyStore { public abstract async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; diff --git a/packages/contract-wrappers/src/artifacts.ts b/packages/contract-wrappers/src/artifacts.ts deleted file mode 100644 index 925f34162..000000000 --- a/packages/contract-wrappers/src/artifacts.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ContractArtifact } from 'ethereum-types'; - -import * as DummyERC20Token from './artifacts/DummyERC20Token.json'; -import * as DummyERC721Token from './artifacts/DummyERC721Token.json'; -import * as ERC20Proxy from './artifacts/ERC20Proxy.json'; -import * as ERC20Token from './artifacts/ERC20Token.json'; -import * as ERC721Proxy from './artifacts/ERC721Proxy.json'; -import * as ERC721Token from './artifacts/ERC721Token.json'; -import * as Exchange from './artifacts/Exchange.json'; -import * as Forwarder from './artifacts/Forwarder.json'; -import * as OrderValidator from './artifacts/OrderValidator.json'; -import * as EtherToken from './artifacts/WETH9.json'; -import * as ZRXToken from './artifacts/ZRXToken.json'; - -export const artifacts = { - ZRXToken: (ZRXToken as any) as ContractArtifact, - DummyERC20Token: (DummyERC20Token as any) as ContractArtifact, - DummyERC721Token: (DummyERC721Token as any) as ContractArtifact, - ERC20Token: (ERC20Token as any) as ContractArtifact, - ERC721Token: (ERC721Token as any) as ContractArtifact, - Exchange: (Exchange as any) as ContractArtifact, - EtherToken: (EtherToken as any) as ContractArtifact, - ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, - ERC721Proxy: (ERC721Proxy as any) as ContractArtifact, - Forwarder: (Forwarder as any) as ContractArtifact, - OrderValidator: (OrderValidator as any) as ContractArtifact, -}; diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts index 89402029b..0c535bd5c 100644 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -1,10 +1,17 @@ -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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 { constants } from './utils/constants'; - -import { artifacts } from './artifacts'; import { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper'; import { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper'; import { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper'; @@ -14,10 +21,11 @@ import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper'; import { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper'; import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema'; -import { contractWrappersPrivateNetworkConfigSchema } from './schemas/contract_wrappers_private_network_config_schema'; -import { contractWrappersPublicNetworkConfigSchema } from './schemas/contract_wrappers_public_network_config_schema'; 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. */ @@ -61,35 +69,39 @@ export class ContractWrappers { private readonly _web3Wrapper: Web3Wrapper; /** * Instantiates a new ContractWrappers instance. - * @param provider The Provider instance you would like the 0x.js library to use for interacting with + * @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, [ - contractWrappersPrivateNetworkConfigSchema, - contractWrappersPublicNetworkConfigSchema, - ]); - const artifactJSONs = _.values(artifacts); - const abiArrays = _.map(artifactJSONs, artifact => artifact.compilerOutput.abi); + assert.doesConformToSchema('config', config, ContractWrappersConfigSchema); const txDefaults = { gasPrice: config.gasPrice, }; this._web3Wrapper = new Web3Wrapper(provider, txDefaults); - _.forEach(abiArrays, abi => { - this._web3Wrapper.abiDecoder.addABI(abi); + 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; - this.erc20Proxy = new ERC20ProxyWrapper(this._web3Wrapper, config.networkId, config.erc20ProxyContractAddress); - this.erc721Proxy = new ERC721ProxyWrapper( - this._web3Wrapper, - config.networkId, - config.erc721ProxyContractAddress, - ); + 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, @@ -113,37 +125,34 @@ export class ContractWrappers { config.networkId, this.erc20Token, this.erc721Token, - config.exchangeContractAddress, - config.zrxContractAddress, + contractAddresses.exchange, + contractAddresses.zrxToken, blockPollingIntervalMs, ); this.forwarder = new ForwarderWrapper( this._web3Wrapper, config.networkId, - config.forwarderContractAddress, - config.zrxContractAddress, + contractAddresses.forwarder, + contractAddresses.zrxToken, + contractAddresses.etherToken, + ); + this.orderValidator = new OrderValidatorWrapper( + this._web3Wrapper, + config.networkId, + contractAddresses.orderValidator, ); - this.orderValidator = new OrderValidatorWrapper(this._web3Wrapper, config.networkId); } /** - * Sets a new web3 provider for 0x.js. Updating the provider will stop all - * subscriptions so you will need to re-subscribe to all events relevant to your app after this call. - * @param provider The Web3Provider you would like the 0x.js library to use from now on. - * @param networkId The id of the network your provider is connected to + * Unsubscribes from all subscriptions for all contracts. */ - public setProvider(provider: Provider, networkId: number): void { - this._web3Wrapper.setProvider(provider); - (this.exchange as any)._invalidateContractInstances(); - (this.exchange as any)._setNetworkId(networkId); - (this.erc20Token as any)._invalidateContractInstances(); - (this.erc20Token as any)._setNetworkId(networkId); - (this.erc20Proxy as any)._invalidateContractInstance(); - (this.erc20Proxy as any)._setNetworkId(networkId); - (this.etherToken as any)._invalidateContractInstance(); - (this.etherToken as any)._setNetworkId(networkId); + public unsubscribeAll(): void { + this.exchange.unsubscribeAll(); + this.erc20Token.unsubscribeAll(); + this.erc721Token.unsubscribeAll(); + this.etherToken.unsubscribeAll(); } /** - * Get the provider instance currently used by 0x.js + * Get the provider instance currently used by contract-wrappers * @return Web3 provider instance */ public getProvider(): Provider { diff --git a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts index f7a89e3be..749aaae10 100644 --- a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts @@ -1,9 +1,8 @@ -import { AbiDecoder, intervalUtils, logUtils } from '@0xproject/utils'; -import { marshaller, Web3Wrapper } from '@0xproject/web3-wrapper'; +import { AbiDecoder, intervalUtils, logUtils } from '@0x/utils'; +import { marshaller, Web3Wrapper } from '@0x/web3-wrapper'; import { BlockParamLiteral, ContractAbi, - ContractArtifact, FilterObject, LogEntry, LogWithDecodedArgs, @@ -24,27 +23,15 @@ import { import { constants } from '../utils/constants'; import { filterUtils } from '../utils/filter_utils'; -const CONTRACT_NAME_TO_NOT_FOUND_ERROR: { - [contractName: string]: ContractWrappersError; -} = { - ZRX: ContractWrappersError.ZRXContractDoesNotExist, - EtherToken: ContractWrappersError.EtherTokenContractDoesNotExist, - ERC20Token: ContractWrappersError.ERC20TokenContractDoesNotExist, - ERC20Proxy: ContractWrappersError.ERC20ProxyContractDoesNotExist, - ERC721Token: ContractWrappersError.ERC721TokenContractDoesNotExist, - ERC721Proxy: ContractWrappersError.ERC721ProxyContractDoesNotExist, - Exchange: ContractWrappersError.ExchangeContractDoesNotExist, -}; - export abstract class ContractWrapper { public abstract abi: ContractAbi; - protected _web3Wrapper: Web3Wrapper; protected _networkId: number; + protected _web3Wrapper: Web3Wrapper; private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined; - private _blockPollingIntervalMs: number; + private readonly _blockPollingIntervalMs: number; private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer; - private _filters: { [filterToken: string]: FilterObject }; - private _filterCallbacks: { + private readonly _filters: { [filterToken: string]: FilterObject }; + private readonly _filterCallbacks: { [filterToken: string]: EventCallback<ContractEventArgs>; }; private _onLogAddedSubscriptionToken: string | undefined; @@ -124,40 +111,6 @@ export abstract class ContractWrapper { const logWithDecodedArgs = abiDecoder.tryToDecodeLogOrNoop(log); return logWithDecodedArgs; } - protected async _getContractAbiAndAddressFromArtifactsAsync( - artifact: ContractArtifact, - addressIfExists?: string, - ): Promise<[ContractAbi, string]> { - let contractAddress: string; - if (_.isUndefined(addressIfExists)) { - if (_.isUndefined(artifact.networks[this._networkId])) { - throw new Error(ContractWrappersError.ContractNotDeployedOnNetwork); - } - contractAddress = artifact.networks[this._networkId].address.toLowerCase(); - } else { - contractAddress = addressIfExists; - } - const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(contractAddress); - if (!doesContractExist) { - throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contractName]); - } - const abiAndAddress: [ContractAbi, string] = [artifact.compilerOutput.abi, contractAddress]; - return abiAndAddress; - } - protected _getContractAddress(artifact: ContractArtifact, addressIfExists?: string): string { - if (_.isUndefined(addressIfExists)) { - if (_.isUndefined(artifact.networks[this._networkId])) { - throw new Error(ContractWrappersError.ContractNotDeployedOnNetwork); - } - const contractAddress = artifact.networks[this._networkId].address; - if (_.isUndefined(contractAddress)) { - throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contractName]); - } - return contractAddress; - } else { - return addressIfExists; - } - } private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, rawLog: RawLogEntry): void { const log: LogEntry = marshaller.unmarshalLog(rawLog); _.forEach(this._filters, (filter: FilterObject, filterToken: string) => { @@ -222,14 +175,6 @@ export abstract class ContractWrapper { }); return logs as RawLogEntry[]; } - // HACK: This should be a package-scoped method (which doesn't exist in TS) - // We don't want this method available in the public interface for all classes - // who inherit from ContractWrapper, and it is only used by the internal implementation - // of those higher classes. - // tslint:disable-next-line:no-unused-variable - private _setNetworkId(networkId: number): void { - this._networkId = networkId; - } private _stopBlockAndLogStream(): void { if (_.isUndefined(this._blockAndLogStreamerIfExists)) { throw new Error(ContractWrappersError.SubscriptionNotFound); diff --git a/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts index ff027d78a..45460bd6d 100644 --- a/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts @@ -1,38 +1,42 @@ -import { AssetProxyId } from '@0xproject/types'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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 { artifacts } from '../artifacts'; import { assert } from '../utils/assert'; +import { _getDefaultContractAddresses } from '../utils/contract_addresses'; import { ContractWrapper } from './contract_wrapper'; -import { ERC20ProxyContract } from './generated/erc20_proxy'; /** * This class includes the functionality related to interacting with the ERC20Proxy contract. */ export class ERC20ProxyWrapper extends ContractWrapper { - public abi: ContractAbi = artifacts.ERC20Proxy.compilerOutput.abi; + public abi: ContractAbi = ERC20Proxy.compilerOutput.abi; + public address: string; private _erc20ProxyContractIfExists?: ERC20ProxyContract; - private _contractAddressIfExists?: string; /** * Instantiate ERC20ProxyWrapper * @param web3Wrapper Web3Wrapper instance to use * @param networkId Desired networkId - * @param contractAddressIfExists The contract address to use. This is usually pulled from - * the artifacts but needs to be specified when using with your own custom testnet. + * @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, contractAddressIfExists?: string) { + constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { super(web3Wrapper, networkId); - this._contractAddressIfExists = contractAddressIfExists; + 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 = await this._getERC20ProxyContractAsync(); + 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; } @@ -44,7 +48,7 @@ export class ERC20ProxyWrapper extends ContractWrapper { public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> { assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress); const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase(); - const ERC20ProxyContractInstance = await this._getERC20ProxyContractAsync(); + const ERC20ProxyContractInstance = this._getERC20ProxyContract(); const isAuthorized = await ERC20ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress); return isAuthorized; } @@ -53,36 +57,17 @@ export class ERC20ProxyWrapper extends ContractWrapper { * @return The list of authorized addresses. */ public async getAuthorizedAddressesAsync(): Promise<string[]> { - const ERC20ProxyContractInstance = await this._getERC20ProxyContractAsync(); + const ERC20ProxyContractInstance = this._getERC20ProxyContract(); const authorizedAddresses = await ERC20ProxyContractInstance.getAuthorizedAddresses.callAsync(); return authorizedAddresses; } - /** - * Retrieves the Ethereum address of the ERC20Proxy contract deployed on the network - * that the user-passed web3 provider is connected to. - * @returns The Ethereum address of the ERC20Proxy contract being used. - */ - public getContractAddress(): string { - const contractAddress = this._getContractAddress(artifacts.ERC20Proxy, this._contractAddressIfExists); - return contractAddress; - } - // HACK: We don't want this method to be visible to the other units within that package but not to the end user. - // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. - // tslint:disable-next-line:no-unused-variable - private _invalidateContractInstance(): void { - delete this._erc20ProxyContractIfExists; - } - private async _getERC20ProxyContractAsync(): Promise<ERC20ProxyContract> { + private _getERC20ProxyContract(): ERC20ProxyContract { if (!_.isUndefined(this._erc20ProxyContractIfExists)) { return this._erc20ProxyContractIfExists; } - const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.ERC20Proxy, - this._contractAddressIfExists, - ); const contractInstance = new ERC20ProxyContract( - abi, - address, + this.abi, + this.address, this._web3Wrapper.getProvider(), this._web3Wrapper.getContractDefaults(), ); diff --git a/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts index 4625cef6a..5e0ec1951 100644 --- a/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts @@ -1,10 +1,11 @@ -import { schemas } from '@0xproject/json-schemas'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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 { artifacts } from '../artifacts'; import { methodOptsSchema } from '../schemas/method_opts_schema'; import { txOptsSchema } from '../schemas/tx_opts_schema'; import { @@ -17,12 +18,10 @@ import { } 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'; -import { ERC20TokenContract, ERC20TokenEventArgs, ERC20TokenEvents } from './generated/erc20_token'; - -const removeUndefinedProperties = _.pickBy; /** * This class includes all the functionality related to interacting with ERC20 token contracts. @@ -30,10 +29,10 @@ const removeUndefinedProperties = _.pickBy; * to the 0x ERC20 Proxy smart contract. */ export class ERC20TokenWrapper extends ContractWrapper { - public abi: ContractAbi = artifacts.ERC20Token.compilerOutput.abi; + public abi: ContractAbi = ERC20Token.compilerOutput.abi; public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; - private _tokenContractsByAddress: { [address: string]: ERC20TokenContract }; - private _erc20ProxyWrapper: ERC20ProxyWrapper; + private readonly _tokenContractsByAddress: { [address: string]: ERC20TokenContract }; + private readonly _erc20ProxyWrapper: ERC20ProxyWrapper; /** * Instantiate ERC20TokenWrapper * @param web3Wrapper Web3Wrapper instance to use @@ -108,7 +107,7 @@ export class ERC20TokenWrapper extends ContractWrapper { const txHash = await tokenContract.approve.sendTransactionAsync( normalizedSpenderAddress, amountInBaseUnits, - removeUndefinedProperties({ + utils.removeUndefinedProperties({ from: normalizedOwnerAddress, gas: txOpts.gasLimit, gasPrice: txOpts.gasPrice, @@ -189,7 +188,7 @@ export class ERC20TokenWrapper extends ContractWrapper { ownerAddress: string, methodOpts: MethodOpts = {}, ): Promise<BigNumber> { - const proxyAddress = this._erc20ProxyWrapper.getContractAddress(); + const proxyAddress = this._erc20ProxyWrapper.address; const allowanceInBaseUnits = await this.getAllowanceAsync(tokenAddress, ownerAddress, proxyAddress, methodOpts); return allowanceInBaseUnits; } @@ -209,7 +208,7 @@ export class ERC20TokenWrapper extends ContractWrapper { amountInBaseUnits: BigNumber, txOpts: TransactionOpts = {}, ): Promise<string> { - const proxyAddress = this._erc20ProxyWrapper.getContractAddress(); + const proxyAddress = this._erc20ProxyWrapper.address; const txHash = await this.setAllowanceAsync( tokenAddress, ownerAddress, @@ -278,7 +277,7 @@ export class ERC20TokenWrapper extends ContractWrapper { const txHash = await tokenContract.transfer.sendTransactionAsync( normalizedToAddress, amountInBaseUnits, - removeUndefinedProperties({ + utils.removeUndefinedProperties({ from: normalizedFromAddress, gas: txOpts.gasLimit, gasPrice: txOpts.gasPrice, @@ -339,7 +338,7 @@ export class ERC20TokenWrapper extends ContractWrapper { normalizedFromAddress, normalizedToAddress, amountInBaseUnits, - removeUndefinedProperties({ + utils.removeUndefinedProperties({ from: normalizedSenderAddress, gas: txOpts.gasLimit, gasPrice: txOpts.gasPrice, @@ -373,7 +372,7 @@ export class ERC20TokenWrapper extends ContractWrapper { normalizedTokenAddress, eventName, indexFilterValues, - artifacts.ERC20Token.compilerOutput.abi, + ERC20Token.compilerOutput.abi, callback, isVerbose, ); @@ -418,30 +417,19 @@ export class ERC20TokenWrapper extends ContractWrapper { eventName, blockRange, indexFilterValues, - artifacts.ERC20Token.compilerOutput.abi, + ERC20Token.compilerOutput.abi, ); return logs; } - // HACK: We don't want this method to be visible to the other units within that package but not to the end user. - // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. - // tslint:disable-next-line:no-unused-variable - private _invalidateContractInstances(): void { - this.unsubscribeAll(); - this._tokenContractsByAddress = {}; - } private async _getTokenContractAsync(tokenAddress: string): Promise<ERC20TokenContract> { const normalizedTokenAddress = tokenAddress.toLowerCase(); let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress]; if (!_.isUndefined(tokenContract)) { return tokenContract; } - const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.ERC20Token, - normalizedTokenAddress, - ); const contractInstance = new ERC20TokenContract( - abi, - address, + this.abi, + normalizedTokenAddress, this._web3Wrapper.getProvider(), this._web3Wrapper.getContractDefaults(), ); diff --git a/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts index 933c1dc27..12758e191 100644 --- a/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts @@ -1,38 +1,42 @@ -import { AssetProxyId } from '@0xproject/types'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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 { artifacts } from '../artifacts'; import { assert } from '../utils/assert'; +import { _getDefaultContractAddresses } from '../utils/contract_addresses'; import { ContractWrapper } from './contract_wrapper'; -import { ERC721ProxyContract } from './generated/erc721_proxy'; /** * This class includes the functionality related to interacting with the ERC721Proxy contract. */ export class ERC721ProxyWrapper extends ContractWrapper { - public abi: ContractAbi = artifacts.ERC20Proxy.compilerOutput.abi; + public abi: ContractAbi = ERC721Proxy.compilerOutput.abi; + public address: string; private _erc721ProxyContractIfExists?: ERC721ProxyContract; - private _contractAddressIfExists?: string; /** * Instantiate ERC721ProxyWrapper * @param web3Wrapper Web3Wrapper instance to use * @param networkId Desired networkId - * @param contractAddressIfExists The contract address to use. This is usually pulled from - * the artifacts but needs to be specified when using with your own custom testnet. + * @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, contractAddressIfExists?: string) { + constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { super(web3Wrapper, networkId); - this._contractAddressIfExists = contractAddressIfExists; + 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._getERC721ProxyContractAsync(); + 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; } @@ -44,7 +48,7 @@ export class ERC721ProxyWrapper extends ContractWrapper { public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> { assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress); const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase(); - const ERC721ProxyContractInstance = await this._getERC721ProxyContractAsync(); + const ERC721ProxyContractInstance = await this._getERC721ProxyContract(); const isAuthorized = await ERC721ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress); return isAuthorized; } @@ -53,36 +57,17 @@ export class ERC721ProxyWrapper extends ContractWrapper { * @return The list of authorized addresses. */ public async getAuthorizedAddressesAsync(): Promise<string[]> { - const ERC721ProxyContractInstance = await this._getERC721ProxyContractAsync(); + const ERC721ProxyContractInstance = await this._getERC721ProxyContract(); const authorizedAddresses = await ERC721ProxyContractInstance.getAuthorizedAddresses.callAsync(); return authorizedAddresses; } - /** - * Retrieves the Ethereum address of the ERC721Proxy contract deployed on the network - * that the user-passed web3 provider is connected to. - * @returns The Ethereum address of the ERC721Proxy contract being used. - */ - public getContractAddress(): string { - const contractAddress = this._getContractAddress(artifacts.ERC721Proxy, this._contractAddressIfExists); - return contractAddress; - } - // HACK: We don't want this method to be visible to the other units within that package but not to the end user. - // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. - // tslint:disable-next-line:no-unused-variable - private _invalidateContractInstance(): void { - delete this._erc721ProxyContractIfExists; - } - private async _getERC721ProxyContractAsync(): Promise<ERC721ProxyContract> { + private _getERC721ProxyContract(): ERC721ProxyContract { if (!_.isUndefined(this._erc721ProxyContractIfExists)) { return this._erc721ProxyContractIfExists; } - const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.ERC721Proxy, - this._contractAddressIfExists, - ); const contractInstance = new ERC721ProxyContract( - abi, - address, + this.abi, + this.address, this._web3Wrapper.getProvider(), this._web3Wrapper.getContractDefaults(), ); diff --git a/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts index 590dbbf74..1610af47b 100644 --- a/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts @@ -1,10 +1,11 @@ -import { schemas } from '@0xproject/json-schemas'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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 { artifacts } from '../artifacts'; import { methodOptsSchema } from '../schemas/method_opts_schema'; import { txOptsSchema } from '../schemas/tx_opts_schema'; import { @@ -17,12 +18,10 @@ import { } 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'; -import { ERC721TokenContract, ERC721TokenEventArgs, ERC721TokenEvents } from './generated/erc721_token'; - -const removeUndefinedProperties = _.pickBy; /** * This class includes all the functionality related to interacting with ERC721 token contracts. @@ -30,9 +29,9 @@ const removeUndefinedProperties = _.pickBy; * to the 0x ERC721 Proxy smart contract. */ export class ERC721TokenWrapper extends ContractWrapper { - public abi: ContractAbi = artifacts.ERC721Token.compilerOutput.abi; - private _tokenContractsByAddress: { [address: string]: ERC721TokenContract }; - private _erc721ProxyWrapper: ERC721ProxyWrapper; + public abi: ContractAbi = ERC721Token.compilerOutput.abi; + private readonly _tokenContractsByAddress: { [address: string]: ERC721TokenContract }; + private readonly _erc721ProxyWrapper: ERC721ProxyWrapper; /** * Instantiate ERC721TokenWrapper * @param web3Wrapper Web3Wrapper instance to use @@ -150,7 +149,7 @@ export class ERC721TokenWrapper extends ContractWrapper { ownerAddress: string, methodOpts: MethodOpts = {}, ): Promise<boolean> { - const proxyAddress = this._erc721ProxyWrapper.getContractAddress(); + const proxyAddress = this._erc721ProxyWrapper.address; const isProxyApprovedForAll = await this.isApprovedForAllAsync( tokenAddress, ownerAddress, @@ -199,7 +198,7 @@ export class ERC721TokenWrapper extends ContractWrapper { tokenId: BigNumber, methodOpts: MethodOpts = {}, ): Promise<boolean> { - const proxyAddress = this._erc721ProxyWrapper.getContractAddress(); + const proxyAddress = this._erc721ProxyWrapper.address; const approvedAddress = await this.getApprovedIfExistsAsync(tokenAddress, tokenId, methodOpts); const isProxyApproved = approvedAddress === proxyAddress; return isProxyApproved; @@ -235,7 +234,7 @@ export class ERC721TokenWrapper extends ContractWrapper { const txHash = await tokenContract.setApprovalForAll.sendTransactionAsync( normalizedOperatorAddress, isApproved, - removeUndefinedProperties({ + utils.removeUndefinedProperties({ gas: txOpts.gasLimit, gasPrice: txOpts.gasPrice, from: normalizedOwnerAddress, @@ -260,7 +259,7 @@ export class ERC721TokenWrapper extends ContractWrapper { isApproved: boolean, txOpts: TransactionOpts = {}, ): Promise<string> { - const proxyAddress = this._erc721ProxyWrapper.getContractAddress(); + const proxyAddress = this._erc721ProxyWrapper.address; const txHash = await this.setApprovalForAllAsync(tokenAddress, ownerAddress, proxyAddress, isApproved, txOpts); return txHash; } @@ -295,7 +294,7 @@ export class ERC721TokenWrapper extends ContractWrapper { const txHash = await tokenContract.approve.sendTransactionAsync( normalizedApprovedAddress, tokenId, - removeUndefinedProperties({ + utils.removeUndefinedProperties({ gas: txOpts.gasLimit, gasPrice: txOpts.gasPrice, from: tokenOwnerAddress, @@ -318,7 +317,7 @@ export class ERC721TokenWrapper extends ContractWrapper { tokenId: BigNumber, txOpts: TransactionOpts = {}, ): Promise<string> { - const proxyAddress = this._erc721ProxyWrapper.getContractAddress(); + const proxyAddress = this._erc721ProxyWrapper.address; const txHash = await this.setApprovalAsync(tokenAddress, proxyAddress, tokenId, txOpts); return txHash; } @@ -366,7 +365,7 @@ export class ERC721TokenWrapper extends ContractWrapper { ownerAddress, normalizedReceiverAddress, tokenId, - removeUndefinedProperties({ + utils.removeUndefinedProperties({ gas: txOpts.gasLimit, gasPrice: txOpts.gasPrice, from: normalizedSenderAddress, @@ -400,7 +399,7 @@ export class ERC721TokenWrapper extends ContractWrapper { normalizedTokenAddress, eventName, indexFilterValues, - artifacts.ERC721Token.compilerOutput.abi, + ERC721Token.compilerOutput.abi, callback, isVerbose, ); @@ -445,30 +444,19 @@ export class ERC721TokenWrapper extends ContractWrapper { eventName, blockRange, indexFilterValues, - artifacts.ERC721Token.compilerOutput.abi, + ERC721Token.compilerOutput.abi, ); return logs; } - // HACK: We don't want this method to be visible to the other units within that package but not to the end user. - // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. - // tslint:disable-next-line:no-unused-variable - private _invalidateContractInstances(): void { - this.unsubscribeAll(); - this._tokenContractsByAddress = {}; - } private async _getTokenContractAsync(tokenAddress: string): Promise<ERC721TokenContract> { const normalizedTokenAddress = tokenAddress.toLowerCase(); let tokenContract = this._tokenContractsByAddress[normalizedTokenAddress]; if (!_.isUndefined(tokenContract)) { return tokenContract; } - const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.ERC721Token, - normalizedTokenAddress, - ); const contractInstance = new ERC721TokenContract( - abi, - address, + this.abi, + normalizedTokenAddress, this._web3Wrapper.getProvider(), this._web3Wrapper.getContractDefaults(), ); diff --git a/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts index 1ac01812e..913c47cf7 100644 --- a/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts @@ -1,29 +1,28 @@ -import { schemas } from '@0xproject/json-schemas'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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 { artifacts } from '../artifacts'; 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'; -import { WETH9Contract, WETH9EventArgs, WETH9Events } from './generated/weth9'; - -const removeUndefinedProperties = _.pickBy; /** * This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract. * The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back. */ export class EtherTokenWrapper extends ContractWrapper { - public abi: ContractAbi = artifacts.EtherToken.compilerOutput.abi; - private _etherTokenContractsByAddress: { + public abi: ContractAbi = WETH9.compilerOutput.abi; + private readonly _etherTokenContractsByAddress: { [address: string]: WETH9Contract; } = {}; - private _erc20TokenWrapper: ERC20TokenWrapper; + private readonly _erc20TokenWrapper: ERC20TokenWrapper; /** * Instantiate EtherTokenWrapper. * @param web3Wrapper Web3Wrapper instance to use @@ -67,7 +66,7 @@ export class EtherTokenWrapper extends ContractWrapper { const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress); const txHash = await wethContract.deposit.sendTransactionAsync( - removeUndefinedProperties({ + utils.removeUndefinedProperties({ from: normalizedDepositorAddress, value: amountInWei, gas: txOpts.gasLimit, @@ -109,7 +108,7 @@ export class EtherTokenWrapper extends ContractWrapper { const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress); const txHash = await wethContract.withdraw.sendTransactionAsync( amountInWei, - removeUndefinedProperties({ + utils.removeUndefinedProperties({ from: normalizedWithdrawerAddress, gas: txOpts.gasLimit, gasPrice: txOpts.gasPrice, @@ -142,7 +141,7 @@ export class EtherTokenWrapper extends ContractWrapper { eventName, blockRange, indexFilterValues, - artifacts.EtherToken.compilerOutput.abi, + WETH9.compilerOutput.abi, ); return logs; } @@ -172,7 +171,7 @@ export class EtherTokenWrapper extends ContractWrapper { normalizedEtherTokenAddress, eventName, indexFilterValues, - artifacts.EtherToken.compilerOutput.abi, + WETH9.compilerOutput.abi, callback, isVerbose, ); @@ -192,36 +191,14 @@ export class EtherTokenWrapper extends ContractWrapper { public unsubscribeAll(): void { super._unsubscribeAll(); } - /** - * Retrieves the Ethereum address of the EtherToken contract deployed on the network - * that the user-passed web3 provider is connected to. If it's not Kovan, Ropsten, Rinkeby, Mainnet or TestRPC - * (networkId: 50), it will return undefined (e.g a private network). - * @returns The Ethereum address of the EtherToken contract or undefined. - */ - public getContractAddressIfExists(): string | undefined { - const networkSpecificArtifact = artifacts.EtherToken.networks[this._networkId]; - const contractAddressIfExists = _.isUndefined(networkSpecificArtifact) - ? undefined - : networkSpecificArtifact.address; - return contractAddressIfExists; - } - // tslint:disable-next-line:no-unused-variable - private _invalidateContractInstance(): void { - this.unsubscribeAll(); - this._etherTokenContractsByAddress = {}; - } private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<WETH9Contract> { let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress]; if (!_.isUndefined(etherTokenContract)) { return etherTokenContract; } - const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.EtherToken, - etherTokenAddress, - ); const contractInstance = new WETH9Contract( - abi, - address, + this.abi, + etherTokenAddress, this._web3Wrapper.getProvider(), this._web3Wrapper.getContractDefaults(), ); diff --git a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts index dc9ffcbf7..c76e51eee 100644 --- a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts @@ -1,22 +1,24 @@ -import { schemas } from '@0xproject/json-schemas'; +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 '@0xproject/order-utils'; -import { AssetProxyId, Order, SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +} 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 { artifacts } from '../artifacts'; import { AssetBalanceAndProxyAllowanceFetcher } from '../fetchers/asset_balance_and_proxy_allowance_fetcher'; import { OrderFilledCancelledFetcher } from '../fetchers/order_filled_cancelled_fetcher'; import { methodOptsSchema } from '../schemas/method_opts_schema'; import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema'; import { txOptsSchema } from '../schemas/tx_opts_schema'; +import { validateOrderFillableOptsSchema } from '../schemas/validate_order_fillable_opts_schema'; import { BlockRange, EventCallback, @@ -24,54 +26,58 @@ import { IndexedFilterValues, MethodOpts, OrderInfo, - OrderStatus, 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'; -import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from './generated/exchange'; /** * 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 = artifacts.Exchange.compilerOutput.abi; + public abi: ContractAbi = Exchange.compilerOutput.abi; + public address: string; + public zrxTokenAddress: string; private _exchangeContractIfExists?: ExchangeContract; - private _erc721TokenWrapper: ERC721TokenWrapper; - private _erc20TokenWrapper: ERC20TokenWrapper; - private _contractAddressIfExists?: string; - private _zrxContractAddressIfExists?: string; + private readonly _erc721TokenWrapper: ERC721TokenWrapper; + private readonly _erc20TokenWrapper: ERC20TokenWrapper; /** * Instantiate ExchangeWrapper - * @param web3Wrapper Web3Wrapper instance to use - * @param networkId Desired networkId - * @param contractAddressIfExists The exchange contract address to use. This is usually pulled from - * the artifacts but needs to be specified when using with your own custom testnet. - * @param zrxContractAddressIfExists The ZRXToken contract address to use. This is usually pulled from - * the artifacts but needs to be specified when using with your own custom testnet. - * @param blockPollingIntervalMs The block polling interval to use for active subscriptions + * @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, - contractAddressIfExists?: string, - zrxContractAddressIfExists?: string, + address?: string, + zrxTokenAddress?: string, blockPollingIntervalMs?: number, ) { super(web3Wrapper, networkId, blockPollingIntervalMs); this._erc20TokenWrapper = erc20TokenWrapper; this._erc721TokenWrapper = erc721TokenWrapper; - this._contractAddressIfExists = contractAddressIfExists; - this._zrxContractAddressIfExists = zrxContractAddressIfExists; + 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. @@ -1051,12 +1057,11 @@ export class ExchangeWrapper extends ContractWrapper { assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.isFunction('callback', callback); - const exchangeContractAddress = this.getContractAddress(); const subscriptionToken = this._subscribe<ArgsType>( - exchangeContractAddress, + this.address, eventName, indexFilterValues, - artifacts.Exchange.compilerOutput.abi, + Exchange.compilerOutput.abi, callback, isVerbose, ); @@ -1091,13 +1096,12 @@ export class ExchangeWrapper extends ContractWrapper { assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); - const exchangeContractAddress = this.getContractAddress(); const logs = await this._getLogsAsync<ArgsType>( - exchangeContractAddress, + this.address, eventName, blockRange, indexFilterValues, - artifacts.Exchange.compilerOutput.abi, + Exchange.compilerOutput.abi, ); return logs; } @@ -1111,6 +1115,9 @@ export class ExchangeWrapper extends ContractWrapper { 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, @@ -1121,7 +1128,7 @@ export class ExchangeWrapper extends ContractWrapper { const expectedFillTakerTokenAmountIfExists = opts.expectedFillTakerTokenAmount; const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest); - const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher); + const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider()); await orderValidationUtils.validateOrderFillableOrThrowAsync( exchangeTradeSimulator, signedOrder, @@ -1149,7 +1156,7 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore); const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest); - const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher); + const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher, this._web3Wrapper.getProvider()); await orderValidationUtils.validateFillOrderThrowIfInvalidAsync( exchangeTradeSimulator, this._web3Wrapper.getProvider(), @@ -1160,29 +1167,11 @@ export class ExchangeWrapper extends ContractWrapper { ); } /** - * Retrieves the Ethereum address of the Exchange contract deployed on the network - * that the user-passed web3 provider is connected to. - * @returns The Ethereum address of the Exchange contract being used. - */ - public getContractAddress(): string { - const contractAddress = this._getContractAddress(artifacts.Exchange, this._contractAddressIfExists); - return contractAddress; - } - /** - * Returns the ZRX token address used by the exchange contract. - * @return Address of ZRX token - */ - public getZRXTokenAddress(): string { - const contractAddress = this._getContractAddress(artifacts.ZRXToken, this._zrxContractAddressIfExists); - return contractAddress; - } - /** * Returns the ZRX asset data used by the exchange contract. * @return ZRX asset data */ public getZRXAssetData(): string { - const zrxTokenAddress = this.getZRXTokenAddress(); - const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress); + const zrxAssetData = assetDataUtils.encodeERC20AssetData(this.zrxTokenAddress); return zrxAssetData; } /** @@ -1195,23 +1184,14 @@ export class ExchangeWrapper extends ContractWrapper { const encoder = new TransactionEncoder(exchangeInstance); return encoder; } - // tslint:disable:no-unused-variable - private _invalidateContractInstances(): void { - this.unsubscribeAll(); - delete this._exchangeContractIfExists; - } // tslint:enable:no-unused-variable private async _getExchangeContractAsync(): Promise<ExchangeContract> { if (!_.isUndefined(this._exchangeContractIfExists)) { return this._exchangeContractIfExists; } - const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.Exchange, - this._contractAddressIfExists, - ); const contractInstance = new ExchangeContract( - abi, - address, + this.abi, + this.address, this._web3Wrapper.getProvider(), this._web3Wrapper.getContractDefaults(), ); diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts index c19edf188..80742e030 100644 --- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts @@ -1,40 +1,62 @@ -import { schemas } from '@0xproject/json-schemas'; -import { AssetProxyId, SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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 { artifacts } from '../artifacts'; 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'; -import { ForwarderContract } from './generated/forwarder'; /** * This class includes the functionality related to interacting with the Forwarder contract. */ export class ForwarderWrapper extends ContractWrapper { - public abi: ContractAbi = artifacts.Forwarder.compilerOutput.abi; + public abi: ContractAbi = Forwarder.compilerOutput.abi; + public address: string; + public zrxTokenAddress: string; + public etherTokenAddress: string; private _forwarderContractIfExists?: ForwarderContract; - private _contractAddressIfExists?: string; - private _zrxContractAddressIfExists?: string; + + /** + * 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, - contractAddressIfExists?: string, - zrxContractAddressIfExists?: string, + address?: string, + zrxTokenAddress?: string, + etherTokenAddress?: string, ) { super(web3Wrapper, networkId); - this._contractAddressIfExists = contractAddressIfExists; - this._zrxContractAddressIfExists = zrxContractAddressIfExists; + 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. @@ -73,12 +95,8 @@ export class ForwarderWrapper extends ContractWrapper { assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); // other assertions - assert.ordersCanBeUsedForForwarderContract(signedOrders, this.getEtherTokenAddress()); - assert.feeOrdersCanBeUsedForForwarderContract( - signedFeeOrders, - this.getZRXTokenAddress(), - this.getEtherTokenAddress(), - ); + assert.ordersCanBeUsedForForwarderContract(signedOrders, this.etherTokenAddress); + assert.feeOrdersCanBeUsedForForwarderContract(signedFeeOrders, this.zrxTokenAddress, this.etherTokenAddress); // format feePercentage const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage); // lowercase input addresses @@ -100,7 +118,7 @@ export class ForwarderWrapper extends ContractWrapper { optimizedFeeOrders, feeSignatures, formattedFeePercentage, - feeRecipientAddress, + normalizedFeeRecipientAddress, { value: ethAmount, from: normalizedTakerAddress, @@ -165,12 +183,8 @@ export class ForwarderWrapper extends ContractWrapper { assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); // other assertions - assert.ordersCanBeUsedForForwarderContract(signedOrders, this.getEtherTokenAddress()); - assert.feeOrdersCanBeUsedForForwarderContract( - signedFeeOrders, - this.getZRXTokenAddress(), - this.getEtherTokenAddress(), - ); + assert.ordersCanBeUsedForForwarderContract(signedOrders, this.etherTokenAddress); + assert.feeOrdersCanBeUsedForForwarderContract(signedFeeOrders, this.zrxTokenAddress, this.etherTokenAddress); // format feePercentage const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage); // lowercase input addresses @@ -193,7 +207,7 @@ export class ForwarderWrapper extends ContractWrapper { optimizedFeeOrders, feeSignatures, formattedFeePercentage, - feeRecipientAddress, + normalizedFeeRecipientAddress, { value: ethAmount, from: normalizedTakerAddress, @@ -220,48 +234,13 @@ export class ForwarderWrapper extends ContractWrapper { ); return txHash; } - /** - * Retrieves the Ethereum address of the Forwarder contract deployed on the network - * that the user-passed web3 provider is connected to. - * @returns The Ethereum address of the Forwarder contract being used. - */ - public getContractAddress(): string { - const contractAddress = this._getContractAddress(artifacts.Forwarder, this._contractAddressIfExists); - return contractAddress; - } - /** - * Returns the ZRX token address used by the forwarder contract. - * @return Address of ZRX token - */ - public getZRXTokenAddress(): string { - const contractAddress = this._getContractAddress(artifacts.ZRXToken, this._zrxContractAddressIfExists); - return contractAddress; - } - /** - * Returns the Ether token address used by the forwarder contract. - * @return Address of Ether token - */ - public getEtherTokenAddress(): string { - const contractAddress = this._getContractAddress(artifacts.EtherToken); - return contractAddress; - } - // HACK: We don't want this method to be visible to the other units within that package but not to the end user. - // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. - // tslint:disable-next-line:no-unused-variable - private _invalidateContractInstance(): void { - delete this._forwarderContractIfExists; - } private async _getForwarderContractAsync(): Promise<ForwarderContract> { if (!_.isUndefined(this._forwarderContractIfExists)) { return this._forwarderContractIfExists; } - const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.Forwarder, - this._contractAddressIfExists, - ); const contractInstance = new ForwarderContract( - abi, - address, + this.abi, + this.address, this._web3Wrapper.getProvider(), this._web3Wrapper.getContractDefaults(), ); diff --git a/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts index 1da88f624..c186e080e 100644 --- a/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts @@ -1,30 +1,35 @@ -import { schemas } from '@0xproject/json-schemas'; -import { SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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 { artifacts } from '../artifacts'; import { BalanceAndAllowance, OrderAndTraderInfo, TraderInfo } from '../types'; import { assert } from '../utils/assert'; +import { _getDefaultContractAddresses } from '../utils/contract_addresses'; import { ContractWrapper } from './contract_wrapper'; -import { OrderValidatorContract } from './generated/order_validator'; /** * This class includes the functionality related to interacting with the OrderValidator contract. */ export class OrderValidatorWrapper extends ContractWrapper { - public abi: ContractAbi = artifacts.OrderValidator.compilerOutput.abi; + 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 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) { + 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 @@ -164,20 +169,13 @@ export class OrderValidatorWrapper extends ContractWrapper { const result = await OrderValidatorContractInstance.getERC721TokenOwner.callAsync(tokenAddress, tokenId); return result; } - // HACK: We don't want this method to be visible to the other units within that package but not to the end user. - // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused. - // tslint:disable-next-line:no-unused-variable - private _invalidateContractInstance(): void { - delete this._orderValidatorContractIfExists; - } private async _getOrderValidatorContractAsync(): Promise<OrderValidatorContract> { if (!_.isUndefined(this._orderValidatorContractIfExists)) { return this._orderValidatorContractIfExists; } - const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(artifacts.OrderValidator); const contractInstance = new OrderValidatorContract( - abi, - address, + this.abi, + this.address, this._web3Wrapper.getProvider(), this._web3Wrapper.getContractDefaults(), ); 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 index 023cd5ac3..d10cffe57 100644 --- 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 @@ -1,7 +1,7 @@ // tslint:disable:no-unnecessary-type-assertion -import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0xproject/order-utils'; -import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { AbstractBalanceAndProxyAllowanceFetcher, assetDataUtils } from '@0x/order-utils'; +import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0x/types'; +import { BigNumber } from '@0x/utils'; import { BlockParamLiteral } from 'ethereum-types'; import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper'; diff --git a/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts b/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts index 7a252aed3..5d350916c 100644 --- a/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts +++ b/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts @@ -1,6 +1,7 @@ // tslint:disable:no-unnecessary-type-assertion -import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils'; -import { BigNumber } from '@0xproject/utils'; +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'; @@ -18,9 +19,18 @@ export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelled }); return filledTakerAmount; } - public async isOrderCancelledAsync(orderHash: string): Promise<boolean> { + public async isOrderCancelledAsync(signedOrder: SignedOrder): Promise<boolean> { + const orderHash = orderHashUtils.getOrderHashHex(signedOrder); const isCancelled = await this._exchange.isCancelledAsync(orderHash); - return isCancelled; + 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(); diff --git a/packages/contract-wrappers/src/globals.d.ts b/packages/contract-wrappers/src/globals.d.ts deleted file mode 100644 index 94e63a32d..000000000 --- a/packages/contract-wrappers/src/globals.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module '*.json' { - const json: any; - /* tslint:disable */ - export default json; - /* tslint:enable */ -} diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index e8a53170e..d66ff5c9c 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -1,3 +1,30 @@ +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'; @@ -12,6 +39,7 @@ export { TransactionEncoder } from './utils/transaction_encoder'; export { ContractWrappersError, + ForwarderWrapperError, IndexedFilterValues, BlockRange, ContractWrappersConfig, @@ -28,7 +56,7 @@ export { ValidateOrderFillableOpts, } from './types'; -export { Order, SignedOrder, AssetProxyId } from '@0xproject/types'; +export { Order, SignedOrder, AssetProxyId } from '@0x/types'; export { BlockParamLiteral, @@ -54,41 +82,7 @@ export { StateMutability, } from 'ethereum-types'; -export { - WETH9Events, - WETH9WithdrawalEventArgs, - WETH9ApprovalEventArgs, - WETH9EventArgs, - WETH9DepositEventArgs, - WETH9TransferEventArgs, -} from './contract_wrappers/generated/weth9'; - -export { - ERC20TokenTransferEventArgs, - ERC20TokenApprovalEventArgs, - ERC20TokenEvents, - ERC20TokenEventArgs, -} from './contract_wrappers/generated/erc20_token'; - -export { - ERC721TokenApprovalEventArgs, - ERC721TokenApprovalForAllEventArgs, - ERC721TokenTransferEventArgs, - ERC721TokenEvents, - ERC721TokenEventArgs, -} from './contract_wrappers/generated/erc721_token'; - -export { - ExchangeCancelUpToEventArgs, - ExchangeAssetProxyRegisteredEventArgs, - ExchangeSignatureValidatorApprovalEventArgs, - ExchangeFillEventArgs, - ExchangeCancelEventArgs, - ExchangeEventArgs, - ExchangeEvents, -} from './contract_wrappers/generated/exchange'; - -export { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils'; +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 index ac248b2d4..ae1ce668c 100644 --- a/packages/contract-wrappers/src/schemas/contract_wrappers_config_schema.ts +++ b/packages/contract-wrappers/src/schemas/contract_wrappers_config_schema.ts @@ -1,5 +1,25 @@ export const ContractWrappersConfigSchema = { id: '/ContractWrappersConfig', - oneOf: [{ $ref: '/ZeroExContractPrivateNetworkConfig' }, { $ref: '/ZeroExContractPublicNetworkConfig' }], + 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/contract_wrappers_private_network_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts deleted file mode 100644 index 904690ae7..000000000 --- a/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts +++ /dev/null @@ -1,36 +0,0 @@ -export const contractWrappersPrivateNetworkConfigSchema = { - id: '/ZeroExContractPrivateNetworkConfig', - properties: { - networkId: { - type: 'number', - minimum: 1, - }, - gasPrice: { $ref: '/numberSchema' }, - zrxContractAddress: { $ref: '/addressSchema' }, - exchangeContractAddress: { $ref: '/addressSchema' }, - erc20ProxyContractAddress: { $ref: '/addressSchema' }, - erc721ProxyContractAddress: { $ref: '/addressSchema' }, - blockPollingIntervalMs: { type: 'number' }, - orderWatcherConfig: { - type: 'object', - properties: { - pollingIntervalMs: { - type: 'number', - minimum: 0, - }, - numConfirmations: { - type: 'number', - minimum: 0, - }, - }, - }, - }, - type: 'object', - required: [ - 'networkId', - 'zrxContractAddress', - 'exchangeContractAddress', - 'erc20ProxyContractAddress', - 'erc721ProxyContractAddress', - ], -}; diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts deleted file mode 100644 index 5cd008ae0..000000000 --- a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts +++ /dev/null @@ -1,44 +0,0 @@ -const networkNameToId: { [networkName: string]: number } = { - mainnet: 1, - ropsten: 3, - rinkeby: 4, - kovan: 42, - ganache: 50, -}; - -export const contractWrappersPublicNetworkConfigSchema = { - id: '/ZeroExContractPublicNetworkConfig', - properties: { - networkId: { - type: 'number', - enum: [ - networkNameToId.mainnet, - networkNameToId.kovan, - networkNameToId.ropsten, - networkNameToId.rinkeby, - networkNameToId.ganache, - ], - }, - gasPrice: { $ref: '/numberSchema' }, - zrxContractAddress: { $ref: '/addressSchema' }, - exchangeContractAddress: { $ref: '/addressSchema' }, - erc20ProxyContractAddress: { $ref: '/addressSchema' }, - erc721ProxyContractAddress: { $ref: '/addressSchema' }, - blockPollingIntervalMs: { type: 'number' }, - orderWatcherConfig: { - type: 'object', - properties: { - pollingIntervalMs: { - type: 'number', - minimum: 0, - }, - numConfirmations: { - type: 'number', - minimum: 0, - }, - }, - }, - }, - type: 'object', - required: ['networkId'], -}; 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 new file mode 100644 index 000000000..2e111af04 --- /dev/null +++ b/packages/contract-wrappers/src/schemas/validate_order_fillable_opts_schema.ts @@ -0,0 +1,7 @@ +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 index e0b12b7c9..5a5bdd530 100644 --- a/packages/contract-wrappers/src/types.ts +++ b/packages/contract-wrappers/src/types.ts @@ -1,25 +1,28 @@ -import { BigNumber } from '@0xproject/utils'; +import { + ERC20TokenEventArgs, + ERC20TokenEvents, + ERC721TokenEventArgs, + ERC721TokenEvents, + ExchangeEventArgs, + ExchangeEvents, + WETH9EventArgs, + WETH9Events, +} from '@0x/abi-gen-wrappers'; +import { ContractAddresses } from '@0x/contract-addresses'; +import { OrderState, SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; -import { OrderState, SignedOrder } from '@0xproject/types'; import { BlockParam, ContractEventArg, DecodedLogArgs, LogEntryEvent, LogWithDecodedArgs } from 'ethereum-types'; -import { ERC20TokenEventArgs, ERC20TokenEvents } from './contract_wrappers/generated/erc20_token'; -import { ERC721TokenEventArgs, ERC721TokenEvents } from './contract_wrappers/generated/erc721_token'; -import { ExchangeEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange'; -import { WETH9EventArgs, WETH9Events } from './contract_wrappers/generated/weth9'; - export enum ExchangeWrapperError { AssetDataMismatch = 'ASSET_DATA_MISMATCH', } +export enum ForwarderWrapperError { + CompleteFillFailed = 'COMPLETE_FILL_FAILED', +} + export enum ContractWrappersError { - ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST', - ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST', - EtherTokenContractDoesNotExist = 'ETHER_TOKEN_CONTRACT_DOES_NOT_EXIST', - ERC20ProxyContractDoesNotExist = 'ERC20_PROXY_CONTRACT_DOES_NOT_EXIST', - ERC721ProxyContractDoesNotExist = 'ERC721_PROXY_CONTRACT_DOES_NOT_EXIST', - ERC20TokenContractDoesNotExist = 'ERC20_TOKEN_CONTRACT_DOES_NOT_EXIST', - ERC721TokenContractDoesNotExist = 'ERC721_TOKEN_CONTRACT_DOES_NOT_EXIST', ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK', InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER', InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER', @@ -31,6 +34,7 @@ export enum ContractWrappersError { SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT', ERC721OwnerNotFound = 'ERC_721_OWNER_NOT_FOUND', ERC721NoApproval = 'ERC_721_NO_APPROVAL', + SignatureRequestDenied = 'SIGNATURE_REQUEST_DENIED', } export enum InternalContractWrappersError { @@ -105,22 +109,13 @@ 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 - * exchangeContractAddress: The address of an exchange contract to use - * zrxContractAddress: The address of the ZRX contract to use - * erc20ProxyContractAddress: The address of the erc20 token transfer proxy contract to use - * erc721ProxyContractAddress: The address of the erc721 token transfer proxy contract to use - * forwarderContractAddress: The address of the forwarder contract to use - * orderWatcherConfig: All the configs related to the orderWatcher + * 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; - exchangeContractAddress?: string; - zrxContractAddress?: string; - erc20ProxyContractAddress?: string; - erc721ProxyContractAddress?: string; - forwarderContractAddress?: string; + contractAddresses?: ContractAddresses; blockPollingIntervalMs?: number; } diff --git a/packages/contract-wrappers/src/utils/assert.ts b/packages/contract-wrappers/src/utils/assert.ts index 30726c546..3f02ed052 100644 --- a/packages/contract-wrappers/src/utils/assert.ts +++ b/packages/contract-wrappers/src/utils/assert.ts @@ -1,10 +1,10 @@ -import { assert as sharedAssert } from '@0xproject/assert'; +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 '@0xproject/json-schemas'; // tslint:disable-line:no-unused-variable -import { assetDataUtils, signatureUtils } from '@0xproject/order-utils'; -import { Order } from '@0xproject/types'; // tslint:disable-line:no-unused-variable -import { BigNumber } from '@0xproject/utils'; // tslint:disable-line:no-unused-variable -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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'; diff --git a/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts b/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts index 3172cf531..bee7acaa7 100644 --- a/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts +++ b/packages/contract-wrappers/src/utils/calldata_optimization_utils.ts @@ -1,4 +1,4 @@ -import { SignedOrder } from '@0xproject/types'; +import { SignedOrder } from '@0x/types'; import * as _ from 'lodash'; import { constants } from './constants'; diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts index 78441decf..c587ba526 100644 --- a/packages/contract-wrappers/src/utils/constants.ts +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -1,4 +1,4 @@ -import { BigNumber } from '@0xproject/utils'; +import { BigNumber } from '@0x/utils'; export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', @@ -14,4 +14,5 @@ export const constants = { ZERO_AMOUNT: new BigNumber(0), ONE_AMOUNT: new BigNumber(1), ETHER_TOKEN_DECIMALS: 18, + USER_DENIED_SIGNATURE_PATTERN: 'User denied transaction signature', }; diff --git a/packages/contract-wrappers/src/utils/contract_addresses.ts b/packages/contract-wrappers/src/utils/contract_addresses.ts new file mode 100644 index 000000000..dc156e017 --- /dev/null +++ b/packages/contract-wrappers/src/utils/contract_addresses.ts @@ -0,0 +1,15 @@ +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 index e17246015..a4207ae4c 100644 --- a/packages/contract-wrappers/src/utils/decorators.ts +++ b/packages/contract-wrappers/src/utils/decorators.ts @@ -29,6 +29,14 @@ const schemaErrorTransformer = (error: Error) => { return error; }; +const signatureRequestErrorTransformer = (error: Error) => { + if (_.includes(error.message, constants.USER_DENIED_SIGNATURE_PATTERN)) { + const errMsg = ContractWrappersError.SignatureRequestDenied; + return new Error(errMsg); + } + return error; +}; + /** * Source: https://stackoverflow.com/a/29837695/3546986 */ @@ -87,7 +95,11 @@ const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => { }; // _.flow(f, g) = f ∘ g -const zeroExErrorTransformer = _.flow(schemaErrorTransformer, contractCallErrorTransformer); +const zeroExErrorTransformer = _.flow( + schemaErrorTransformer, + contractCallErrorTransformer, + signatureRequestErrorTransformer, +); export const decorators = { asyncZeroExErrorHandler: asyncErrorHandlerFactory(zeroExErrorTransformer), diff --git a/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts index a7c4a238f..f374d509b 100644 --- a/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts +++ b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts @@ -1,5 +1,5 @@ -import { ExchangeContractErrs } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +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'; diff --git a/packages/contract-wrappers/src/utils/transaction_encoder.ts b/packages/contract-wrappers/src/utils/transaction_encoder.ts index 33086944b..0cf08a8fe 100644 --- a/packages/contract-wrappers/src/utils/transaction_encoder.ts +++ b/packages/contract-wrappers/src/utils/transaction_encoder.ts @@ -1,10 +1,10 @@ -import { schemas } from '@0xproject/json-schemas'; -import { eip712Utils } from '@0xproject/order-utils'; -import { Order, SignedOrder } from '@0xproject/types'; -import { BigNumber, signTypedDataUtils } from '@0xproject/utils'; -import _ = require('lodash'); +import { ExchangeContract } from '@0x/abi-gen-wrappers'; -import { ExchangeContract } from '../contract_wrappers/generated/exchange'; +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'; diff --git a/packages/contract-wrappers/src/utils/utils.ts b/packages/contract-wrappers/src/utils/utils.ts index f7949ec34..0b3270e78 100644 --- a/packages/contract-wrappers/src/utils/utils.ts +++ b/packages/contract-wrappers/src/utils/utils.ts @@ -1,5 +1,6 @@ -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import { BigNumber } from '@0x/utils'; +import { Web3Wrapper } from '@0x/web3-wrapper'; +import * as _ from 'lodash'; import { constants } from './constants'; @@ -14,4 +15,7 @@ export const utils = { numberPercentageToEtherTokenAmountPercentage(percentage: number): BigNumber { return Web3Wrapper.toBaseUnitAmount(constants.ONE_AMOUNT, constants.ETHER_TOKEN_DECIMALS).mul(percentage); }, + removeUndefinedProperties<T extends object>(obj: T): Partial<T> { + return _.pickBy(obj); + }, }; diff --git a/packages/contract-wrappers/test/artifacts_test.ts b/packages/contract-wrappers/test/artifacts_test.ts deleted file mode 100644 index c05d513b3..000000000 --- a/packages/contract-wrappers/test/artifacts_test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { web3Factory } from '@0xproject/dev-utils'; - -import { ContractWrappers } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { constants } from './utils/constants'; - -chaiSetup.configure(); - -// Those tests are slower cause they're talking to a remote node -const TIMEOUT = 10000; - -// TODO: Re-enable those tests after final kovan and ropsten deployments are done. -describe.skip('Artifacts', () => { - describe('contracts are deployed on kovan', () => { - const kovanRpcUrl = constants.KOVAN_RPC_URL; - const provider = web3Factory.getRpcProvider({ rpcUrl: kovanRpcUrl }); - const config = { - networkId: constants.KOVAN_NETWORK_ID, - }; - const contractWrappers = new ContractWrappers(provider, config); - it('erc20 proxy contract is deployed', async () => { - await (contractWrappers.erc20Proxy as any)._getTokenTransferProxyContractAsync(); - }).timeout(TIMEOUT); - it('erc721 proxy contract is deployed', async () => { - await (contractWrappers.erc721Proxy as any)._getTokenTransferProxyContractAsync(); - }).timeout(TIMEOUT); - }); - describe('contracts are deployed on ropsten', () => { - const ropstenRpcUrl = constants.ROPSTEN_RPC_URL; - const provider = web3Factory.getRpcProvider({ rpcUrl: ropstenRpcUrl }); - const config = { - networkId: constants.ROPSTEN_NETWORK_ID, - }; - const contractWrappers = new ContractWrappers(provider, config); - it('erc20 proxy contract is deployed', async () => { - await (contractWrappers.erc20Proxy as any)._getTokenTransferProxyContractAsync(); - }).timeout(TIMEOUT); - it('erc721 proxy contract is deployed', async () => { - await (contractWrappers.erc721Proxy as any)._getTokenTransferProxyContractAsync(); - }).timeout(TIMEOUT); - }); -}); diff --git a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts index 94e55bffa..6cb8a669e 100644 --- a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts +++ b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts @@ -1,4 +1,4 @@ -import { orderFactory } from '@0xproject/order-utils/lib/src/order_factory'; +import { orderFactory } from '@0x/order-utils/lib/src/order_factory'; import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; diff --git a/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts b/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts index 6bf9f1e25..d8dfa4204 100644 --- a/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts +++ b/packages/contract-wrappers/test/erc20_proxy_wrapper_test.ts @@ -4,6 +4,7 @@ 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(); @@ -11,10 +12,13 @@ const expect = chai.expect; describe('ERC20ProxyWrapper', () => { let contractWrappers: ContractWrappers; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; before(async () => { + const contractAddresses = await migrateOnceAsync(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); }); describe('#isAuthorizedAsync', () => { diff --git a/packages/contract-wrappers/test/erc20_wrapper_test.ts b/packages/contract-wrappers/test/erc20_wrapper_test.ts index fde587dec..15d3a9ead 100644 --- a/packages/contract-wrappers/test/erc20_wrapper_test.ts +++ b/packages/contract-wrappers/test/erc20_wrapper_test.ts @@ -1,7 +1,8 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0xproject/subproviders'; -import { DoneCallback } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +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'; @@ -10,16 +11,17 @@ import { BlockParamLiteral, BlockRange, ContractWrappers, + ContractWrappersConfig, ContractWrappersError, + DecodedLogEvent, ERC20TokenApprovalEventArgs, ERC20TokenEvents, ERC20TokenTransferEventArgs, } 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'; @@ -29,14 +31,20 @@ 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; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; + 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(); @@ -72,19 +80,6 @@ describe('ERC20Wrapper', () => { contractWrappers.erc20Token.transferAsync(tokenAddress, fromAddress, toAddress, transferAmount), ).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - const fromAddress = coinbase; - const toAddress = coinbase; - return expect( - contractWrappers.erc20Token.transferAsync( - nonExistentTokenAddress, - fromAddress, - toAddress, - transferAmount, - ), - ).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist); - }); }); describe('#transferFromAsync', () => { let tokenAddress: string; @@ -189,19 +184,6 @@ describe('ERC20Wrapper', () => { const postBalance = await contractWrappers.erc20Token.getBalanceAsync(tokenAddress, toAddress); return expect(postBalance).to.be.bignumber.equal(transferAmount); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const fromAddress = coinbase; - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - return expect( - contractWrappers.erc20Token.transferFromAsync( - nonExistentTokenAddress, - fromAddress, - toAddress, - senderAddress, - new BigNumber(42), - ), - ).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist); - }); }); describe('#getBalanceAsync', () => { describe('With provider with accounts', () => { @@ -212,13 +194,6 @@ describe('ERC20Wrapper', () => { const expectedBalance = new BigNumber('1000000000000000000000000000'); return expect(balance).to.be.bignumber.equal(expectedBalance); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - const ownerAddress = coinbase; - return expect( - contractWrappers.erc20Token.getBalanceAsync(nonExistentTokenAddress, ownerAddress), - ).to.be.rejectedWith(ContractWrappersError.ERC20TokenContractDoesNotExist); - }); it('should return a balance of 0 for a non-existent owner address', async () => { const tokenAddress = tokens[0]; const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593'; @@ -294,7 +269,7 @@ describe('ERC20Wrapper', () => { }); it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => { const transferAmount = new BigNumber(5); - const zrxAddress = tokenUtils.getProtocolTokenAddress(); + const zrxAddress = contractAddresses.zrxToken; const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses; await contractWrappers.erc20Token.setAllowanceAsync( zrxAddress, @@ -525,7 +500,7 @@ describe('ERC20Wrapper', () => { ); })().catch(done); }); - it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (_logEvent: DecodedLogEvent<ERC20TokenApprovalEventArgs>) => { @@ -539,7 +514,7 @@ describe('ERC20Wrapper', () => { callbackNeverToBeCalled, ); const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.unsubscribeAll(); contractWrappers.erc20Token.subscribe( tokenAddress, ERC20TokenEvents.Transfer, @@ -588,7 +563,7 @@ describe('ERC20Wrapper', () => { let txHash: string; before(() => { tokenAddress = tokens[0]; - tokenTransferProxyAddress = contractWrappers.erc20Proxy.getContractAddress(); + tokenTransferProxyAddress = contractWrappers.erc20Proxy.address; }); it('should get logs with decoded args emitted by Approval', async () => { txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); diff --git a/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts b/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts index 9473d930b..9b0fe8817 100644 --- a/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts +++ b/packages/contract-wrappers/test/erc721_proxy_wrapper_test.ts @@ -4,6 +4,7 @@ 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(); @@ -11,10 +12,13 @@ const expect = chai.expect; describe('ERC721ProxyWrapper', () => { let contractWrappers: ContractWrappers; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; before(async () => { + const contractAddresses = await migrateOnceAsync(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); }); describe('#isAuthorizedAsync', () => { diff --git a/packages/contract-wrappers/test/erc721_wrapper_test.ts b/packages/contract-wrappers/test/erc721_wrapper_test.ts index 10bac6086..a7f1e4c41 100644 --- a/packages/contract-wrappers/test/erc721_wrapper_test.ts +++ b/packages/contract-wrappers/test/erc721_wrapper_test.ts @@ -1,7 +1,7 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0xproject/subproviders'; -import { DoneCallback } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +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'; @@ -10,16 +10,18 @@ import { BlockParamLiteral, BlockRange, ContractWrappers, + ContractWrappersConfig, ContractWrappersError, + DecodedLogEvent, ERC721TokenApprovalEventArgs, ERC721TokenApprovalForAllEventArgs, ERC721TokenEvents, ERC721TokenTransferEventArgs, } 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'; @@ -37,10 +39,15 @@ describe('ERC721Wrapper', () => { let operatorAddress: string; let approvedAddress: string; let receiverAddress: string; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; + 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(); @@ -108,12 +115,6 @@ describe('ERC721Wrapper', () => { tokenCount = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, ownerAddress); expect(tokenCount).to.be.bignumber.equal(1); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - return expect( - contractWrappers.erc721Token.getTokenCountAsync(nonExistentTokenAddress, ownerAddress), - ).to.be.rejectedWith(ContractWrappersError.ERC721TokenContractDoesNotExist); - }); it('should return a balance of 0 for a non-existent owner address', async () => { const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593'; const balance = await contractWrappers.erc721Token.getTokenCountAsync(tokenAddress, nonExistentOwner); @@ -142,13 +143,6 @@ describe('ERC721Wrapper', () => { const tokenOwner = await contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, tokenId); expect(tokenOwner).to.be.bignumber.equal(ownerAddress); }); - it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { - const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; - const fakeTokenId = new BigNumber(42); - return expect( - contractWrappers.erc721Token.getOwnerOfAsync(nonExistentTokenAddress, fakeTokenId), - ).to.be.rejectedWith(ContractWrappersError.ERC721TokenContractDoesNotExist); - }); it('should return undefined not 0 for a non-existent ERC721', async () => { const fakeTokenId = new BigNumber(42); return expect(contractWrappers.erc721Token.getOwnerOfAsync(tokenAddress, fakeTokenId)).to.be.rejectedWith( @@ -319,7 +313,7 @@ describe('ERC721Wrapper', () => { ); })().catch(done); }); - it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ERC721TokenApprovalEventArgs>) => { @@ -333,7 +327,7 @@ describe('ERC721Wrapper', () => { callbackNeverToBeCalled, ); const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.unsubscribeAll(); contractWrappers.erc721Token.subscribe( tokenAddress, ERC721TokenEvents.Approval, diff --git a/packages/contract-wrappers/test/ether_token_wrapper_test.ts b/packages/contract-wrappers/test/ether_token_wrapper_test.ts index c48fc224f..e3efef19d 100644 --- a/packages/contract-wrappers/test/ether_token_wrapper_test.ts +++ b/packages/contract-wrappers/test/ether_token_wrapper_test.ts @@ -1,7 +1,8 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { DoneCallback } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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'; @@ -16,12 +17,11 @@ import { WETH9TransferEventArgs, WETH9WithdrawalEventArgs, } from '../src'; - import { DecodedLogEvent } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { tokenUtils } from './utils/token_utils'; +import { migrateOnceAsync } from './utils/migrate'; import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); @@ -36,6 +36,7 @@ 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; @@ -43,19 +44,22 @@ describe('EtherTokenWrapper', () => { const decimalPlaces = 7; let addressWithoutFunds: string; const gasPrice = new BigNumber(1); - const zeroExConfig = { - gasPrice, - networkId: constants.TESTRPC_NETWORK_ID, - }; const transferAmount = new BigNumber(42); const allowanceAmount = new BigNumber(42); const depositAmount = new BigNumber(42); const withdrawalAmount = new BigNumber(42); before(async () => { - contractWrappers = new ContractWrappers(provider, zeroExConfig); + 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 = contractWrappers.etherToken.getContractAddressIfExists() as string; + wethContractAddress = contractAddresses.etherToken; depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5)); addressWithoutFunds = userAddresses[1]; }); @@ -67,7 +71,7 @@ describe('EtherTokenWrapper', () => { }); describe('#getContractAddressIfExists', async () => { it('should return contract address if connected to a known network', () => { - const contractAddressIfExists = contractWrappers.etherToken.getContractAddressIfExists(); + 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', () => { @@ -172,7 +176,7 @@ describe('EtherTokenWrapper', () => { const indexFilterValues = {}; let etherTokenAddress: string; before(async () => { - etherTokenAddress = tokenUtils.getWethTokenAddress(); + etherTokenAddress = contractAddresses.etherToken; }); afterEach(() => { contractWrappers.etherToken.unsubscribeAll(); @@ -279,7 +283,7 @@ describe('EtherTokenWrapper', () => { await contractWrappers.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH); })().catch(done); }); - it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => { + it('should cancel outstanding subscriptions when contractWrappers.unsubscribeAll is called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (_logEvent: DecodedLogEvent<WETH9ApprovalEventArgs>) => { @@ -293,7 +297,7 @@ describe('EtherTokenWrapper', () => { callbackNeverToBeCalled, ); const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); - contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.unsubscribeAll(); await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); contractWrappers.etherToken.subscribe( etherTokenAddress, @@ -341,8 +345,8 @@ describe('EtherTokenWrapper', () => { let txHash: string; before(async () => { addressWithETH = userAddresses[0]; - etherTokenAddress = tokenUtils.getWethTokenAddress(); - erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress(); + 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; diff --git a/packages/contract-wrappers/test/exchange_wrapper_test.ts b/packages/contract-wrappers/test/exchange_wrapper_test.ts index b3bd7c633..73ce6c743 100644 --- a/packages/contract-wrappers/test/exchange_wrapper_test.ts +++ b/packages/contract-wrappers/test/exchange_wrapper_test.ts @@ -1,8 +1,8 @@ -import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils'; -import { FillScenarios } from '@0xproject/fill-scenarios'; -import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; -import { DoneCallback, SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +import { 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'; @@ -12,6 +12,7 @@ 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'; @@ -27,37 +28,38 @@ describe('ExchangeWrapper', () => { let exchangeContractAddress: string; let makerTokenAddress: string; let takerTokenAddress: string; - let coinbase: string; let makerAddress: string; let anotherMakerAddress: string; let takerAddress: string; let makerAssetData: string; let takerAssetData: string; - let feeRecipient: string; let txHash: string; const fillableAmount = new BigNumber(5); const takerTokenFillAmount = new BigNumber(5); let signedOrder: SignedOrder; let anotherSignedOrder: SignedOrder; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - blockPollingIntervalMs: 0, - }; + 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.getContractAddress(); + exchangeContractAddress = contractWrappers.exchange.address; userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; fillScenarios = new FillScenarios( provider, userAddresses, zrxTokenAddress, exchangeContractAddress, - contractWrappers.erc20Proxy.getContractAddress(), - contractWrappers.erc721Proxy.getContractAddress(), + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, ); - [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; + [, makerAddress, takerAddress, , anotherMakerAddress] = userAddresses; [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); [makerAssetData, takerAssetData] = [ assetDataUtils.encodeERC20AssetData(makerTokenAddress), @@ -280,6 +282,19 @@ describe('ExchangeWrapper', () => { 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); @@ -329,11 +344,11 @@ describe('ExchangeWrapper', () => { 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.getContractAddress(); + 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.getContractAddress(); + const erc721ProxyAddress = contractWrappers.erc721Proxy.address; expect(erc721ProxyAddressById).to.be.equal(erc721ProxyAddress); }); }); @@ -408,7 +423,7 @@ describe('ExchangeWrapper', () => { await contractWrappers.exchange.cancelOrderAsync(signedOrder); })().catch(done); }); - it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when contractWrappers.unsubscribeAll called', (done: DoneCallback) => { (async () => { const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ExchangeFillEventArgs>) => { @@ -417,7 +432,7 @@ describe('ExchangeWrapper', () => { ); contractWrappers.exchange.subscribe(ExchangeEvents.Fill, indexFilterValues, callbackNeverToBeCalled); - contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.unsubscribeAll(); const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ExchangeFillEventArgs>) => { @@ -454,13 +469,6 @@ describe('ExchangeWrapper', () => { })().catch(done); }); }); - describe('#getZRXTokenAddressAsync', () => { - it('gets the same token as is in token registry', () => { - const zrxAddressFromExchangeWrapper = contractWrappers.exchange.getZRXTokenAddress(); - const zrxAddress = tokenUtils.getProtocolTokenAddress(); - expect(zrxAddressFromExchangeWrapper).to.equal(zrxAddress); - }); - }); describe('#getLogsAsync', () => { const blockRange = { fromBlock: 0, diff --git a/packages/contract-wrappers/test/forwarder_wrapper_test.ts b/packages/contract-wrappers/test/forwarder_wrapper_test.ts index 4329e8770..ff4ff8b67 100644 --- a/packages/contract-wrappers/test/forwarder_wrapper_test.ts +++ b/packages/contract-wrappers/test/forwarder_wrapper_test.ts @@ -1,8 +1,8 @@ -import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { FillScenarios } from '@0xproject/fill-scenarios'; -import { assetDataUtils } from '@0xproject/order-utils'; -import { SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +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'; @@ -10,6 +10,7 @@ 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'; @@ -19,21 +20,14 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); // tslint:disable:custom-no-magic-numbers describe('ForwarderWrapper', () => { - const contractWrappersConfig = { - networkId: constants.TESTRPC_NETWORK_ID, - blockPollingIntervalMs: 0, - }; const fillableAmount = new BigNumber(5); let contractWrappers: ContractWrappers; let fillScenarios: FillScenarios; let exchangeContractAddress: string; let zrxTokenAddress: 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; @@ -41,22 +35,28 @@ describe('ForwarderWrapper', () => { let signedOrder: SignedOrder; let anotherSignedOrder: SignedOrder; before(async () => { + const contractAddresses = await migrateOnceAsync(); await blockchainLifecycle.startAsync(); - contractWrappers = new ContractWrappers(provider, contractWrappersConfig); - exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; + contractWrappers = new ContractWrappers(provider, config); + exchangeContractAddress = contractWrappers.exchange.address; userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; fillScenarios = new FillScenarios( provider, userAddresses, zrxTokenAddress, exchangeContractAddress, - contractWrappers.erc20Proxy.getContractAddress(), - contractWrappers.erc721Proxy.getContractAddress(), + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, ); - [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; + [, makerAddress, takerAddress] = userAddresses; [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - takerTokenAddress = tokenUtils.getWethTokenAddress(); + takerTokenAddress = contractWrappers.forwarder.etherTokenAddress; [makerAssetData, takerAssetData] = [ assetDataUtils.encodeERC20AssetData(makerTokenAddress), assetDataUtils.encodeERC20AssetData(takerTokenAddress), diff --git a/packages/contract-wrappers/test/global_hooks.ts b/packages/contract-wrappers/test/global_hooks.ts index 8731318e7..e23739b59 100644 --- a/packages/contract-wrappers/test/global_hooks.ts +++ b/packages/contract-wrappers/test/global_hooks.ts @@ -1,17 +1,6 @@ -import { devConstants } from '@0xproject/dev-utils'; -import { runV2MigrationsAsync } from '@0xproject/migrations'; - -import { provider } from './utils/web3_wrapper'; - -before('migrate contracts', async function(): Promise<void> { +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 - const txDefaults = { - gas: devConstants.GAS_LIMIT, - from: devConstants.TESTRPC_FIRST_ADDRESS, - }; - const artifactsDir = `src/artifacts`; - await runV2MigrationsAsync(provider, artifactsDir, txDefaults); }); diff --git a/packages/contract-wrappers/test/order_validator_wrapper_test.ts b/packages/contract-wrappers/test/order_validator_wrapper_test.ts index baac3eeee..da3f99e72 100644 --- a/packages/contract-wrappers/test/order_validator_wrapper_test.ts +++ b/packages/contract-wrappers/test/order_validator_wrapper_test.ts @@ -1,8 +1,9 @@ -import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { FillScenarios } from '@0xproject/fill-scenarios'; -import { assetDataUtils } from '@0xproject/order-utils'; -import { SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +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'; @@ -12,6 +13,7 @@ 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'; @@ -20,10 +22,6 @@ const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('OrderValidator', () => { - const contractWrappersConfig = { - networkId: constants.TESTRPC_NETWORK_ID, - blockPollingIntervalMs: 0, - }; const fillableAmount = new BigNumber(5); let contractWrappers: ContractWrappers; let fillScenarios: FillScenarios; @@ -42,24 +40,32 @@ describe('OrderValidator', () => { let takerAssetData: string; let signedOrder: SignedOrder; let anotherSignedOrder: SignedOrder; + let contractAddresses: ContractAddresses; + before(async () => { + contractAddresses = await migrateOnceAsync(); await blockchainLifecycle.startAsync(); - contractWrappers = new ContractWrappers(provider, contractWrappersConfig); - exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; + contractWrappers = new ContractWrappers(provider, config); + exchangeContractAddress = contractWrappers.exchange.address; userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; zrxTokenAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress); fillScenarios = new FillScenarios( provider, userAddresses, zrxTokenAddress, exchangeContractAddress, - contractWrappers.erc20Proxy.getContractAddress(), - contractWrappers.erc721Proxy.getContractAddress(), + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, ); [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); - takerTokenAddress = tokenUtils.getWethTokenAddress(); + takerTokenAddress = contractAddresses.etherToken; [makerAssetData, takerAssetData] = [ assetDataUtils.encodeERC20AssetData(makerTokenAddress), assetDataUtils.encodeERC20AssetData(takerTokenAddress), diff --git a/packages/contract-wrappers/test/revert_validation_test.ts b/packages/contract-wrappers/test/revert_validation_test.ts index da011c1d7..efd5dd61f 100644 --- a/packages/contract-wrappers/test/revert_validation_test.ts +++ b/packages/contract-wrappers/test/revert_validation_test.ts @@ -1,10 +1,10 @@ -import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; -import { FillScenarios } from '@0xproject/fill-scenarios'; -import { runV2MigrationsAsync } from '@0xproject/migrations'; -import { assetDataUtils } from '@0xproject/order-utils'; -import { SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +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'; @@ -20,28 +20,19 @@ const expect = chai.expect; describe('Revert Validation ExchangeWrapper', () => { let contractWrappers: ContractWrappers; let userAddresses: string[]; - let zrxTokenAddress: string; let fillScenarios: FillScenarios; - let exchangeContractAddress: string; let makerTokenAddress: string; let takerTokenAddress: string; - let coinbase: string; let makerAddress: string; - let anotherMakerAddress: string; let takerAddress: string; let makerAssetData: string; let takerAssetData: string; - let feeRecipient: string; let txHash: string; let blockchainLifecycle: BlockchainLifecycle; let web3Wrapper: Web3Wrapper; const fillableAmount = new BigNumber(5); const takerTokenFillAmount = new BigNumber(5); let signedOrder: SignedOrder; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - blockPollingIntervalMs: 0, - }; 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 @@ -52,29 +43,31 @@ describe('Revert Validation ExchangeWrapper', () => { }); 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, }; - const artifactsDir = `src/artifacts`; - // 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. - await runV2MigrationsAsync(provider, artifactsDir, txDefaults); await blockchainLifecycle.startAsync(); + const contractAddresses = await runMigrationsAsync(provider, txDefaults); + const config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + blockPollingIntervalMs: 10, + }; contractWrappers = new ContractWrappers(provider, config); - exchangeContractAddress = contractWrappers.exchange.getContractAddress(); userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); fillScenarios = new FillScenarios( provider, userAddresses, - zrxTokenAddress, - exchangeContractAddress, - contractWrappers.erc20Proxy.getContractAddress(), - contractWrappers.erc721Proxy.getContractAddress(), + contractAddresses.zrxToken, + contractAddresses.exchange, + contractAddresses.erc20Proxy, + contractAddresses.erc721Proxy, ); - [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses; + [, makerAddress, takerAddress] = userAddresses; [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); [makerAssetData, takerAssetData] = [ assetDataUtils.encodeERC20AssetData(makerTokenAddress), @@ -112,7 +105,7 @@ describe('Revert Validation ExchangeWrapper', () => { makerTokenBalance, ); await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - expect( + return expect( contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress, { shouldValidate: true, }), diff --git a/packages/contract-wrappers/test/subscription_test.ts b/packages/contract-wrappers/test/subscription_test.ts index 6ec7519fe..0fa6af40d 100644 --- a/packages/contract-wrappers/test/subscription_test.ts +++ b/packages/contract-wrappers/test/subscription_test.ts @@ -1,14 +1,20 @@ -import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { DoneCallback } from '@0xproject/types'; +import { BlockchainLifecycle } from '@0x/dev-utils'; +import { DoneCallback } from '@0x/types'; import * as _ from 'lodash'; import 'mocha'; import * as Sinon from 'sinon'; -import { ContractWrappers, ERC20TokenApprovalEventArgs, ERC20TokenEvents } from '../src'; -import { DecodedLogEvent } from '../src/types'; +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'; @@ -17,10 +23,14 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('SubscriptionTest', () => { let contractWrappers: ContractWrappers; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - }; + let config: ContractWrappersConfig; + before(async () => { + const contractAddresses = await migrateOnceAsync(); + config = { + networkId: constants.TESTRPC_NETWORK_ID, + contractAddresses, + }; contractWrappers = new ContractWrappers(provider, config); }); beforeEach(async () => { diff --git a/packages/contract-wrappers/test/transaction_encoder_test.ts b/packages/contract-wrappers/test/transaction_encoder_test.ts index 9da8fe2ca..ef9eb2cf3 100644 --- a/packages/contract-wrappers/test/transaction_encoder_test.ts +++ b/packages/contract-wrappers/test/transaction_encoder_test.ts @@ -1,14 +1,15 @@ -import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { FillScenarios } from '@0xproject/fill-scenarios'; -import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils, signatureUtils } from '@0xproject/order-utils'; -import { SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; +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'; @@ -31,23 +32,26 @@ describe('TransactionEncoder', () => { const fillableAmount = new BigNumber(5); const takerTokenFillAmount = new BigNumber(5); let signedOrder: SignedOrder; - const config = { - networkId: constants.TESTRPC_NETWORK_ID, - blockPollingIntervalMs: 0, - }; + 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.getContractAddress(); + exchangeContractAddress = contractWrappers.exchange.address; userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - const zrxTokenAddress = tokenUtils.getProtocolTokenAddress(); + const zrxTokenAddress = contractWrappers.exchange.zrxTokenAddress; fillScenarios = new FillScenarios( provider, userAddresses, zrxTokenAddress, exchangeContractAddress, - contractWrappers.erc20Proxy.getContractAddress(), - contractWrappers.erc721Proxy.getContractAddress(), + contractWrappers.erc20Proxy.address, + contractWrappers.erc721Proxy.address, ); [coinbase, makerAddress, takerAddress, senderAddress] = userAddresses; [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); diff --git a/packages/contract-wrappers/test/utils/constants.ts b/packages/contract-wrappers/test/utils/constants.ts index f38728b77..ca6c574e4 100644 --- a/packages/contract-wrappers/test/utils/constants.ts +++ b/packages/contract-wrappers/test/utils/constants.ts @@ -1,4 +1,4 @@ -import { BigNumber } from '@0xproject/utils'; +import { BigNumber } from '@0x/utils'; export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', diff --git a/packages/contract-wrappers/test/utils/migrate.ts b/packages/contract-wrappers/test/utils/migrate.ts new file mode 100644 index 000000000..665ce0faa --- /dev/null +++ b/packages/contract-wrappers/test/utils/migrate.ts @@ -0,0 +1,18 @@ +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 index 06a82ff6e..f8a88637f 100644 --- a/packages/contract-wrappers/test/utils/token_utils.ts +++ b/packages/contract-wrappers/test/utils/token_utils.ts @@ -1,14 +1,13 @@ -import { generatePseudoRandomSalt } from '@0xproject/order-utils'; -import { BigNumber } from '@0xproject/utils'; +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 { artifacts } from '../../src/artifacts'; -import { DummyERC721TokenContract } from '../../src/contract_wrappers/generated/dummy_erc721_token'; - -import { constants } from './constants'; 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 = [ '0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f', '0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db', @@ -20,12 +19,6 @@ const DUMMY_ERC_20_ADRESSES = [ const DUMMY_ERC_721_ADRESSES = ['0x131855dda0aaff096f6854854c55a4debf61077a']; export const tokenUtils = { - getProtocolTokenAddress(): string { - return artifacts.ZRXToken.networks[constants.TESTRPC_NETWORK_ID].address; - }, - getWethTokenAddress(): string { - return artifacts.EtherToken.networks[constants.TESTRPC_NETWORK_ID].address; - }, getDummyERC20TokenAddresses(): string[] { return DUMMY_ERC_20_ADRESSES; }, @@ -33,12 +26,7 @@ export const tokenUtils = { return DUMMY_ERC_721_ADRESSES; }, async mintDummyERC721Async(address: string, tokenOwner: string): Promise<BigNumber> { - const erc721 = new DummyERC721TokenContract( - artifacts.DummyERC721Token.compilerOutput.abi, - address, - provider, - txDefaults, - ); + const erc721 = new DummyERC721TokenContract(DummyERC721Token.compilerOutput.abi, address, provider, txDefaults); const tokenId = generatePseudoRandomSalt(); const txHash = await erc721.mint.sendTransactionAsync(tokenOwner, tokenId); web3Wrapper.awaitTransactionSuccessAsync(txHash); diff --git a/packages/contract-wrappers/test/utils/web3_wrapper.ts b/packages/contract-wrappers/test/utils/web3_wrapper.ts index 02c8c5918..4e86ebeba 100644 --- a/packages/contract-wrappers/test/utils/web3_wrapper.ts +++ b/packages/contract-wrappers/test/utils/web3_wrapper.ts @@ -1,5 +1,5 @@ -import { devConstants, web3Factory } from '@0xproject/dev-utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import { devConstants, web3Factory } from '@0x/dev-utils'; +import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider } from 'ethereum-types'; const txDefaults = { diff --git a/packages/contract-wrappers/tslint.json b/packages/contract-wrappers/tslint.json index ffaefe83a..dd9053357 100644 --- a/packages/contract-wrappers/tslint.json +++ b/packages/contract-wrappers/tslint.json @@ -1,3 +1,3 @@ { - "extends": ["@0xproject/tslint-config"] + "extends": ["@0x/tslint-config"] } |