aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contract-wrappers
diff options
context:
space:
mode:
Diffstat (limited to 'packages/contract-wrappers')
-rw-r--r--packages/contract-wrappers/CHANGELOG.json123
-rw-r--r--packages/contract-wrappers/CHANGELOG.md46
-rw-r--r--packages/contract-wrappers/package.json68
-rw-r--r--packages/contract-wrappers/src/artifacts.ts4
-rw-r--r--packages/contract-wrappers/src/contract_wrappers.ts10
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts59
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts7
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts7
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts7
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts7
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts7
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts104
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts17
-rw-r--r--packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts187
-rw-r--r--packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts77
-rw-r--r--packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts29
-rw-r--r--packages/contract-wrappers/src/index.ts53
-rw-r--r--packages/contract-wrappers/src/monorepo_scripts/postpublish.ts8
-rw-r--r--packages/contract-wrappers/src/types.ts21
-rw-r--r--packages/contract-wrappers/src/utils/assert.ts6
-rw-r--r--packages/contract-wrappers/src/utils/constants.ts2
-rw-r--r--packages/contract-wrappers/src/utils/decorators.ts7
-rw-r--r--packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts2
-rw-r--r--packages/contract-wrappers/src/utils/filter_utils.ts2
-rw-r--r--packages/contract-wrappers/src/utils/transaction_encoder.ts293
-rw-r--r--packages/contract-wrappers/src/utils/utils.ts6
-rw-r--r--packages/contract-wrappers/test/calldata_optimization_utils_test.ts3
-rw-r--r--packages/contract-wrappers/test/erc20_wrapper_test.ts3
-rw-r--r--packages/contract-wrappers/test/erc721_wrapper_test.ts21
-rw-r--r--packages/contract-wrappers/test/ether_token_wrapper_test.ts5
-rw-r--r--packages/contract-wrappers/test/exchange_wrapper_test.ts12
-rw-r--r--packages/contract-wrappers/test/forwarder_wrapper_test.ts19
-rw-r--r--packages/contract-wrappers/test/global_hooks.ts2
-rw-r--r--packages/contract-wrappers/test/order_validator_wrapper_test.ts140
-rw-r--r--packages/contract-wrappers/test/revert_validation_test.ts122
-rw-r--r--packages/contract-wrappers/test/subscription_test.ts17
-rw-r--r--packages/contract-wrappers/test/transaction_encoder_test.ts211
-rw-r--r--packages/contract-wrappers/test/utils/constants.ts1
-rw-r--r--packages/contract-wrappers/tsconfig.json3
-rw-r--r--packages/contract-wrappers/typedoc-tsconfig.json7
40 files changed, 1580 insertions, 145 deletions
diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json
index fdf779338..a96cb3a59 100644
--- a/packages/contract-wrappers/CHANGELOG.json
+++ b/packages/contract-wrappers/CHANGELOG.json
@@ -1,5 +1,128 @@
[
{
+ "version": "2.0.2",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1538693146
+ },
+ {
+ "timestamp": 1538157789,
+ "version": "2.0.1",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ]
+ },
+ {
+ "version": "2.0.0",
+ "changes": [
+ {
+ "note":
+ "Fixes dropped events in subscriptions by fetching logs by blockHash instead of blockNumber. Support for fetching by blockHash was added in Geth > v1.8.13 and Parity > v2.1.0. Infura works too.",
+ "pr": 1080
+ },
+ {
+ "note":
+ "Fix misunderstanding about blockstream interface callbacks and pass the raw JSON RPC responses to it",
+ "pr": 1080
+ }
+ ],
+ "timestamp": 1537907159
+ },
+ {
+ "version": "1.0.5",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1537875740
+ },
+ {
+ "version": "1.0.4",
+ "changes": [
+ {
+ "note": "Dependencies updated"
+ }
+ ],
+ "timestamp": 1537541580
+ },
+ {
+ "version": "1.0.3",
+ "changes": [
+ {
+ "note": "Drastically reduce the bundle size by removing unused parts of included contract artifacts."
+ }
+ ],
+ "timestamp": 1537369748
+ },
+ {
+ "version": "1.0.2",
+ "changes": [
+ {
+ "note": "Add ZRX & WETH mainnet contract addresses into the included artifacts"
+ }
+ ],
+ "timestamp": 1537265493
+ },
+ {
+ "version": "1.0.1",
+ "changes": [
+ {
+ "note": "Add `OrderValidatorWrapper`"
+ },
+ {
+ "note":
+ "Fix bug where contracts not deployed on a network showed an `EXCHANGE_CONTRACT_DOES_NOT_EXIST` error instead of `CONTRACT_NOT_DEPLOYED_ON_NETWORK`",
+ "pr": 1044
+ },
+ {
+ "note":
+ "Export `AssetBalanceAndProxyAllowanceFetcher` and `OrderFilledCancelledFetcher` implementations",
+ "pr": 1054
+ },
+ {
+ "note":
+ "Add `validateOrderFillableOrThrowAsync` and `validateFillOrderThrowIfInvalidAsync` to ExchangeWrapper",
+ "pr": 1054
+ }
+ ],
+ "timestamp": 1536142250
+ },
+ {
+ "version": "1.0.1-rc.5",
+ "changes": [
+ {
+ "note": "Fix missing `BlockParamLiteral` type import issue"
+ }
+ ],
+ "timestamp": 1535377027
+ },
+ {
+ "version": "1.0.1-rc.4",
+ "changes": [
+ {
+ "note":
+ "Export missing types: `TransactionEncoder`, `ContractAbi`, `JSONRPCRequestPayload`, `JSONRPCResponsePayload`, `JSONRPCErrorCallback`, `AbiDefinition`, `FunctionAbi`, `EventAbi`, `EventParameter`, `DecodedLogArgs`, `MethodAbi`, `ConstructorAbi`, `FallbackAbi`, `DataItem`, `ConstructorStateMutability`, `StateMutability` & `ExchangeSignatureValidatorApprovalEventArgs`",
+ "pr": 924
+ },
+ {
+ "note":
+ "Remove superfluous exported types: `ContractEvent`, `Token`, `OrderFillRequest`, `ContractEventArgs`, `LogEvent`, `OnOrderStateChangeCallback`, `ECSignature`, `OrderStateValid`, `OrderStateInvalid`, `OrderState`, `FilterObject`, `TransactionReceipt` & `TransactionReceiptWithDecodedLogs`",
+ "pr": 924
+ },
+ {
+ "note": "Added Transaction Encoder for use with 0x Exchange executeTransaction",
+ "pr": 975
+ }
+ ],
+ "timestamp": 1535133899
+ },
+ {
"version": "1.0.1-rc.3",
"changes": [
{
diff --git a/packages/contract-wrappers/CHANGELOG.md b/packages/contract-wrappers/CHANGELOG.md
index c2ad7218e..60675ddbe 100644
--- a/packages/contract-wrappers/CHANGELOG.md
+++ b/packages/contract-wrappers/CHANGELOG.md
@@ -5,6 +5,52 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
+## v2.0.2 - _October 4, 2018_
+
+ * Dependencies updated
+
+## v2.0.1 - _September 28, 2018_
+
+ * Dependencies updated
+
+## v2.0.0 - _September 25, 2018_
+
+ * Fixes dropped events in subscriptions by fetching logs by blockHash instead of blockNumber. Support for fetching by blockHash was added in Geth > v1.8.13 and Parity > v2.1.0. Infura works too. (#1080)
+ * Fix misunderstanding about blockstream interface callbacks and pass the raw JSON RPC responses to it (#1080)
+
+## v1.0.5 - _September 25, 2018_
+
+ * Dependencies updated
+
+## v1.0.4 - _September 21, 2018_
+
+ * Dependencies updated
+
+## v1.0.3 - _September 19, 2018_
+
+ * Drastically reduce the bundle size by removing unused parts of included contract artifacts.
+
+## v1.0.2 - _September 18, 2018_
+
+ * Add ZRX & WETH mainnet contract addresses into the included artifacts
+
+## v1.0.1 - _September 5, 2018_
+
+ * Add `OrderValidatorWrapper`
+ * Fix bug where contracts not deployed on a network showed an `EXCHANGE_CONTRACT_DOES_NOT_EXIST` error instead of `CONTRACT_NOT_DEPLOYED_ON_NETWORK` (#1044)
+ * Export `AssetBalanceAndProxyAllowanceFetcher` and `OrderFilledCancelledFetcher` implementations (#1054)
+ * Add `validateOrderFillableOrThrowAsync` and `validateFillOrderThrowIfInvalidAsync` to ExchangeWrapper (#1054)
+
+## v1.0.1-rc.5 - _August 27, 2018_
+
+ * Fix missing `BlockParamLiteral` type import issue
+
+## v1.0.1-rc.4 - _August 24, 2018_
+
+ * Export missing types: `TransactionEncoder`, `ContractAbi`, `JSONRPCRequestPayload`, `JSONRPCResponsePayload`, `JSONRPCErrorCallback`, `AbiDefinition`, `FunctionAbi`, `EventAbi`, `EventParameter`, `DecodedLogArgs`, `MethodAbi`, `ConstructorAbi`, `FallbackAbi`, `DataItem`, `ConstructorStateMutability`, `StateMutability` & `ExchangeSignatureValidatorApprovalEventArgs` (#924)
+ * Remove superfluous exported types: `ContractEvent`, `Token`, `OrderFillRequest`, `ContractEventArgs`, `LogEvent`, `OnOrderStateChangeCallback`, `ECSignature`, `OrderStateValid`, `OrderStateInvalid`, `OrderState`, `FilterObject`, `TransactionReceipt` & `TransactionReceiptWithDecodedLogs` (#924)
+ * Added Transaction Encoder for use with 0x Exchange executeTransaction (#975)
+
## v1.0.1-rc.3 - _August 13, 2018_
* Added strict encoding/decoding checks for sendTransaction and call (#915)
diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json
index 7667b5b7f..e83caad97 100644
--- a/packages/contract-wrappers/package.json
+++ b/packages/contract-wrappers/package.json
@@ -1,6 +1,6 @@
{
"name": "@0xproject/contract-wrappers",
- "version": "1.0.1-rc.3",
+ "version": "2.0.2",
"description": "Smart TS wrappers for 0x smart contracts",
"keywords": [
"0xproject",
@@ -11,26 +11,27 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
- "watch_without_deps": "yarn pre_build && tsc -w",
- "build": "yarn pre_build && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
- "pre_build": "run-s update_artifacts_v2_beta update_artifacts_v2 generate_contract_wrappers copy_artifacts",
- "generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers",
+ "build": "yarn pre_build && tsc -b",
+ "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/**/*",
"test:circleci": "run-s test:coverage",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
- "update_artifacts_v2_beta": "for i in ${npm_package_config_contracts_v2_beta}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-beta-testnet/$i.json src/artifacts; done;",
- "update_artifacts_v2": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json src/artifacts; done;",
+ "update_artifacts": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-trimmed/$i.json src/artifacts; done;",
"copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts",
- "clean": "shx rm -rf _bundles lib test_temp scripts test/artifacts src/contract_wrappers/generated src/artifacts",
+ "clean": "shx rm -rf _bundles lib test_temp test/artifacts src/contract_wrappers/generated src/artifacts generated_docs",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
- "manual:postpublish": "yarn build; node ./scripts/postpublish.js"
+ "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
- "contracts_v2_beta": "Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder",
- "contracts_v2": "DummyERC20Token DummyERC721Token"
+ "contracts_v2": "AssetProxyOwner Exchange ERC20Proxy ERC20Token ERC721Proxy ERC721Token WETH9 ZRXToken Forwarder OrderValidator DummyERC20Token DummyERC721Token",
+ "postpublish": {
+ "assets": []
+ }
},
"repository": {
"type": "git",
@@ -41,23 +42,21 @@
"node": ">=6.0.0"
},
"devDependencies": {
- "@0xproject/abi-gen": "^1.0.5",
- "@0xproject/dev-utils": "^1.0.4",
- "@0xproject/migrations": "^1.0.4",
- "@0xproject/monorepo-scripts": "^1.0.5",
- "@0xproject/sol-compiler": "^1.0.5",
- "@0xproject/subproviders": "^1.0.5",
- "@0xproject/tslint-config": "^1.0.5",
+ "@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",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
- "@types/node": "^8.0.53",
+ "@types/node": "*",
"@types/sinon": "^2.2.2",
"@types/uuid": "^3.4.2",
- "awesome-typescript-loader": "^3.1.3",
+ "@types/web3-provider-engine": "^14.0.0",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
- "copyfiles": "^1.2.0",
+ "copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
@@ -68,23 +67,24 @@
"sinon": "^4.0.0",
"source-map-support": "^0.5.0",
"tslint": "5.11.0",
- "typescript": "2.9.2",
+ "typedoc": "0.12.0",
+ "typescript": "3.0.1",
"web3-provider-engine": "14.0.6"
},
"dependencies": {
- "@0xproject/assert": "^1.0.5",
- "@0xproject/base-contract": "^2.0.0-rc.1",
- "@0xproject/fill-scenarios": "^1.0.1-rc.3",
- "@0xproject/json-schemas": "^1.0.1-rc.4",
- "@0xproject/order-utils": "^1.0.1-rc.3",
- "@0xproject/types": "^1.0.1-rc.4",
- "@0xproject/typescript-typings": "^1.0.4",
- "@0xproject/utils": "^1.0.5",
- "@0xproject/web3-wrapper": "^1.2.0",
- "ethereum-types": "^1.0.4",
- "ethereumjs-blockstream": "5.0.0",
+ "@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",
+ "ethereumjs-blockstream": "6.0.0",
"ethereumjs-util": "^5.1.1",
- "ethers": "3.0.22",
+ "ethers": "4.0.0-beta.14",
"js-sha3": "^0.7.0",
"lodash": "^4.17.5",
"uuid": "^3.1.0"
diff --git a/packages/contract-wrappers/src/artifacts.ts b/packages/contract-wrappers/src/artifacts.ts
index 2481b311a..925f34162 100644
--- a/packages/contract-wrappers/src/artifacts.ts
+++ b/packages/contract-wrappers/src/artifacts.ts
@@ -1,4 +1,4 @@
-import { ContractArtifact } from '@0xproject/sol-compiler';
+import { ContractArtifact } from 'ethereum-types';
import * as DummyERC20Token from './artifacts/DummyERC20Token.json';
import * as DummyERC721Token from './artifacts/DummyERC721Token.json';
@@ -8,6 +8,7 @@ import * as ERC721Proxy from './artifacts/ERC721Proxy.json';
import * as ERC721Token from './artifacts/ERC721Token.json';
import * as Exchange from './artifacts/Exchange.json';
import * as Forwarder from './artifacts/Forwarder.json';
+import * as OrderValidator from './artifacts/OrderValidator.json';
import * as EtherToken from './artifacts/WETH9.json';
import * as ZRXToken from './artifacts/ZRXToken.json';
@@ -22,4 +23,5 @@ export const artifacts = {
ERC20Proxy: (ERC20Proxy as any) as ContractArtifact,
ERC721Proxy: (ERC721Proxy as any) as ContractArtifact,
Forwarder: (Forwarder as any) as ContractArtifact,
+ OrderValidator: (OrderValidator as any) as ContractArtifact,
};
diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts
index 4277a0746..89402029b 100644
--- a/packages/contract-wrappers/src/contract_wrappers.ts
+++ b/packages/contract-wrappers/src/contract_wrappers.ts
@@ -12,6 +12,7 @@ import { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
import { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper';
+import { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper';
import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema';
import { contractWrappersPrivateNetworkConfigSchema } from './schemas/contract_wrappers_private_network_config_schema';
import { contractWrappersPublicNetworkConfigSchema } from './schemas/contract_wrappers_public_network_config_schema';
@@ -52,8 +53,12 @@ export class ContractWrappers {
* An instance of the ForwarderWrapper class containing methods for interacting with any Forwarder smart contract.
*/
public forwarder: ForwarderWrapper;
+ /**
+ * An instance of the OrderValidatorWrapper class containing methods for interacting with any OrderValidator smart contract.
+ */
+ public orderValidator: OrderValidatorWrapper;
- private _web3Wrapper: Web3Wrapper;
+ 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
@@ -106,6 +111,8 @@ export class ContractWrappers {
this.exchange = new ExchangeWrapper(
this._web3Wrapper,
config.networkId,
+ this.erc20Token,
+ this.erc721Token,
config.exchangeContractAddress,
config.zrxContractAddress,
blockPollingIntervalMs,
@@ -116,6 +123,7 @@ export class ContractWrappers {
config.forwarderContractAddress,
config.zrxContractAddress,
);
+ this.orderValidator = new OrderValidatorWrapper(this._web3Wrapper, config.networkId);
}
/**
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
diff --git a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts
index daf70253a..f7a89e3be 100644
--- a/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts
@@ -1,7 +1,15 @@
-import { ContractArtifact } from '@0xproject/sol-compiler';
import { AbiDecoder, intervalUtils, logUtils } from '@0xproject/utils';
-import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from 'ethereum-types';
+import { marshaller, Web3Wrapper } from '@0xproject/web3-wrapper';
+import {
+ BlockParamLiteral,
+ ContractAbi,
+ ContractArtifact,
+ FilterObject,
+ LogEntry,
+ LogWithDecodedArgs,
+ RawLog,
+ RawLogEntry,
+} from 'ethereum-types';
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
import * as _ from 'lodash';
@@ -138,16 +146,20 @@ export abstract class ContractWrapper {
}
protected _getContractAddress(artifact: ContractArtifact, addressIfExists?: string): string {
if (_.isUndefined(addressIfExists)) {
+ if (_.isUndefined(artifact.networks[this._networkId])) {
+ throw new Error(ContractWrappersError.ContractNotDeployedOnNetwork);
+ }
const contractAddress = artifact.networks[this._networkId].address;
if (_.isUndefined(contractAddress)) {
- throw new Error(ContractWrappersError.ExchangeContractDoesNotExist);
+ throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contractName]);
}
return contractAddress;
} else {
return addressIfExists;
}
}
- private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, log: LogEntry): void {
+ private _onLogStateChanged<ArgsType extends ContractEventArgs>(isRemoved: boolean, rawLog: RawLogEntry): void {
+ const log: LogEntry = marshaller.unmarshalLog(rawLog);
_.forEach(this._filters, (filter: FilterObject, filterToken: string) => {
if (filterUtils.matchesFilter(log, filter)) {
const decodedLog = this._tryToDecodeLogOrNoop(log) as LogWithDecodedArgs<ArgsType>;
@@ -164,8 +176,8 @@ export abstract class ContractWrapper {
throw new Error(ContractWrappersError.SubscriptionAlreadyPresent);
}
this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
- this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
- this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
+ this._blockstreamGetBlockOrNullAsync.bind(this),
+ this._blockstreamGetLogsAsync.bind(this),
ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose),
);
const catchAllLogFilter = {};
@@ -184,6 +196,32 @@ export abstract class ContractWrapper {
this._onLogStateChanged.bind(this, isRemoved),
);
}
+ // This method only exists in order to comply with the expected interface of Blockstream's constructor
+ private async _blockstreamGetBlockOrNullAsync(hash: string): Promise<Block | null> {
+ const shouldIncludeTransactionData = false;
+ const blockOrNull = await this._web3Wrapper.sendRawPayloadAsync<Block | null>({
+ method: 'eth_getBlockByHash',
+ params: [hash, shouldIncludeTransactionData],
+ });
+ return blockOrNull;
+ }
+ // This method only exists in order to comply with the expected interface of Blockstream's constructor
+ private async _blockstreamGetLatestBlockOrNullAsync(): Promise<Block | null> {
+ const shouldIncludeTransactionData = false;
+ const blockOrNull = await this._web3Wrapper.sendRawPayloadAsync<Block | null>({
+ method: 'eth_getBlockByNumber',
+ params: [BlockParamLiteral.Latest, shouldIncludeTransactionData],
+ });
+ return blockOrNull;
+ }
+ // This method only exists in order to comply with the expected interface of Blockstream's constructor
+ private async _blockstreamGetLogsAsync(filterOptions: FilterObject): Promise<RawLogEntry[]> {
+ const logs = await this._web3Wrapper.sendRawPayloadAsync<RawLogEntry[]>({
+ method: 'eth_getLogs',
+ params: [filterOptions],
+ });
+ return logs as RawLogEntry[];
+ }
// HACK: This should be a package-scoped method (which doesn't exist in TS)
// We don't want this method available in the public interface for all classes
// who inherit from ContractWrapper, and it is only used by the internal implementation
@@ -202,11 +240,14 @@ export abstract class ContractWrapper {
delete this._blockAndLogStreamerIfExists;
}
private async _reconcileBlockAsync(): Promise<void> {
- const latestBlock = await this._web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
+ const latestBlockOrNull = await this._blockstreamGetLatestBlockOrNullAsync();
+ if (_.isNull(latestBlockOrNull)) {
+ return; // noop
+ }
// We need to coerce to Block type cause Web3.Block includes types for mempool blocks
if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
// If we clear the interval while fetching the block - this._blockAndLogStreamer will be undefined
- await this._blockAndLogStreamerIfExists.reconcileNewBlock((latestBlock as any) as Block);
+ await this._blockAndLogStreamerIfExists.reconcileNewBlock(latestBlockOrNull);
}
}
}
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 821d1a8a2..ff027d78a 100644
--- a/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/erc20_proxy_wrapper.ts
@@ -16,6 +16,13 @@ export class ERC20ProxyWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.ERC20Proxy.compilerOutput.abi;
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.
+ */
constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
super(web3Wrapper, networkId);
this._contractAddressIfExists = contractAddressIfExists;
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 17bda5085..4625cef6a 100644
--- a/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/erc20_token_wrapper.ts
@@ -34,6 +34,13 @@ export class ERC20TokenWrapper extends ContractWrapper {
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
private _tokenContractsByAddress: { [address: string]: ERC20TokenContract };
private _erc20ProxyWrapper: ERC20ProxyWrapper;
+ /**
+ * Instantiate ERC20TokenWrapper
+ * @param web3Wrapper Web3Wrapper instance to use
+ * @param networkId Desired networkId
+ * @param erc20ProxyWrapper The ERC20ProxyWrapper instance to use
+ * @param blockPollingIntervalMs The block polling interval to use for active subscriptions
+ */
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
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 38ecd4687..933c1dc27 100644
--- a/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/erc721_proxy_wrapper.ts
@@ -16,6 +16,13 @@ export class ERC721ProxyWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.ERC20Proxy.compilerOutput.abi;
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.
+ */
constructor(web3Wrapper: Web3Wrapper, networkId: number, contractAddressIfExists?: string) {
super(web3Wrapper, networkId);
this._contractAddressIfExists = contractAddressIfExists;
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 7231e0bde..590dbbf74 100644
--- a/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/erc721_token_wrapper.ts
@@ -33,6 +33,13 @@ export class ERC721TokenWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.ERC721Token.compilerOutput.abi;
private _tokenContractsByAddress: { [address: string]: ERC721TokenContract };
private _erc721ProxyWrapper: ERC721ProxyWrapper;
+ /**
+ * Instantiate ERC721TokenWrapper
+ * @param web3Wrapper Web3Wrapper instance to use
+ * @param networkId Desired networkId
+ * @param erc721ProxyWrapper The ERC721ProxyWrapper instance to use
+ * @param blockPollingIntervalMs The block polling interval to use for active subscriptions
+ */
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
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 5046d3667..1ac01812e 100644
--- a/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts
@@ -24,6 +24,13 @@ export class EtherTokenWrapper extends ContractWrapper {
[address: string]: WETH9Contract;
} = {};
private _erc20TokenWrapper: ERC20TokenWrapper;
+ /**
+ * Instantiate EtherTokenWrapper.
+ * @param web3Wrapper Web3Wrapper instance to use
+ * @param networkId Desired networkId
+ * @param erc20TokenWrapper The ERC20TokenWrapper instance to use
+ * @param blockPollingIntervalMs The block polling interval to use for active subscriptions
+ */
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
diff --git a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts
index 48bd00f90..dc9ffcbf7 100644
--- a/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts
@@ -1,12 +1,19 @@
import { schemas } from '@0xproject/json-schemas';
-import { assetDataUtils } from '@0xproject/order-utils';
+import {
+ assetDataUtils,
+ BalanceAndProxyAllowanceLazyStore,
+ ExchangeTransferSimulator,
+ OrderValidationUtils,
+} from '@0xproject/order-utils';
import { AssetProxyId, Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
-import { ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
+import { BlockParamLiteral, ContractAbi, LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { artifacts } from '../artifacts';
+import { AssetBalanceAndProxyAllowanceFetcher } from '../fetchers/asset_balance_and_proxy_allowance_fetcher';
+import { OrderFilledCancelledFetcher } from '../fetchers/order_filled_cancelled_fetcher';
import { methodOptsSchema } from '../schemas/method_opts_schema';
import { orderTxOptsSchema } from '../schemas/order_tx_opts_schema';
import { txOptsSchema } from '../schemas/tx_opts_schema';
@@ -17,12 +24,17 @@ import {
IndexedFilterValues,
MethodOpts,
OrderInfo,
+ OrderStatus,
OrderTransactionOpts,
+ ValidateOrderFillableOpts,
} from '../types';
import { assert } from '../utils/assert';
import { decorators } from '../utils/decorators';
+import { TransactionEncoder } from '../utils/transaction_encoder';
import { ContractWrapper } from './contract_wrapper';
+import { ERC20TokenWrapper } from './erc20_token_wrapper';
+import { ERC721TokenWrapper } from './erc721_token_wrapper';
import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from './generated/exchange';
/**
@@ -32,16 +44,32 @@ import { ExchangeContract, ExchangeEventArgs, ExchangeEvents } from './generated
export class ExchangeWrapper extends ContractWrapper {
public abi: ContractAbi = artifacts.Exchange.compilerOutput.abi;
private _exchangeContractIfExists?: ExchangeContract;
+ private _erc721TokenWrapper: ERC721TokenWrapper;
+ private _erc20TokenWrapper: ERC20TokenWrapper;
private _contractAddressIfExists?: string;
private _zrxContractAddressIfExists?: string;
+ /**
+ * 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
+ */
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
+ erc20TokenWrapper: ERC20TokenWrapper,
+ erc721TokenWrapper: ERC721TokenWrapper,
contractAddressIfExists?: string,
zrxContractAddressIfExists?: string,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
+ this._erc20TokenWrapper = erc20TokenWrapper;
+ this._erc721TokenWrapper = erc721TokenWrapper;
this._contractAddressIfExists = contractAddressIfExists;
this._zrxContractAddressIfExists = zrxContractAddressIfExists;
}
@@ -665,6 +693,7 @@ export class ExchangeWrapper extends ContractWrapper {
* @param leftSignedOrder First order to match.
* @param rightSignedOrder Second order to match.
* @param takerAddress The address that sends the transaction and gets the spread.
+ * @param orderTransactionOpts Optional arguments this method accepts.
* @return Transaction hash.
*/
@decorators.asyncZeroExErrorHandler
@@ -723,6 +752,7 @@ export class ExchangeWrapper extends ContractWrapper {
* @param signerAddress Address that should have signed the given hash.
* @param signature Proof that the hash has been signed by signer.
* @param senderAddress Address that should send the transaction.
+ * @param orderTransactionOpts Optional arguments this method accepts.
* @returns Transaction hash.
*/
@decorators.asyncZeroExErrorHandler
@@ -901,7 +931,7 @@ export class ExchangeWrapper extends ContractWrapper {
/**
* Cancel a given order.
* @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel.
- * @param transactionOpts Optional arguments this method accepts.
+ * @param orderTransactionOpts Optional arguments this method accepts.
* @return Transaction hash.
*/
@decorators.asyncZeroExErrorHandler
@@ -1072,6 +1102,64 @@ export class ExchangeWrapper extends ContractWrapper {
return logs;
}
/**
+ * Validate if the supplied order is fillable, and throw if it isn't
+ * @param signedOrder SignedOrder of interest
+ * @param opts ValidateOrderFillableOpts options (e.g expectedFillTakerTokenAmount.
+ * If it isn't supplied, we check if the order is fillable for a non-zero amount)
+ */
+ public async validateOrderFillableOrThrowAsync(
+ signedOrder: SignedOrder,
+ opts: ValidateOrderFillableOpts = {},
+ ): Promise<void> {
+ const balanceAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher(
+ this._erc20TokenWrapper,
+ this._erc721TokenWrapper,
+ BlockParamLiteral.Latest,
+ );
+ const balanceAllowanceStore = new BalanceAndProxyAllowanceLazyStore(balanceAllowanceFetcher);
+ const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore);
+
+ const expectedFillTakerTokenAmountIfExists = opts.expectedFillTakerTokenAmount;
+ const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
+ const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher);
+ await orderValidationUtils.validateOrderFillableOrThrowAsync(
+ exchangeTradeSimulator,
+ signedOrder,
+ this.getZRXAssetData(),
+ expectedFillTakerTokenAmountIfExists,
+ );
+ }
+ /**
+ * Validate a call to FillOrder and throw if it wouldn't succeed
+ * @param signedOrder SignedOrder of interest
+ * @param fillTakerAssetAmount Amount we'd like to fill the order for
+ * @param takerAddress The taker of the order
+ */
+ public async validateFillOrderThrowIfInvalidAsync(
+ signedOrder: SignedOrder,
+ fillTakerAssetAmount: BigNumber,
+ takerAddress: string,
+ ): Promise<void> {
+ const balanceAllowanceFetcher = new AssetBalanceAndProxyAllowanceFetcher(
+ this._erc20TokenWrapper,
+ this._erc721TokenWrapper,
+ BlockParamLiteral.Latest,
+ );
+ const balanceAllowanceStore = new BalanceAndProxyAllowanceLazyStore(balanceAllowanceFetcher);
+ const exchangeTradeSimulator = new ExchangeTransferSimulator(balanceAllowanceStore);
+
+ const filledCancelledFetcher = new OrderFilledCancelledFetcher(this, BlockParamLiteral.Latest);
+ const orderValidationUtils = new OrderValidationUtils(filledCancelledFetcher);
+ await orderValidationUtils.validateFillOrderThrowIfInvalidAsync(
+ exchangeTradeSimulator,
+ this._web3Wrapper.getProvider(),
+ signedOrder,
+ fillTakerAssetAmount,
+ takerAddress,
+ this.getZRXAssetData(),
+ );
+ }
+ /**
* Retrieves the Ethereum address of the Exchange contract deployed on the network
* that the user-passed web3 provider is connected to.
* @returns The Ethereum address of the Exchange contract being used.
@@ -1097,6 +1185,16 @@ export class ExchangeWrapper extends ContractWrapper {
const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress);
return zrxAssetData;
}
+ /**
+ * Returns a Transaction Encoder. Transaction messages exist for the purpose of calling methods on the Exchange contract
+ * in the context of another address.
+ * @return TransactionEncoder
+ */
+ public async transactionEncoderAsync(): Promise<TransactionEncoder> {
+ const exchangeInstance = await this._getExchangeContractAsync();
+ const encoder = new TransactionEncoder(exchangeInstance);
+ return encoder;
+ }
// tslint:disable:no-unused-variable
private _invalidateContractInstances(): void {
this.unsubscribeAll();
diff --git a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts
index 13ef0fe01..906222731 100644
--- a/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts
+++ b/packages/contract-wrappers/src/contract_wrappers/forwarder_wrapper.ts
@@ -12,6 +12,7 @@ import { TransactionOpts } from '../types';
import { assert } from '../utils/assert';
import { calldataOptimizationUtils } from '../utils/calldata_optimization_utils';
import { constants } from '../utils/constants';
+import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper';
import { ForwarderContract } from './generated/forwarder';
@@ -57,7 +58,7 @@ export class ForwarderWrapper extends ContractWrapper {
takerAddress: string,
ethAmount: BigNumber,
signedFeeOrders: SignedOrder[] = [],
- feePercentage: BigNumber = constants.ZERO_AMOUNT,
+ feePercentage: number = 0,
feeRecipientAddress: string = constants.NULL_ADDRESS,
txOpts: TransactionOpts = {},
): Promise<string> {
@@ -66,7 +67,7 @@ export class ForwarderWrapper extends ContractWrapper {
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.isBigNumber('ethAmount', ethAmount);
assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
- assert.isBigNumber('feePercentage', feePercentage);
+ assert.isNumber('feePercentage', feePercentage);
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
// other assertions
@@ -76,6 +77,8 @@ export class ForwarderWrapper extends ContractWrapper {
this.getZRXTokenAddress(),
this.getEtherTokenAddress(),
);
+ // format feePercentage
+ const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage);
// lowercase input addresses
const normalizedTakerAddress = takerAddress.toLowerCase();
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
@@ -89,7 +92,7 @@ export class ForwarderWrapper extends ContractWrapper {
_.map(optimizedMarketOrders, order => order.signature),
optimizedFeeOrders,
_.map(optimizedFeeOrders, order => order.signature),
- feePercentage,
+ formattedFeePercentage,
feeRecipientAddress,
{
value: ethAmount,
@@ -124,7 +127,7 @@ export class ForwarderWrapper extends ContractWrapper {
takerAddress: string,
ethAmount: BigNumber,
signedFeeOrders: SignedOrder[] = [],
- feePercentage: BigNumber = constants.ZERO_AMOUNT,
+ feePercentage: number = 0,
feeRecipientAddress: string = constants.NULL_ADDRESS,
txOpts: TransactionOpts = {},
): Promise<string> {
@@ -134,7 +137,7 @@ export class ForwarderWrapper extends ContractWrapper {
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
assert.isBigNumber('ethAmount', ethAmount);
assert.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
- assert.isBigNumber('feePercentage', feePercentage);
+ assert.isNumber('feePercentage', feePercentage);
assert.isETHAddressHex('feeRecipientAddress', feeRecipientAddress);
assert.doesConformToSchema('txOpts', txOpts, txOptsSchema);
// other assertions
@@ -144,6 +147,8 @@ export class ForwarderWrapper extends ContractWrapper {
this.getZRXTokenAddress(),
this.getEtherTokenAddress(),
);
+ // format feePercentage
+ const formattedFeePercentage = utils.numberPercentageToEtherTokenAmountPercentage(feePercentage);
// lowercase input addresses
const normalizedTakerAddress = takerAddress.toLowerCase();
const normalizedFeeRecipientAddress = feeRecipientAddress.toLowerCase();
@@ -158,7 +163,7 @@ export class ForwarderWrapper extends ContractWrapper {
_.map(optimizedMarketOrders, order => order.signature),
optimizedFeeOrders,
_.map(optimizedFeeOrders, order => order.signature),
- feePercentage,
+ formattedFeePercentage,
feeRecipientAddress,
{
value: ethAmount,
diff --git a/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts
new file mode 100644
index 000000000..1da88f624
--- /dev/null
+++ b/packages/contract-wrappers/src/contract_wrappers/order_validator_wrapper.ts
@@ -0,0 +1,187 @@
+import { schemas } from '@0xproject/json-schemas';
+import { SignedOrder } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+import { Web3Wrapper } from '@0xproject/web3-wrapper';
+import { ContractAbi } from 'ethereum-types';
+import * as _ from 'lodash';
+
+import { artifacts } from '../artifacts';
+import { BalanceAndAllowance, OrderAndTraderInfo, TraderInfo } from '../types';
+import { assert } from '../utils/assert';
+
+import { ContractWrapper } from './contract_wrapper';
+import { OrderValidatorContract } from './generated/order_validator';
+
+/**
+ * This class includes the functionality related to interacting with the OrderValidator contract.
+ */
+export class OrderValidatorWrapper extends ContractWrapper {
+ public abi: ContractAbi = artifacts.OrderValidator.compilerOutput.abi;
+ private _orderValidatorContractIfExists?: OrderValidatorContract;
+ /**
+ * Instantiate OrderValidatorWrapper
+ * @param web3Wrapper Web3Wrapper instance to use
+ * @param networkId Desired networkId
+ */
+ constructor(web3Wrapper: Web3Wrapper, networkId: number) {
+ super(web3Wrapper, networkId);
+ }
+ /**
+ * Get an object conforming to OrderAndTraderInfo containing on-chain information of the provided order and address
+ * @param order An object conforming to SignedOrder
+ * @param takerAddress An ethereum address
+ * @return OrderAndTraderInfo
+ */
+ public async getOrderAndTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<OrderAndTraderInfo> {
+ assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
+ assert.isETHAddressHex('takerAddress', takerAddress);
+ const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
+ const orderAndTraderInfo = await OrderValidatorContractInstance.getOrderAndTraderInfo.callAsync(
+ order,
+ takerAddress,
+ );
+ const result = {
+ orderInfo: orderAndTraderInfo[0],
+ traderInfo: orderAndTraderInfo[1],
+ };
+ return result;
+ }
+ /**
+ * Get an array of objects conforming to OrderAndTraderInfo containing on-chain information of the provided orders and addresses
+ * @param orders An array of objects conforming to SignedOrder
+ * @param takerAddresses An array of ethereum addresses
+ * @return array of OrderAndTraderInfo
+ */
+ public async getOrdersAndTradersInfoAsync(
+ orders: SignedOrder[],
+ takerAddresses: string[],
+ ): Promise<OrderAndTraderInfo[]> {
+ assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
+ _.forEach(takerAddresses, (takerAddress, index) =>
+ assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
+ );
+ assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
+ const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
+ const ordersAndTradersInfo = await OrderValidatorContractInstance.getOrdersAndTradersInfo.callAsync(
+ orders,
+ takerAddresses,
+ );
+ const orderInfos = ordersAndTradersInfo[0];
+ const traderInfos = ordersAndTradersInfo[1];
+ const result = _.map(orderInfos, (orderInfo, index) => {
+ const traderInfo = traderInfos[index];
+ return {
+ orderInfo,
+ traderInfo,
+ };
+ });
+ return result;
+ }
+ /**
+ * Get an object conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order
+ * @param order An object conforming to SignedOrder
+ * @param takerAddress An ethereum address
+ * @return TraderInfo
+ */
+ public async getTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<TraderInfo> {
+ assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
+ assert.isETHAddressHex('takerAddress', takerAddress);
+ const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
+ const result = await OrderValidatorContractInstance.getTraderInfo.callAsync(order, takerAddress);
+ return result;
+ }
+ /**
+ * Get an array of objects conforming to TraderInfo containing on-chain balance and allowances for maker and taker of order
+ * @param orders An array of objects conforming to SignedOrder
+ * @param takerAddresses An array of ethereum addresses
+ * @return array of TraderInfo
+ */
+ public async getTradersInfoAsync(orders: SignedOrder[], takerAddresses: string[]): Promise<TraderInfo[]> {
+ assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
+ _.forEach(takerAddresses, (takerAddress, index) =>
+ assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
+ );
+ assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
+ const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
+ const result = await OrderValidatorContractInstance.getTradersInfo.callAsync(orders, takerAddresses);
+ return result;
+ }
+ /**
+ * Get an object conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and assetData
+ * @param address An ethereum address
+ * @param assetData An encoded string that can be decoded by a specified proxy contract
+ * @return BalanceAndAllowance
+ */
+ public async getBalanceAndAllowanceAsync(address: string, assetData: string): Promise<BalanceAndAllowance> {
+ assert.isETHAddressHex('address', address);
+ assert.isHexString('assetData', assetData);
+ const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
+ const balanceAndAllowance = await OrderValidatorContractInstance.getBalanceAndAllowance.callAsync(
+ address,
+ assetData,
+ );
+ const result = {
+ balance: balanceAndAllowance[0],
+ allowance: balanceAndAllowance[1],
+ };
+ return result;
+ }
+ /**
+ * Get an array of objects conforming to BalanceAndAllowance containing on-chain balance and allowance for some address and array of assetDatas
+ * @param address An ethereum address
+ * @param assetDatas An array of encoded strings that can be decoded by a specified proxy contract
+ * @return BalanceAndAllowance
+ */
+ public async getBalancesAndAllowancesAsync(address: string, assetDatas: string[]): Promise<BalanceAndAllowance[]> {
+ assert.isETHAddressHex('address', address);
+ _.forEach(assetDatas, (assetData, index) => assert.isHexString(`assetDatas[${index}]`, assetData));
+ const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
+ const balancesAndAllowances = await OrderValidatorContractInstance.getBalancesAndAllowances.callAsync(
+ address,
+ assetDatas,
+ );
+ const balances = balancesAndAllowances[0];
+ const allowances = balancesAndAllowances[1];
+ const result = _.map(balances, (balance, index) => {
+ const allowance = allowances[index];
+ return {
+ balance,
+ allowance,
+ };
+ });
+ return result;
+ }
+ /**
+ * Get owner address of tokenId by calling `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token.
+ * @param tokenAddress An ethereum address
+ * @param tokenId An ERC721 tokenId
+ * @return Owner of tokenId or null address if unowned
+ */
+ public async getERC721TokenOwnerAsync(tokenAddress: string, tokenId: BigNumber): Promise<string | undefined> {
+ assert.isETHAddressHex('tokenAddress', tokenAddress);
+ assert.isBigNumber('tokenId', tokenId);
+ const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
+ const result = await OrderValidatorContractInstance.getERC721TokenOwner.callAsync(tokenAddress, tokenId);
+ return result;
+ }
+ // HACK: We don't want this method to be visible to the other units within that package but not to the end user.
+ // TS doesn't give that possibility and therefore we make it private and access it over an any cast. Because of that tslint sees it as unused.
+ // tslint:disable-next-line:no-unused-variable
+ private _invalidateContractInstance(): void {
+ delete this._orderValidatorContractIfExists;
+ }
+ private async _getOrderValidatorContractAsync(): Promise<OrderValidatorContract> {
+ if (!_.isUndefined(this._orderValidatorContractIfExists)) {
+ return this._orderValidatorContractIfExists;
+ }
+ const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync(artifacts.OrderValidator);
+ const contractInstance = new OrderValidatorContract(
+ abi,
+ address,
+ this._web3Wrapper.getProvider(),
+ this._web3Wrapper.getContractDefaults(),
+ );
+ this._orderValidatorContractIfExists = contractInstance;
+ return this._orderValidatorContractIfExists;
+ }
+}
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
new file mode 100644
index 000000000..023cd5ac3
--- /dev/null
+++ b/packages/contract-wrappers/src/fetchers/asset_balance_and_proxy_allowance_fetcher.ts
@@ -0,0 +1,77 @@
+// 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 { BlockParamLiteral } from 'ethereum-types';
+
+import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper';
+import { ERC721TokenWrapper } from '../contract_wrappers/erc721_token_wrapper';
+
+export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher {
+ private readonly _erc20Token: ERC20TokenWrapper;
+ private readonly _erc721Token: ERC721TokenWrapper;
+ private readonly _stateLayer: BlockParamLiteral;
+ constructor(erc20Token: ERC20TokenWrapper, erc721Token: ERC721TokenWrapper, stateLayer: BlockParamLiteral) {
+ this._erc20Token = erc20Token;
+ this._erc721Token = erc721Token;
+ this._stateLayer = stateLayer;
+ }
+ public async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
+ const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
+ if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) {
+ const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
+ const balance = await this._erc20Token.getBalanceAsync(decodedERC20AssetData.tokenAddress, userAddress, {
+ defaultBlock: this._stateLayer,
+ });
+ return balance;
+ } else {
+ const decodedERC721AssetData = decodedAssetData as ERC721AssetData;
+ const tokenOwner = await this._erc721Token.getOwnerOfAsync(
+ decodedERC721AssetData.tokenAddress,
+ decodedERC721AssetData.tokenId,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ const balance = tokenOwner === userAddress ? new BigNumber(1) : new BigNumber(0);
+ return balance;
+ }
+ }
+ public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
+ const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
+ if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) {
+ const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
+ const proxyAllowance = await this._erc20Token.getProxyAllowanceAsync(
+ decodedERC20AssetData.tokenAddress,
+ userAddress,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ return proxyAllowance;
+ } else {
+ const decodedERC721AssetData = decodedAssetData as ERC721AssetData;
+
+ const isApprovedForAll = await this._erc721Token.isProxyApprovedForAllAsync(
+ decodedERC721AssetData.tokenAddress,
+ userAddress,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ if (isApprovedForAll) {
+ return new BigNumber(this._erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
+ } else {
+ const isApproved = await this._erc721Token.isProxyApprovedAsync(
+ decodedERC721AssetData.tokenAddress,
+ decodedERC721AssetData.tokenId,
+ {
+ defaultBlock: this._stateLayer,
+ },
+ );
+ const proxyAllowance = isApproved ? new BigNumber(1) : new BigNumber(0);
+ return proxyAllowance;
+ }
+ }
+ }
+}
diff --git a/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts b/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts
new file mode 100644
index 000000000..7a252aed3
--- /dev/null
+++ b/packages/contract-wrappers/src/fetchers/order_filled_cancelled_fetcher.ts
@@ -0,0 +1,29 @@
+// tslint:disable:no-unnecessary-type-assertion
+import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
+import { BigNumber } from '@0xproject/utils';
+import { BlockParamLiteral } from 'ethereum-types';
+
+import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
+
+export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher {
+ private readonly _exchange: ExchangeWrapper;
+ private readonly _stateLayer: BlockParamLiteral;
+ constructor(exchange: ExchangeWrapper, stateLayer: BlockParamLiteral) {
+ this._exchange = exchange;
+ this._stateLayer = stateLayer;
+ }
+ public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> {
+ const filledTakerAmount = this._exchange.getFilledTakerAssetAmountAsync(orderHash, {
+ defaultBlock: this._stateLayer,
+ });
+ return filledTakerAmount;
+ }
+ public async isOrderCancelledAsync(orderHash: string): Promise<boolean> {
+ const isCancelled = await this._exchange.isCancelledAsync(orderHash);
+ return isCancelled;
+ }
+ public getZRXAssetData(): string {
+ const zrxAssetData = this._exchange.getZRXAssetData();
+ return zrxAssetData;
+ }
+}
diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts
index 1986e0004..2fcdd2ddb 100644
--- a/packages/contract-wrappers/src/index.ts
+++ b/packages/contract-wrappers/src/index.ts
@@ -6,46 +6,51 @@ export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
export { ForwarderWrapper } from './contract_wrappers/forwarder_wrapper';
+export { OrderValidatorWrapper } from './contract_wrappers/order_validator_wrapper';
+
+export { TransactionEncoder } from './utils/transaction_encoder';
export {
ContractWrappersError,
- EventCallback,
- ContractEvent,
- Token,
IndexedFilterValues,
BlockRange,
- OrderFillRequest,
- ContractEventArgs,
ContractWrappersConfig,
MethodOpts,
OrderTransactionOpts,
TransactionOpts,
- LogEvent,
- DecodedLogEvent,
- OnOrderStateChangeCallback,
OrderStatus,
OrderInfo,
+ EventCallback,
+ DecodedLogEvent,
+ BalanceAndAllowance,
+ OrderAndTraderInfo,
+ TraderInfo,
+ ValidateOrderFillableOpts,
} from './types';
-export {
- Order,
- SignedOrder,
- ECSignature,
- OrderStateValid,
- OrderStateInvalid,
- OrderState,
- AssetProxyId,
-} from '@0xproject/types';
+export { Order, SignedOrder, AssetProxyId } from '@0xproject/types';
export {
BlockParamLiteral,
- FilterObject,
BlockParam,
ContractEventArg,
- LogWithDecodedArgs,
Provider,
- TransactionReceipt,
- TransactionReceiptWithDecodedLogs,
+ ContractAbi,
+ JSONRPCRequestPayload,
+ JSONRPCResponsePayload,
+ JSONRPCErrorCallback,
+ AbiDefinition,
+ LogWithDecodedArgs,
+ FunctionAbi,
+ EventAbi,
+ EventParameter,
+ DecodedLogArgs,
+ MethodAbi,
+ ConstructorAbi,
+ FallbackAbi,
+ DataItem,
+ ConstructorStateMutability,
+ StateMutability,
} from 'ethereum-types';
export {
@@ -75,8 +80,14 @@ export {
export {
ExchangeCancelUpToEventArgs,
ExchangeAssetProxyRegisteredEventArgs,
+ ExchangeSignatureValidatorApprovalEventArgs,
ExchangeFillEventArgs,
ExchangeCancelEventArgs,
ExchangeEventArgs,
ExchangeEvents,
} from './contract_wrappers/generated/exchange';
+
+export { AbstractBalanceAndProxyAllowanceFetcher, AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
+
+export { AssetBalanceAndProxyAllowanceFetcher } from './fetchers/asset_balance_and_proxy_allowance_fetcher';
+export { OrderFilledCancelledFetcher } from './fetchers/order_filled_cancelled_fetcher';
diff --git a/packages/contract-wrappers/src/monorepo_scripts/postpublish.ts b/packages/contract-wrappers/src/monorepo_scripts/postpublish.ts
deleted file mode 100644
index dcb99d0f7..000000000
--- a/packages/contract-wrappers/src/monorepo_scripts/postpublish.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { postpublishUtils } from '@0xproject/monorepo-scripts';
-
-import * as packageJSON from '../package.json';
-import * as tsConfigJSON from '../tsconfig.json';
-
-const cwd = `${__dirname}/..`;
-// tslint:disable-next-line:no-floating-promises
-postpublishUtils.runAsync(packageJSON, tsConfigJSON, cwd);
diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts
index 2b3cdc591..e0b12b7c9 100644
--- a/packages/contract-wrappers/src/types.ts
+++ b/packages/contract-wrappers/src/types.ts
@@ -188,3 +188,24 @@ export enum OrderStatus {
FULLY_FILLED,
CANCELLED,
}
+
+export interface TraderInfo {
+ makerBalance: BigNumber;
+ makerAllowance: BigNumber;
+ takerBalance: BigNumber;
+ takerAllowance: BigNumber;
+ makerZrxBalance: BigNumber;
+ makerZrxAllowance: BigNumber;
+ takerZrxBalance: BigNumber;
+ takerZrxAllowance: BigNumber;
+}
+
+export interface OrderAndTraderInfo {
+ orderInfo: OrderInfo;
+ traderInfo: TraderInfo;
+}
+
+export interface BalanceAndAllowance {
+ balance: BigNumber;
+ allowance: BigNumber;
+}
diff --git a/packages/contract-wrappers/src/utils/assert.ts b/packages/contract-wrappers/src/utils/assert.ts
index 183642170..30726c546 100644
--- a/packages/contract-wrappers/src/utils/assert.ts
+++ b/packages/contract-wrappers/src/utils/assert.ts
@@ -1,8 +1,8 @@
import { assert as sharedAssert } from '@0xproject/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, isValidSignatureAsync } from '@0xproject/order-utils';
-import { ECSignature, Order } from '@0xproject/types'; // 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 { Provider } from 'ethereum-types';
@@ -18,7 +18,7 @@ export const assert = {
signature: string,
signerAddress: string,
): Promise<void> {
- const isValid = await isValidSignatureAsync(provider, orderHash, signature, signerAddress);
+ const isValid = await signatureUtils.isValidSignatureAsync(provider, orderHash, signature, signerAddress);
sharedAssert.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
},
isValidSubscriptionToken(variableName: string, subscriptionToken: string): void {
diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts
index 2df11538c..78441decf 100644
--- a/packages/contract-wrappers/src/utils/constants.ts
+++ b/packages/contract-wrappers/src/utils/constants.ts
@@ -12,4 +12,6 @@ export const constants = {
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
DEFAULT_BLOCK_POLLING_INTERVAL: 1000,
ZERO_AMOUNT: new BigNumber(0),
+ ONE_AMOUNT: new BigNumber(1),
+ ETHER_TOKEN_DECIMALS: 18,
};
diff --git a/packages/contract-wrappers/src/utils/decorators.ts b/packages/contract-wrappers/src/utils/decorators.ts
index 6e77450e8..e17246015 100644
--- a/packages/contract-wrappers/src/utils/decorators.ts
+++ b/packages/contract-wrappers/src/utils/decorators.ts
@@ -1,4 +1,3 @@
-import { RevertReason } from '@0xproject/types';
import * as _ from 'lodash';
import { AsyncMethod, ContractWrappersError, SyncMethod } from '../types';
@@ -24,7 +23,7 @@ const contractCallErrorTransformer = (error: Error) => {
const schemaErrorTransformer = (error: Error) => {
if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) {
const errMsg =
- 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS';
+ 'Order taker must be of type string. If you want anyone to be able to fill an order - pass NULL_ADDRESS';
return new Error(errMsg);
}
return error;
@@ -46,7 +45,7 @@ const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
// tslint:disable-next-line:only-arrow-functions
descriptor.value = async function(...args: any[]): Promise<any> {
try {
- const result = await originalMethod.apply(this, args);
+ const result = await originalMethod.apply(this, args); // tslint:disable-line:no-invalid-this
return result;
} catch (error) {
const transformedError = errorTransformer(error);
@@ -73,7 +72,7 @@ const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
// tslint:disable-next-line:only-arrow-functions
descriptor.value = function(...args: any[]): any {
try {
- const result = originalMethod.apply(this, args);
+ const result = originalMethod.apply(this, args); // tslint:disable-line:no-invalid-this
return result;
} catch (error) {
const transformedError = errorTransformer(error);
diff --git a/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts
index 279f2a796..a7c4a238f 100644
--- a/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts
+++ b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts
@@ -34,7 +34,7 @@ const ERR_MSG_MAPPING = {
};
export class ExchangeTransferSimulator {
- private _store: AbstractBalanceAndProxyAllowanceLazyStore;
+ private readonly _store: AbstractBalanceAndProxyAllowanceLazyStore;
private static _throwValidationError(
failureReason: FailureReason,
tradeSide: TradeSide,
diff --git a/packages/contract-wrappers/src/utils/filter_utils.ts b/packages/contract-wrappers/src/utils/filter_utils.ts
index 0e73987f7..c05be062c 100644
--- a/packages/contract-wrappers/src/utils/filter_utils.ts
+++ b/packages/contract-wrappers/src/utils/filter_utils.ts
@@ -1,4 +1,4 @@
-import { ConstructorAbi, ContractAbi, EventAbi, FallbackAbi, FilterObject, LogEntry, MethodAbi } from 'ethereum-types';
+import { ContractAbi, EventAbi, FilterObject, LogEntry } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as jsSHA3 from 'js-sha3';
import * as _ from 'lodash';
diff --git a/packages/contract-wrappers/src/utils/transaction_encoder.ts b/packages/contract-wrappers/src/utils/transaction_encoder.ts
new file mode 100644
index 000000000..87cbb43fd
--- /dev/null
+++ b/packages/contract-wrappers/src/utils/transaction_encoder.ts
@@ -0,0 +1,293 @@
+import { schemas } from '@0xproject/json-schemas';
+import { EIP712Schema, EIP712Types, eip712Utils } from '@0xproject/order-utils';
+import { Order, SignedOrder } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+import _ = require('lodash');
+
+import { ExchangeContract } from '../contract_wrappers/generated/exchange';
+
+import { assert } from './assert';
+
+const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = {
+ name: 'ZeroExTransaction',
+ parameters: [
+ { name: 'salt', type: EIP712Types.Uint256 },
+ { name: 'signerAddress', type: EIP712Types.Address },
+ { name: 'data', type: EIP712Types.Bytes },
+ ],
+};
+
+/**
+ * Transaction Encoder. Transaction messages exist for the purpose of calling methods on the Exchange contract
+ * in the context of another address. For example, UserA can encode and sign a fillOrder transaction and UserB
+ * can submit this to the blockchain. The Exchange context executes as if UserA had directly submitted this transaction.
+ */
+export class TransactionEncoder {
+ private readonly _exchangeInstance: ExchangeContract;
+ constructor(exchangeInstance: ExchangeContract) {
+ this._exchangeInstance = exchangeInstance;
+ }
+ /**
+ * Encodes the transaction data for use with the Exchange contract.
+ * @param data The ABI Encoded 0x Exchange method. I.e fillOrder
+ * @param salt A random value to provide uniqueness and prevent replay attacks.
+ * @param signerAddress The address which will sign this transaction.
+ * @return An unsigned hex encoded transaction for use in 0x Exchange executeTransaction.
+ */
+ public getTransactionHex(data: string, salt: BigNumber, signerAddress: string): string {
+ const exchangeAddress = this._getExchangeContract().address;
+ const executeTransactionData = {
+ salt,
+ signerAddress,
+ data,
+ };
+ const executeTransactionHashBuff = eip712Utils.structHash(
+ EIP712_ZEROEX_TRANSACTION_SCHEMA,
+ executeTransactionData,
+ );
+ const eip721MessageBuffer = eip712Utils.createEIP712Message(executeTransactionHashBuff, exchangeAddress);
+ const messageHex = `0x${eip721MessageBuffer.toString('hex')}`;
+ return messageHex;
+ }
+ /**
+ * Encodes a fillOrder transaction.
+ * @param signedOrder An object that conforms to the SignedOrder interface.
+ * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
+ * @return Hex encoded abi of the function call.
+ */
+ public fillOrderTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string {
+ assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
+ assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
+ const abiEncodedData = this._getExchangeContract().fillOrder.getABIEncodedTransactionData(
+ signedOrder,
+ takerAssetFillAmount,
+ signedOrder.signature,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a fillOrderNoThrow transaction.
+ * @param signedOrder An object that conforms to the SignedOrder interface.
+ * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
+ * @return Hex encoded abi of the function call.
+ */
+ public fillOrderNoThrowTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string {
+ assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
+ assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
+ const abiEncodedData = this._getExchangeContract().fillOrderNoThrow.getABIEncodedTransactionData(
+ signedOrder,
+ takerAssetFillAmount,
+ signedOrder.signature,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a fillOrKillOrder transaction.
+ * @param signedOrder An object that conforms to the SignedOrder interface.
+ * @param takerAssetFillAmount The amount of the order (in taker asset baseUnits) that you wish to fill.
+ * @return Hex encoded abi of the function call.
+ */
+ public fillOrKillOrderTx(signedOrder: SignedOrder, takerAssetFillAmount: BigNumber): string {
+ assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
+ assert.isValidBaseUnitAmount('takerAssetFillAmount', takerAssetFillAmount);
+ const abiEncodedData = this._getExchangeContract().fillOrKillOrder.getABIEncodedTransactionData(
+ signedOrder,
+ takerAssetFillAmount,
+ signedOrder.signature,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a batchFillOrders transaction.
+ * @param signedOrders An array of signed orders to fill.
+ * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
+ * @return Hex encoded abi of the function call.
+ */
+ public batchFillOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string {
+ assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ _.forEach(takerAssetFillAmounts, takerAssetFillAmount =>
+ assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount),
+ );
+ const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
+ const abiEncodedData = this._getExchangeContract().batchFillOrders.getABIEncodedTransactionData(
+ signedOrders,
+ takerAssetFillAmounts,
+ signatures,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a batchFillOrKillOrders transaction.
+ * @param signedOrders An array of signed orders to fill.
+ * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
+ * @return Hex encoded abi of the function call.
+ */
+ public batchFillOrKillOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string {
+ assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ _.forEach(takerAssetFillAmounts, takerAssetFillAmount =>
+ assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount),
+ );
+ const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
+ const abiEncodedData = this._getExchangeContract().batchFillOrKillOrders.getABIEncodedTransactionData(
+ signedOrders,
+ takerAssetFillAmounts,
+ signatures,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a batchFillOrdersNoThrow transaction.
+ * @param signedOrders An array of signed orders to fill.
+ * @param takerAssetFillAmounts The amounts of the orders (in taker asset baseUnits) that you wish to fill.
+ * @return Hex encoded abi of the function call.
+ */
+ public batchFillOrdersNoThrowTx(signedOrders: SignedOrder[], takerAssetFillAmounts: BigNumber[]): string {
+ assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ _.forEach(takerAssetFillAmounts, takerAssetFillAmount =>
+ assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount),
+ );
+ const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
+ const abiEncodedData = this._getExchangeContract().batchFillOrdersNoThrow.getABIEncodedTransactionData(
+ signedOrders,
+ takerAssetFillAmounts,
+ signatures,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a batchCancelOrders transaction.
+ * @param signedOrders An array of orders to cancel.
+ * @return Hex encoded abi of the function call.
+ */
+ public batchCancelOrdersTx(signedOrders: SignedOrder[]): string {
+ assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ const abiEncodedData = this._getExchangeContract().batchCancelOrders.getABIEncodedTransactionData(signedOrders);
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a cancelOrdersUpTo transaction.
+ * @param targetOrderEpoch Target order epoch.
+ * @return Hex encoded abi of the function call.
+ */
+ public cancelOrdersUpToTx(targetOrderEpoch: BigNumber): string {
+ assert.isBigNumber('targetOrderEpoch', targetOrderEpoch);
+ const abiEncodedData = this._getExchangeContract().cancelOrdersUpTo.getABIEncodedTransactionData(
+ targetOrderEpoch,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a cancelOrder transaction.
+ * @param order An object that conforms to the Order or SignedOrder interface. The order you would like to cancel.
+ * @return Hex encoded abi of the function call.
+ */
+ public cancelOrderTx(order: Order | SignedOrder): string {
+ assert.doesConformToSchema('order', order, schemas.orderSchema);
+ const abiEncodedData = this._getExchangeContract().cancelOrder.getABIEncodedTransactionData(order);
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a marketSellOrders transaction.
+ * @param signedOrders An array of signed orders to fill.
+ * @param takerAssetFillAmount Taker asset fill amount.
+ * @return Hex encoded abi of the function call.
+ */
+ public marketSellOrdersTx(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): string {
+ assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount);
+ const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
+ const abiEncodedData = this._getExchangeContract().marketSellOrders.getABIEncodedTransactionData(
+ signedOrders,
+ takerAssetFillAmount,
+ signatures,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a marketSellOrdersNoThrow transaction.
+ * @param signedOrders An array of signed orders to fill.
+ * @param takerAssetFillAmount Taker asset fill amount.
+ * @return Hex encoded abi of the function call.
+ */
+ public marketSellOrdersNoThrowTx(signedOrders: SignedOrder[], takerAssetFillAmount: BigNumber): string {
+ assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ assert.isBigNumber('takerAssetFillAmount', takerAssetFillAmount);
+ const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
+ const abiEncodedData = this._getExchangeContract().marketSellOrdersNoThrow.getABIEncodedTransactionData(
+ signedOrders,
+ takerAssetFillAmount,
+ signatures,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a maketBuyOrders transaction.
+ * @param signedOrders An array of signed orders to fill.
+ * @param makerAssetFillAmount Maker asset fill amount.
+ * @return Hex encoded abi of the function call.
+ */
+ public marketBuyOrdersTx(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): string {
+ assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount);
+ const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
+ const abiEncodedData = this._getExchangeContract().marketBuyOrders.getABIEncodedTransactionData(
+ signedOrders,
+ makerAssetFillAmount,
+ signatures,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a maketBuyOrdersNoThrow transaction.
+ * @param signedOrders An array of signed orders to fill.
+ * @param makerAssetFillAmount Maker asset fill amount.
+ * @return Hex encoded abi of the function call.
+ */
+ public marketBuyOrdersNoThrowTx(signedOrders: SignedOrder[], makerAssetFillAmount: BigNumber): string {
+ assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
+ assert.isBigNumber('makerAssetFillAmount', makerAssetFillAmount);
+ const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
+ const abiEncodedData = this._getExchangeContract().marketBuyOrdersNoThrow.getABIEncodedTransactionData(
+ signedOrders,
+ makerAssetFillAmount,
+ signatures,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a preSign transaction.
+ * @param hash Hash to pre-sign
+ * @param signerAddress Address that should have signed the given hash.
+ * @param signature Proof that the hash has been signed by signer.
+ * @return Hex encoded abi of the function call.
+ */
+ public preSignTx(hash: string, signerAddress: string, signature: string): string {
+ assert.isHexString('hash', hash);
+ assert.isETHAddressHex('signerAddress', signerAddress);
+ assert.isHexString('signature', signature);
+ const abiEncodedData = this._getExchangeContract().preSign.getABIEncodedTransactionData(
+ hash,
+ signerAddress,
+ signature,
+ );
+ return abiEncodedData;
+ }
+ /**
+ * Encodes a setSignatureValidatorApproval transaction.
+ * @param validatorAddress Validator contract address.
+ * @param isApproved Boolean value to set approval to.
+ * @return Hex encoded abi of the function call.
+ */
+ public setSignatureValidatorApprovalTx(validatorAddress: string, isApproved: boolean): string {
+ assert.isETHAddressHex('validatorAddress', validatorAddress);
+ assert.isBoolean('isApproved', isApproved);
+ const abiEncodedData = this._getExchangeContract().setSignatureValidatorApproval.getABIEncodedTransactionData(
+ validatorAddress,
+ isApproved,
+ );
+ return abiEncodedData;
+ }
+ private _getExchangeContract(): ExchangeContract {
+ return this._exchangeInstance;
+ }
+}
diff --git a/packages/contract-wrappers/src/utils/utils.ts b/packages/contract-wrappers/src/utils/utils.ts
index 689a7ee0a..f7949ec34 100644
--- a/packages/contract-wrappers/src/utils/utils.ts
+++ b/packages/contract-wrappers/src/utils/utils.ts
@@ -1,4 +1,7 @@
import { BigNumber } from '@0xproject/utils';
+import { Web3Wrapper } from '@0xproject/web3-wrapper';
+
+import { constants } from './constants';
export const utils = {
getCurrentUnixTimestampSec(): BigNumber {
@@ -8,4 +11,7 @@ export const utils = {
getCurrentUnixTimestampMs(): BigNumber {
return new BigNumber(Date.now());
},
+ numberPercentageToEtherTokenAmountPercentage(percentage: number): BigNumber {
+ return Web3Wrapper.toBaseUnitAmount(constants.ONE_AMOUNT, constants.ETHER_TOKEN_DECIMALS).mul(percentage);
+ },
};
diff --git a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts
index a4cea772f..94e55bffa 100644
--- a/packages/contract-wrappers/test/calldata_optimization_utils_test.ts
+++ b/packages/contract-wrappers/test/calldata_optimization_utils_test.ts
@@ -1,9 +1,8 @@
-import { orderFactory } from '@0xproject/order-utils';
+import { orderFactory } from '@0xproject/order-utils/lib/src/order_factory';
import * as chai from 'chai';
import * as _ from 'lodash';
import 'mocha';
-import { assert } from '../src/utils/assert';
import { calldataOptimizationUtils } from '../src/utils/calldata_optimization_utils';
import { constants } from '../src/utils/constants';
diff --git a/packages/contract-wrappers/test/erc20_wrapper_test.ts b/packages/contract-wrappers/test/erc20_wrapper_test.ts
index cf7ac527e..fde587dec 100644
--- a/packages/contract-wrappers/test/erc20_wrapper_test.ts
+++ b/packages/contract-wrappers/test/erc20_wrapper_test.ts
@@ -11,12 +11,13 @@ import {
BlockRange,
ContractWrappers,
ContractWrappersError,
- DecodedLogEvent,
ERC20TokenApprovalEventArgs,
ERC20TokenEvents,
ERC20TokenTransferEventArgs,
} from '../src';
+import { DecodedLogEvent } from '../src/types';
+
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { tokenUtils } from './utils/token_utils';
diff --git a/packages/contract-wrappers/test/erc721_wrapper_test.ts b/packages/contract-wrappers/test/erc721_wrapper_test.ts
index f005ac2e0..10bac6086 100644
--- a/packages/contract-wrappers/test/erc721_wrapper_test.ts
+++ b/packages/contract-wrappers/test/erc721_wrapper_test.ts
@@ -11,12 +11,12 @@ import {
BlockRange,
ContractWrappers,
ContractWrappersError,
- DecodedLogEvent,
ERC721TokenApprovalEventArgs,
ERC721TokenApprovalForAllEventArgs,
ERC721TokenEvents,
ERC721TokenTransferEventArgs,
} from '../src';
+import { DecodedLogEvent } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
@@ -229,11 +229,17 @@ describe('ERC721Wrapper', () => {
it('should set the proxy approval', async () => {
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
- const approvalBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync(tokenAddress, tokenId);
- expect(approvalBeforeSet).to.be.false();
+ const isProxyApprovedBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync(
+ tokenAddress,
+ tokenId,
+ );
+ expect(isProxyApprovedBeforeSet).to.be.false();
await contractWrappers.erc721Token.setProxyApprovalAsync(tokenAddress, tokenId);
- const approvalAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync(tokenAddress, tokenId);
- expect(approvalAfterSet).to.be.true();
+ const isProxyApprovedAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync(
+ tokenAddress,
+ tokenId,
+ );
+ expect(isProxyApprovedAfterSet).to.be.true();
});
});
describe('#subscribe', () => {
@@ -357,7 +363,6 @@ describe('ERC721Wrapper', () => {
);
contractWrappers.erc721Token.unsubscribe(subscriptionToken);
- const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await contractWrappers.erc721Token.setApprovalForAllAsync(
@@ -373,15 +378,11 @@ describe('ERC721Wrapper', () => {
});
});
describe('#getLogsAsync', () => {
- let tokenTransferProxyAddress: string;
const blockRange: BlockRange = {
fromBlock: 0,
toBlock: BlockParamLiteral.Latest,
};
let txHash: string;
- before(() => {
- tokenTransferProxyAddress = contractWrappers.erc721Proxy.getContractAddress();
- });
it('should get logs with decoded args emitted by ApprovalForAll', async () => {
const isApprovedForAll = true;
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(
diff --git a/packages/contract-wrappers/test/ether_token_wrapper_test.ts b/packages/contract-wrappers/test/ether_token_wrapper_test.ts
index 48bd6d3f6..c48fc224f 100644
--- a/packages/contract-wrappers/test/ether_token_wrapper_test.ts
+++ b/packages/contract-wrappers/test/ether_token_wrapper_test.ts
@@ -10,7 +10,6 @@ import {
BlockRange,
ContractWrappers,
ContractWrappersError,
- DecodedLogEvent,
WETH9ApprovalEventArgs,
WETH9DepositEventArgs,
WETH9Events,
@@ -18,6 +17,8 @@ import {
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';
@@ -343,7 +344,7 @@ describe('EtherTokenWrapper', () => {
etherTokenAddress = tokenUtils.getWethTokenAddress();
erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
// Start the block range after all migrations to avoid unexpected logs
- const currentBlock = await web3Wrapper.getBlockNumberAsync();
+ const currentBlock: number = await web3Wrapper.getBlockNumberAsync();
const fromBlock = currentBlock + 1;
blockRange = {
fromBlock,
diff --git a/packages/contract-wrappers/test/exchange_wrapper_test.ts b/packages/contract-wrappers/test/exchange_wrapper_test.ts
index fa3b49eb9..b3bd7c633 100644
--- a/packages/contract-wrappers/test/exchange_wrapper_test.ts
+++ b/packages/contract-wrappers/test/exchange_wrapper_test.ts
@@ -7,14 +7,8 @@ import * as chai from 'chai';
import { BlockParamLiteral } from 'ethereum-types';
import 'mocha';
-import {
- ContractWrappers,
- DecodedLogEvent,
- ExchangeCancelEventArgs,
- ExchangeEvents,
- ExchangeFillEventArgs,
- OrderStatus,
-} from '../src';
+import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src';
+import { DecodedLogEvent } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
@@ -364,7 +358,7 @@ describe('ExchangeWrapper', () => {
describe('#getVersionAsync', () => {
it('should return version the hash', async () => {
const version = await contractWrappers.exchange.getVersionAsync();
- const VERSION = '2.0.1-alpha';
+ const VERSION = '2.0.0';
expect(version).to.be.equal(VERSION);
});
});
diff --git a/packages/contract-wrappers/test/forwarder_wrapper_test.ts b/packages/contract-wrappers/test/forwarder_wrapper_test.ts
index 3f3b40e0b..f77b47337 100644
--- a/packages/contract-wrappers/test/forwarder_wrapper_test.ts
+++ b/packages/contract-wrappers/test/forwarder_wrapper_test.ts
@@ -1,20 +1,12 @@
-import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
-import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
-import { DoneCallback, SignedOrder } from '@0xproject/types';
+import { assetDataUtils } from '@0xproject/order-utils';
+import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
-import { BlockParamLiteral } from 'ethereum-types';
import 'mocha';
-import {
- ContractWrappers,
- DecodedLogEvent,
- ExchangeCancelEventArgs,
- ExchangeEvents,
- ExchangeFillEventArgs,
- OrderStatus,
-} from '../src';
+import { ContractWrappers, OrderStatus } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
@@ -31,10 +23,8 @@ describe('ForwarderWrapper', () => {
blockPollingIntervalMs: 0,
};
const fillableAmount = new BigNumber(5);
- const takerTokenFillAmount = new BigNumber(5);
let contractWrappers: ContractWrappers;
let fillScenarios: FillScenarios;
- let forwarderContractAddress: string;
let exchangeContractAddress: string;
let zrxTokenAddress: string;
let userAddresses: string[];
@@ -52,7 +42,6 @@ describe('ForwarderWrapper', () => {
before(async () => {
await blockchainLifecycle.startAsync();
contractWrappers = new ContractWrappers(provider, contractWrappersConfig);
- forwarderContractAddress = contractWrappers.forwarder.getContractAddress();
exchangeContractAddress = contractWrappers.exchange.getContractAddress();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
diff --git a/packages/contract-wrappers/test/global_hooks.ts b/packages/contract-wrappers/test/global_hooks.ts
index 05b23d5b8..8731318e7 100644
--- a/packages/contract-wrappers/test/global_hooks.ts
+++ b/packages/contract-wrappers/test/global_hooks.ts
@@ -12,6 +12,6 @@ before('migrate contracts', async function(): Promise<void> {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
- const artifactsDir = `../migrations/artifacts/2.0.0`;
+ 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
new file mode 100644
index 000000000..baac3eeee
--- /dev/null
+++ b/packages/contract-wrappers/test/order_validator_wrapper_test.ts
@@ -0,0 +1,140 @@
+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 * as chai from 'chai';
+import * as _ from 'lodash';
+import 'mocha';
+
+import { ContractWrappers, OrderStatus } from '../src';
+import { OrderInfo, TraderInfo } from '../src/types';
+
+import { chaiSetup } from './utils/chai_setup';
+import { constants } from './utils/constants';
+import { tokenUtils } from './utils/token_utils';
+import { provider, web3Wrapper } from './utils/web3_wrapper';
+
+chaiSetup.configure();
+const expect = chai.expect;
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+describe('OrderValidator', () => {
+ const contractWrappersConfig = {
+ networkId: constants.TESTRPC_NETWORK_ID,
+ blockPollingIntervalMs: 0,
+ };
+ const fillableAmount = new BigNumber(5);
+ let contractWrappers: ContractWrappers;
+ let fillScenarios: FillScenarios;
+ let exchangeContractAddress: string;
+ let zrxTokenAddress: string;
+ let zrxTokenAssetData: string;
+ let userAddresses: string[];
+ let coinbase: string;
+ let makerAddress: string;
+ let takerAddress: string;
+ let feeRecipient: string;
+ let anotherMakerAddress: string;
+ let makerTokenAddress: string;
+ let takerTokenAddress: string;
+ let makerAssetData: string;
+ let takerAssetData: string;
+ let signedOrder: SignedOrder;
+ let anotherSignedOrder: SignedOrder;
+ before(async () => {
+ await blockchainLifecycle.startAsync();
+ contractWrappers = new ContractWrappers(provider, contractWrappersConfig);
+ exchangeContractAddress = contractWrappers.exchange.getContractAddress();
+ userAddresses = await web3Wrapper.getAvailableAddressesAsync();
+ zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
+ zrxTokenAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress);
+ fillScenarios = new FillScenarios(
+ provider,
+ userAddresses,
+ zrxTokenAddress,
+ exchangeContractAddress,
+ contractWrappers.erc20Proxy.getContractAddress(),
+ contractWrappers.erc721Proxy.getContractAddress(),
+ );
+ [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
+ [makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
+ takerTokenAddress = tokenUtils.getWethTokenAddress();
+ [makerAssetData, takerAssetData] = [
+ assetDataUtils.encodeERC20AssetData(makerTokenAddress),
+ assetDataUtils.encodeERC20AssetData(takerTokenAddress),
+ ];
+
+ signedOrder = await fillScenarios.createFillableSignedOrderAsync(
+ makerAssetData,
+ takerAssetData,
+ makerAddress,
+ constants.NULL_ADDRESS,
+ fillableAmount,
+ );
+ anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync(
+ zrxTokenAssetData,
+ takerAssetData,
+ makerAddress,
+ constants.NULL_ADDRESS,
+ fillableAmount,
+ );
+ });
+ after(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ describe('#getOrdersAndTradersInfoAsync', () => {
+ let signedOrders: SignedOrder[];
+ let takerAddresses: string[];
+ let ordersInfo: OrderInfo[];
+ let tradersInfo: TraderInfo[];
+ beforeEach(async () => {
+ signedOrders = [signedOrder, anotherSignedOrder];
+ takerAddresses = [takerAddress, takerAddress];
+ const ordersAndTradersInfo = await contractWrappers.orderValidator.getOrdersAndTradersInfoAsync(
+ signedOrders,
+ takerAddresses,
+ );
+ ordersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.orderInfo);
+ tradersInfo = _.map(ordersAndTradersInfo, orderAndTraderInfo => orderAndTraderInfo.traderInfo);
+ });
+ it('should return the same number of order infos and trader infos as input orders', async () => {
+ expect(ordersInfo.length).to.be.equal(signedOrders.length);
+ expect(tradersInfo.length).to.be.equal(takerAddresses.length);
+ });
+ it('should return correct on-chain order info for input orders', async () => {
+ const firstOrderInfo = ordersInfo[0];
+ const secondOrderInfo = ordersInfo[1];
+ expect(firstOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE);
+ expect(firstOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
+ expect(secondOrderInfo.orderStatus).to.be.equal(OrderStatus.FILLABLE);
+ expect(secondOrderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
+ });
+ it('should return correct on-chain trader info for input takers', async () => {
+ const firstTraderInfo = tradersInfo[0];
+ const secondTraderInfo = tradersInfo[1];
+ expect(firstTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5));
+ expect(firstTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5));
+ expect(firstTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0));
+ expect(firstTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0));
+ expect(firstTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5));
+ expect(firstTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5));
+ expect(firstTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0));
+ expect(firstTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0));
+ expect(secondTraderInfo.makerBalance).to.bignumber.equal(new BigNumber(5));
+ expect(secondTraderInfo.makerAllowance).to.bignumber.equal(new BigNumber(5));
+ expect(secondTraderInfo.takerBalance).to.bignumber.equal(new BigNumber(0));
+ expect(secondTraderInfo.takerAllowance).to.bignumber.equal(new BigNumber(0));
+ expect(secondTraderInfo.makerZrxBalance).to.bignumber.equal(new BigNumber(5));
+ expect(secondTraderInfo.makerZrxAllowance).to.bignumber.equal(new BigNumber(5));
+ expect(secondTraderInfo.takerZrxBalance).to.bignumber.equal(new BigNumber(0));
+ expect(secondTraderInfo.takerZrxAllowance).to.bignumber.equal(new BigNumber(0));
+ });
+ });
+});
diff --git a/packages/contract-wrappers/test/revert_validation_test.ts b/packages/contract-wrappers/test/revert_validation_test.ts
new file mode 100644
index 000000000..da011c1d7
--- /dev/null
+++ b/packages/contract-wrappers/test/revert_validation_test.ts
@@ -0,0 +1,122 @@
+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 * as chai from 'chai';
+import 'mocha';
+
+import { ContractWrappers } from '../src';
+
+import { chaiSetup } from './utils/chai_setup';
+import { constants } from './utils/constants';
+import { tokenUtils } from './utils/token_utils';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('Revert Validation ExchangeWrapper', () => {
+ let contractWrappers: ContractWrappers;
+ let userAddresses: string[];
+ let 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
+ // are handled in an environment which behaves similar to production
+ const provider = web3Factory.getRpcProvider({
+ shouldUseInProcessGanache: true,
+ shouldThrowErrorsOnGanacheRPCResponse: false,
+ });
+ web3Wrapper = new Web3Wrapper(provider);
+ blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+ 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();
+ 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(),
+ );
+ [coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
+ [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
+ [makerAssetData, takerAssetData] = [
+ assetDataUtils.encodeERC20AssetData(makerTokenAddress),
+ assetDataUtils.encodeERC20AssetData(takerTokenAddress),
+ ];
+ signedOrder = await fillScenarios.createFillableSignedOrderAsync(
+ makerAssetData,
+ takerAssetData,
+ makerAddress,
+ takerAddress,
+ fillableAmount,
+ );
+ });
+ after(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ describe('#fillOrderAsync', () => {
+ it('should throw the revert reason when shouldValidate is true and a fill would revert', async () => {
+ // Create a scenario where the fill will revert
+ const makerTokenBalance = await contractWrappers.erc20Token.getBalanceAsync(
+ makerTokenAddress,
+ makerAddress,
+ );
+ // Transfer all of the tokens from maker to create a failure scenario
+ txHash = await contractWrappers.erc20Token.transferAsync(
+ makerTokenAddress,
+ makerAddress,
+ takerAddress,
+ makerTokenBalance,
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
+ expect(
+ contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress, {
+ shouldValidate: true,
+ }),
+ ).to.be.rejectedWith('TRANSFER_FAILED');
+ });
+ });
+});
diff --git a/packages/contract-wrappers/test/subscription_test.ts b/packages/contract-wrappers/test/subscription_test.ts
index 80d17576f..6ec7519fe 100644
--- a/packages/contract-wrappers/test/subscription_test.ts
+++ b/packages/contract-wrappers/test/subscription_test.ts
@@ -1,11 +1,11 @@
-import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { DoneCallback } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import 'mocha';
import * as Sinon from 'sinon';
-import { ContractWrappers, DecodedLogEvent, ERC20TokenApprovalEventArgs, ERC20TokenEvents, Token } from '../src';
+import { ContractWrappers, ERC20TokenApprovalEventArgs, ERC20TokenEvents } from '../src';
+import { DecodedLogEvent } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
@@ -17,17 +17,11 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('SubscriptionTest', () => {
let contractWrappers: ContractWrappers;
- let userAddresses: string[];
- let coinbase: string;
- let addressWithoutFunds: string;
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
};
before(async () => {
contractWrappers = new ContractWrappers(provider, config);
- userAddresses = await web3Wrapper.getAvailableAddressesAsync();
- coinbase = userAddresses[0];
- addressWithoutFunds = userAddresses[1];
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -38,7 +32,6 @@ describe('SubscriptionTest', () => {
describe('#subscribe', () => {
const indexFilterValues = {};
let tokenAddress: string;
- const allowanceAmount = new BigNumber(42);
let stubs: Sinon.SinonStub[] = [];
before(() => {
const tokenAddresses = tokenUtils.getDummyERC20TokenAddresses();
@@ -52,7 +45,7 @@ describe('SubscriptionTest', () => {
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
(async () => {
const callback = (err: Error | null, _logEvent?: DecodedLogEvent<ERC20TokenApprovalEventArgs>) =>
- _.noop;
+ _.noop.bind(_);
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Approval,
@@ -60,7 +53,7 @@ describe('SubscriptionTest', () => {
callback,
);
stubs = [
- Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws(
+ Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockIfExistsAsync').throws(
new Error('JSON RPC error'),
),
];
diff --git a/packages/contract-wrappers/test/transaction_encoder_test.ts b/packages/contract-wrappers/test/transaction_encoder_test.ts
new file mode 100644
index 000000000..a397e43a8
--- /dev/null
+++ b/packages/contract-wrappers/test/transaction_encoder_test.ts
@@ -0,0 +1,211 @@
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { FillScenarios } from '@0xproject/fill-scenarios';
+import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils, signatureUtils } from '@0xproject/order-utils';
+import { SignedOrder, SignerType } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+import 'mocha';
+
+import { ContractWrappers } from '../src';
+import { TransactionEncoder } from '../src/utils/transaction_encoder';
+
+import { constants } from './utils/constants';
+import { tokenUtils } from './utils/token_utils';
+import { provider, web3Wrapper } from './utils/web3_wrapper';
+
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+describe('TransactionEncoder', () => {
+ let contractWrappers: ContractWrappers;
+ let userAddresses: string[];
+ let fillScenarios: FillScenarios;
+ let exchangeContractAddress: string;
+ let makerTokenAddress: string;
+ let takerTokenAddress: string;
+ let coinbase: string;
+ let makerAddress: string;
+ let senderAddress: string;
+ let takerAddress: string;
+ let makerAssetData: string;
+ let takerAssetData: string;
+ let txHash: string;
+ const fillableAmount = new BigNumber(5);
+ const takerTokenFillAmount = new BigNumber(5);
+ let signedOrder: SignedOrder;
+ const config = {
+ networkId: constants.TESTRPC_NETWORK_ID,
+ blockPollingIntervalMs: 0,
+ };
+ before(async () => {
+ await blockchainLifecycle.startAsync();
+ contractWrappers = new ContractWrappers(provider, config);
+ exchangeContractAddress = contractWrappers.exchange.getContractAddress();
+ userAddresses = await web3Wrapper.getAvailableAddressesAsync();
+ const zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
+ fillScenarios = new FillScenarios(
+ provider,
+ userAddresses,
+ zrxTokenAddress,
+ exchangeContractAddress,
+ contractWrappers.erc20Proxy.getContractAddress(),
+ contractWrappers.erc721Proxy.getContractAddress(),
+ );
+ [coinbase, makerAddress, takerAddress, senderAddress] = userAddresses;
+ [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
+ [makerAssetData, takerAssetData] = [
+ assetDataUtils.encodeERC20AssetData(makerTokenAddress),
+ assetDataUtils.encodeERC20AssetData(takerTokenAddress),
+ ];
+ signedOrder = await fillScenarios.createFillableSignedOrderAsync(
+ makerAssetData,
+ takerAssetData,
+ makerAddress,
+ takerAddress,
+ fillableAmount,
+ );
+ });
+ after(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ describe('encode and executeTransaction', () => {
+ const executeTransactionOrThrowAsync = async (
+ encoder: TransactionEncoder,
+ data: string,
+ signerAddress: string = takerAddress,
+ ): Promise<void> => {
+ const salt = generatePseudoRandomSalt();
+ const encodedTransaction = encoder.getTransactionHex(data, salt, signerAddress);
+ const signature = await signatureUtils.ecSignOrderHashAsync(
+ provider,
+ encodedTransaction,
+ signerAddress,
+ SignerType.Default,
+ );
+ txHash = await contractWrappers.exchange.executeTransactionAsync(
+ salt,
+ signerAddress,
+ data,
+ signature,
+ senderAddress,
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
+ };
+ describe('#fillOrderTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.fillOrderTx(signedOrder, takerTokenFillAmount);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#fillOrderNoThrowTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.fillOrderNoThrowTx(signedOrder, takerTokenFillAmount);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#fillOrKillOrderTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.fillOrKillOrderTx(signedOrder, takerTokenFillAmount);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#marketSellOrdersTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.marketSellOrdersTx([signedOrder], takerTokenFillAmount);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#marketSellOrdersNoThrowTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.marketSellOrdersNoThrowTx([signedOrder], takerTokenFillAmount);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#marketBuyOrdersTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.marketBuyOrdersTx([signedOrder], fillableAmount);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#marketBuyOrdersNoThrowTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.marketBuyOrdersNoThrowTx([signedOrder], fillableAmount);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#preSignTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
+ const signature = signedOrder.signature;
+ const data = encoder.preSignTx(orderHash, makerAddress, signature);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#setSignatureValidatorApprovalTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const isApproved = true;
+ const data = encoder.setSignatureValidatorApprovalTx(senderAddress, isApproved);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#batchFillOrdersTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.batchFillOrdersTx([signedOrder], [takerTokenFillAmount]);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#batchFillOrKillOrdersTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.batchFillOrKillOrdersTx([signedOrder], [takerTokenFillAmount]);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#batchFillOrdersNoThrowTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.batchFillOrdersNoThrowTx([signedOrder], [takerTokenFillAmount]);
+ await executeTransactionOrThrowAsync(encoder, data);
+ });
+ });
+ describe('#batchCancelOrdersTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.batchCancelOrdersTx([signedOrder]);
+ const signerAddress = makerAddress;
+ await executeTransactionOrThrowAsync(encoder, data, signerAddress);
+ });
+ });
+ describe('#cancelOrderTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const data = encoder.cancelOrderTx(signedOrder);
+ const signerAddress = makerAddress;
+ await executeTransactionOrThrowAsync(encoder, data, signerAddress);
+ });
+ });
+ describe('#cancelOrdersUpToTx', () => {
+ it('should successfully execute the transaction', async () => {
+ const encoder = await contractWrappers.exchange.transactionEncoderAsync();
+ const targetEpoch = signedOrder.salt;
+ const data = encoder.cancelOrdersUpToTx(targetEpoch);
+ const signerAddress = makerAddress;
+ await executeTransactionOrThrowAsync(encoder, data, signerAddress);
+ });
+ });
+ });
+});
diff --git a/packages/contract-wrappers/test/utils/constants.ts b/packages/contract-wrappers/test/utils/constants.ts
index 60c3370a2..f38728b77 100644
--- a/packages/contract-wrappers/test/utils/constants.ts
+++ b/packages/contract-wrappers/test/utils/constants.ts
@@ -15,4 +15,5 @@ export const constants = {
DUMMY_TOKEN_TOTAL_SUPPLY: new BigNumber(10 ** 27), // tslint:disable-line:custom-no-magic-numbers
NUM_DUMMY_ERC20_TO_DEPLOY: 3,
NUM_DUMMY_ERC721_TO_DEPLOY: 1,
+ ZERO_AMOUNT: new BigNumber(0),
};
diff --git a/packages/contract-wrappers/tsconfig.json b/packages/contract-wrappers/tsconfig.json
index e35816553..2ee711adc 100644
--- a/packages/contract-wrappers/tsconfig.json
+++ b/packages/contract-wrappers/tsconfig.json
@@ -1,7 +1,8 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
- "outDir": "lib"
+ "outDir": "lib",
+ "rootDir": "."
},
"include": ["./src/**/*", "./test/**/*"]
}
diff --git a/packages/contract-wrappers/typedoc-tsconfig.json b/packages/contract-wrappers/typedoc-tsconfig.json
new file mode 100644
index 000000000..c9b0af1ae
--- /dev/null
+++ b/packages/contract-wrappers/typedoc-tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../typedoc-tsconfig",
+ "compilerOptions": {
+ "outDir": "lib"
+ },
+ "include": ["./src/**/*", "./test/**/*"]
+}