merge v2-prototype

This commit is contained in:
Fabio Berger
2018-07-19 17:48:06 +02:00
388 changed files with 117332 additions and 8410 deletions

View File

@@ -64,7 +64,8 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0xproject/0x.js
- run: yarn wsrun test:circleci 0x.js
- run: yarn wsrun test:circleci @0xproject/abi-gen
- run: yarn wsrun test:circleci @0xproject/assert
- run: yarn wsrun test:circleci @0xproject/base-contract
- run: yarn wsrun test:circleci @0xproject/connect
@@ -83,6 +84,10 @@ jobs:
key: coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/0x.js/coverage/lcov.info
- save_cache:
key: coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo/packages/abi-gen/coverage/lcov.info
- save_cache:
key: coverage-assert-{{ .Environment.CIRCLE_SHA1 }}
paths:
@@ -160,6 +165,9 @@ jobs:
- restore_cache:
keys:
- coverage-0xjs-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-abi-gen-{{ .Environment.CIRCLE_SHA1 }}
- restore_cache:
keys:
- coverage-assert-{{ .Environment.CIRCLE_SHA1 }}

View File

@@ -10,7 +10,7 @@ lib
/packages/migrations/src/1.0.0/contract_wrappers
/packages/migrations/src/2.0.0/contract_wrappers
/packages/migrations/src/2.0.0-beta-testnet/contract_wrappers
/packages/0x.js/test/artifacts
/packages/0x.js/src/artifacts
/packages/contracts/src/artifacts
/packages/metacoin/artifacts
/packages/contract-wrappers/test/artifacts

View File

@@ -8,11 +8,13 @@
## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
<!--- What types of changes does your code introduce? Uncomment all the bullets that apply: -->
* [ ] Bug fix (non-breaking change which fixes an issue)
* [ ] New feature (non-breaking change which adds functionality)
* [ ] Breaking change (fix or feature that would cause existing functionality to change)
<!-- * Bug fix (non-breaking change which fixes an issue) -->
<!-- * New feature (non-breaking change which adds functionality) -->
<!-- * Breaking change (fix or feature that would cause existing functionality to change) -->
## Checklist:

View File

@@ -1,5 +1,5 @@
{
"lerna": "2.5.1",
"lerna": "3.0.0-beta.14",
"packages": ["packages/*"],
"commands": {
"publish": {

View File

@@ -31,7 +31,7 @@
"stage_docs": "wsrun docs:stage $PKG --fast-exit --parallel --exclude-missing",
"lint": "wsrun lint $PKG --fast-exit --parallel --exclude-missing",
"comment:postinstall": "HACK: For some reason `yarn` is not setting up symlinks properly for order-utils. We temporarily set them manually. Remove this after V2 refactor is complete.",
"postinstall": "rm -rf `pwd`/packages/order-utils/node_modules/@0xproject; mkdir `pwd`/packages/order-utils/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-utils/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/assert `pwd`/packages/order-utils/node_modules/@0xproject/assert; ln -s `pwd`/packages/types `pwd`/packages/order-utils/node_modules/@0xproject/types; rm -f `pwd`/packages/contracts/node_modules/@0xproject/types; ln -s `pwd`/packages/types `pwd`/packages/contracts/node_modules/@0xproject/types; rm -rf `pwd`/packages/fill-scenarios/node_modules/@0xproject; mkdir -p `pwd`/packages/fill-scenarios/node_modules/@0xproject; ln -s `pwd`/packages/types `pwd`/packages/fill-scenarios/node_modules/@0xproject/types; ln -s `pwd`/packages/json-schemas `pwd`/packages/fill-scenarios/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/fill-scenarios/node_modules/@0xproject/order-utils; rm -rf `pwd`/packages/contract-wrappers/node_modules/@0xproject; mkdir -p `pwd`/packages/contract-wrappers/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contract-wrappers/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/assert `pwd`/packages/contract-wrappers/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/contract-wrappers/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/types `pwd`/packages/contract-wrappers/node_modules/@0xproject/types; ln -s `pwd`/packages/fill-scenarios `pwd`/packages/contract-wrappers/node_modules/@0xproject/fill-scenarios; rm -rf `pwd`/packages/assert/node_modules/@0xproject; mkdir -p `pwd`/packages/assert/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/assert/node_modules/@0xproject/json-schemas"
"postinstall": "rm -rf `pwd`/packages/0x.js/node_modules/@0xproject; mkdir `pwd`/packages/0x.js/node_modules/@0xproject; ln -s `pwd`/packages/contract-wrappers `pwd`/packages/0x.js/node_modules/@0xproject/contract-wrappers; ln -s `pwd`/packages/order-utils `pwd`/packages/0x.js/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/types `pwd`/packages/0x.js/node_modules/@0xproject/types; rm -rf `pwd`/packages/order-utils/node_modules/@0xproject; mkdir `pwd`/packages/order-utils/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-utils/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/assert `pwd`/packages/order-utils/node_modules/@0xproject/assert; ln -s `pwd`/packages/types `pwd`/packages/order-utils/node_modules/@0xproject/types; rm -rf `pwd`/packages/fill-scenarios/node_modules/@0xproject; mkdir -p `pwd`/packages/fill-scenarios/node_modules/@0xproject; ln -s `pwd`/packages/types `pwd`/packages/fill-scenarios/node_modules/@0xproject/types; ln -s `pwd`/packages/json-schemas `pwd`/packages/fill-scenarios/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/fill-scenarios/node_modules/@0xproject/order-utils; rm -rf `pwd`/packages/contract-wrappers/node_modules/@0xproject; mkdir -p `pwd`/packages/contract-wrappers/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contract-wrappers/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/assert `pwd`/packages/contract-wrappers/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/contract-wrappers/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/types `pwd`/packages/contract-wrappers/node_modules/@0xproject/types; ln -s `pwd`/packages/fill-scenarios `pwd`/packages/contract-wrappers/node_modules/@0xproject/fill-scenarios; rm -rf `pwd`/packages/assert/node_modules/@0xproject; mkdir -p `pwd`/packages/assert/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/assert/node_modules/@0xproject/json-schemas; rm -rf `pwd`/packages/order-watcher/node_modules/@0xproject; mkdir `pwd`/packages/order-watcher/node_modules/@0xproject; ln -s `pwd`/packages/assert `pwd`/packages/order-watcher/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-watcher/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/order-watcher/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/types `pwd`/packages/order-watcher/node_modules/@0xproject/types; ln -s `pwd`/packages/contract-wrappers `pwd`/packages/order-watcher/node_modules/@0xproject/contract-wrappers; rm -rf `pwd`/packages/contracts/node_modules/@0xproject; mkdir `pwd`/packages/contracts/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contracts/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/types `pwd`/packages/contracts/node_modules/@0xproject/types; rm -rf `pwd`/packages/migrations/node_modules/@0xproject; mkdir `pwd`/packages/migrations/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/migrations/node_modules/@0xproject/order-utils"
},
"config": {
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
@@ -41,7 +41,7 @@
"coveralls": "^3.0.0",
"ganache-cli": "6.1.3",
"lcov-result-merger": "^3.0.0",
"lerna": "^2.5.1",
"lerna": "3.0.0-beta.14",
"npm-run-all": "^4.1.2",
"prettier": "^1.11.1",
"wsrun": "^2.2.0",

View File

@@ -1,4 +1,57 @@
[
{
"version": "1.0.0",
"changes": [
{
"note": "Remove tokenRegistry wrapper",
"pr": 863
},
{
"note": "Rename zeroEx.token to zeroEx.erc20Token, and add zeroEx.erc721Token",
"pr": 863
},
{
"note": "Rename zeroEx.proxy to zeroEx.erc20Proxy and add zeroEx.erc721Proxy",
"pr": 863
},
{
"note":
"Refactored ZeroEx.isValidSignature to zeroEx.isValidSignatureAsync. It is now async so that it can verify contract-dependent signature types",
"pr": 863
},
{
"note":
"Refactored signOrderHashAsync to ecSignOrderHashAsync. There are now many non-ECSignature ways to sign orders too.",
"pr": 863
},
{
"note":
"Removed createOrderWatcherAsync method. Will be added back once OrderWatcher is refactored for V2",
"pr": 863
},
{
"note": "0x.js exports renamed contract events and event arg types",
"pr": 863
},
{
"note": "Remove stateLayer config from OrderWatcher. It now always operates on the latest block",
"pr": 875
},
{
"note": "Export ZeroEx.assetData with methods to decode/encode assetData fields found in 0x orders",
"pr": 884
}
]
},
{
"timestamp": 1531919263,
"version": "0.38.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.38.5",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.38.6 - _July 18, 2018_
* Dependencies updated
## v0.38.5 - _July 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "0x.js",
"version": "0.38.5",
"version": "0.38.6",
"engines": {
"node": ">=6.12"
},
@@ -18,9 +18,10 @@
"watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && yarn build:all && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"build:all": "run-p build:umd:prod build:commonjs; exit 0;",
"pre_build": "run-s generate_contract_wrappers copy_artifacts",
"copy_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
"pre_build": "run-s update_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/artifacts",
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json src/artifacts; done;",
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(ZRXToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
"lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
"test:circleci": "run-s test:coverage",
"test": "yarn run_mocha",
@@ -29,7 +30,7 @@
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"clean": "shx rm -rf _bundles lib test_temp scripts src/generated_contract_wrappers",
"build:umd:prod": "NODE_ENV=production webpack",
"build:commonjs": "tsc && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"build:commonjs": "tsc && yarn copy_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "node scripts/stage_docs.js",
@@ -37,7 +38,7 @@
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
},
"config": {
"compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry",
"contracts": "ZRXToken",
"postpublish": {
"assets": [
"packages/0x.js/_bundles/index.js",
@@ -69,12 +70,11 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@0xproject/abi-gen": "^0.3.3",
"@0xproject/dev-utils": "^0.4.5",
"@0xproject/migrations": "^0.0.9",
"@0xproject/abi-gen": "^0.3.4",
"@0xproject/dev-utils": "^0.4.6",
"@0xproject/migrations": "^0.0.10",
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/tslint-config": "^0.4.21",
"@0xproject/sol-compiler": "^0.5.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/node": "^8.0.53",
@@ -94,22 +94,23 @@
"shx": "^0.2.2",
"sinon": "^4.0.0",
"source-map-support": "^0.5.0",
"tslint": "5.8.0",
"tslint": "5.11.0",
"typedoc": "0xProject/typedoc",
"typescript": "2.7.1",
"webpack": "^3.1.0"
},
"dependencies": {
"@0xproject/assert": "^0.2.13",
"@0xproject/base-contract": "^0.3.5",
"@0xproject/contract-wrappers": "^0.0.5",
"@0xproject/order-utils": "^0.0.8",
"@0xproject/order-watcher": "^0.0.7",
"@0xproject/sol-compiler": "^0.5.3",
"@0xproject/types": "^0.8.2",
"@0xproject/typescript-typings": "^0.4.2",
"@0xproject/utils": "^0.7.2",
"@0xproject/web3-wrapper": "^0.7.2",
"@0xproject/assert": "^0.2.14",
"@0xproject/base-contract": "^0.3.6",
"@0xproject/contract-wrappers": "^0.1.1",
"@0xproject/order-utils": "^1.0.0",
"@0xproject/sol-compiler": "^0.5.4",
"@0xproject/subproviders": "^0.10.6",
"@0xproject/types": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"@0xproject/web3-wrapper": "^0.7.3",
"ethereum-types": "^0.0.2",
"ethers": "3.0.22",
"lodash": "^4.17.4"
},

View File

@@ -2,23 +2,28 @@ import { assert } from '@0xproject/assert';
import {
ContractWrappers,
ContractWrappersConfig,
ERC20ProxyWrapper,
ERC20TokenWrapper,
ERC721ProxyWrapper,
ERC721TokenWrapper,
EtherTokenWrapper,
ExchangeWrapper,
TokenRegistryWrapper,
TokenTransferProxyWrapper,
TokenWrapper,
} from '@0xproject/contract-wrappers';
import {
assetDataUtils,
ecSignOrderHashAsync,
generatePseudoRandomSalt,
getOrderHashHex,
isValidOrderHash,
isValidSignature,
signOrderHashAsync,
isValidSignatureAsync,
MessagePrefixOpts,
orderHashUtils,
} from '@0xproject/order-utils';
import { OrderWatcher, OrderWatcherConfig } from '@0xproject/order-watcher';
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
// HACK: Since we export assetDataUtils from ZeroEx and it has AssetProxyId, ERC20AssetData and ERC721AssetData
// in it's public interface, we need to import these types here.
// tslint:disable-next-line:no-unused-variable
import { AssetProxyId, ECSignature, ERC20AssetData, ERC721AssetData, Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { constants } from './utils/constants';
@@ -33,30 +38,38 @@ export class ZeroEx {
* this constant for your convenience.
*/
public static NULL_ADDRESS = constants.NULL_ADDRESS;
/**
* A set of methods to easily decode/encode assetData fields found in 0x orders.
*/
public static assetData = assetDataUtils;
/**
* An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract.
*/
public exchange: ExchangeWrapper;
/**
* An instance of the TokenRegistryWrapper class containing methods for interacting with the 0x
* TokenRegistry smart contract.
* An instance of the ERC20TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
*/
public tokenRegistry: TokenRegistryWrapper;
public erc20Token: ERC20TokenWrapper;
/**
* An instance of the TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
* An instance of the ERC721TokenWrapper class containing methods for interacting with any ERC721 token smart contract.
*/
public token: TokenWrapper;
public erc721Token: ERC721TokenWrapper;
/**
* An instance of the EtherTokenWrapper class containing methods for interacting with the
* wrapped ETH ERC20 token smart contract.
*/
public etherToken: EtherTokenWrapper;
/**
* An instance of the TokenTransferProxyWrapper class containing methods for interacting with the
* tokenTransferProxy smart contract.
* An instance of the ERC20ProxyWrapper class containing methods for interacting with the
* ERC20 proxy smart contract.
*/
public proxy: TokenTransferProxyWrapper;
private _contractWrappers: ContractWrappers;
public erc20Proxy: ERC20ProxyWrapper;
/**
* An instance of the ERC721ProxyWrapper class containing methods for interacting with the
* ERC721 proxy smart contract.
*/
public erc721Proxy: ERC721ProxyWrapper;
private readonly _contractWrappers: ContractWrappers;
/**
* Generates a pseudo-random 256-bit salt.
* The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
@@ -66,24 +79,13 @@ export class ZeroEx {
public static generatePseudoRandomSalt(): BigNumber {
return generatePseudoRandomSalt();
}
/**
* Verifies that the elliptic curve signature `signature` was generated
* by signing `data` with the private key corresponding to the `signerAddress` address.
* @param data The hex encoded data signed by the supplied signature.
* @param signature An object containing the elliptic curve signature parameters.
* @param signerAddress The hex encoded address that signed the data, producing the supplied signature.
* @return Whether the signature is valid for the supplied signerAddress and data.
*/
public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean {
return isValidSignature(data, signature, signerAddress);
}
/**
* Computes the orderHash for a supplied order.
* @param order An object that conforms to the Order or SignedOrder interface definitions.
* @return The resulting orderHash from hashing the supplied order.
*/
public static getOrderHashHex(order: Order | SignedOrder): string {
return getOrderHashHex(order);
return orderHashUtils.getOrderHashHex(order);
}
/**
* Checks if the supplied hex encoded order hash is valid.
@@ -93,7 +95,7 @@ export class ZeroEx {
* @return Whether the supplied orderHash has the expected format.
*/
public static isValidOrderHash(orderHash: string): boolean {
return isValidOrderHash(orderHash);
return orderHashUtils.isValidOrderHash(orderHash);
}
/**
* A unit amount is defined as the amount of a token above the specified decimal places (integer part).
@@ -134,12 +136,29 @@ export class ZeroEx {
assert.isWeb3Provider('provider', provider);
this._contractWrappers = new ContractWrappers(provider, config);
this.proxy = this._contractWrappers.proxy;
this.token = this._contractWrappers.token;
this.erc20Proxy = this._contractWrappers.erc20Proxy;
this.erc721Proxy = this._contractWrappers.erc721Proxy;
this.erc20Token = this._contractWrappers.erc20Token;
this.erc721Token = this._contractWrappers.erc721Token;
this.exchange = this._contractWrappers.exchange;
this.tokenRegistry = this._contractWrappers.tokenRegistry;
this.etherToken = this._contractWrappers.etherToken;
}
/**
* Verifies that the provided signature is valid according to the 0x Protocol smart contracts
* @param data The hex encoded data signed by the supplied signature.
* @param signature The hex encoded signature.
* @param signerAddress The hex encoded address that signed the data, producing the supplied signature.
* @return Whether the signature is valid for the supplied signerAddress and data.
*/
public async isValidSignatureAsync(data: string, signature: string, signerAddress: string): Promise<boolean> {
const isValid = await isValidSignatureAsync(
this._contractWrappers.getProvider(),
data,
signature,
signerAddress,
);
return isValid;
}
/**
* Sets a new web3 provider for 0x.js. Updating the provider will stop all
* subscriptions so you will need to re-subscribe to all events relevant to your app after this call.
@@ -172,23 +191,21 @@ export class ZeroEx {
* @param orderHash Hex encoded orderHash to sign.
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
* must be available via the Provider supplied to 0x.js.
* @param shouldAddPersonalMessagePrefix Some signers add the personal message prefix `\x19Ethereum Signed Message`
* themselves (e.g Parity Signer, Ledger, TestRPC) and others expect it to already be done by the client
* (e.g Metamask). Depending on which signer this request is going to, decide on whether to add the prefix
* before sending the request.
* @param MessagePrefixOpts Options regarding the desired prefix and whether to add it before calling `eth_sign`
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
*/
public async signOrderHashAsync(
public async ecSignOrderHashAsync(
orderHash: string,
signerAddress: string,
shouldAddPersonalMessagePrefix: boolean,
messagePrefixOpts: MessagePrefixOpts,
): Promise<ECSignature> {
return signOrderHashAsync(
const signature = await ecSignOrderHashAsync(
this._contractWrappers.getProvider(),
orderHash,
signerAddress,
shouldAddPersonalMessagePrefix,
messagePrefixOpts,
);
return signature;
}
/**
* Waits for a transaction to be mined and returns the transaction receipt.
@@ -211,18 +228,4 @@ export class ZeroEx {
);
return transactionReceiptWithDecodedLogs;
}
/**
* Instantiates and returns a new OrderWatcher instance.
* Defaults to watching the pending state.
* @param config The configuration object. Look up the type for the description.
* @return An instance of the 0x.js OrderWatcher class.
*/
public async createOrderWatcherAsync(config?: OrderWatcherConfig): Promise<OrderWatcher> {
// Hack: Get Web3Wrapper from ContractWrappers
const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
const networkId = await web3Wrapper.getNetworkIdAsync();
const provider = this._contractWrappers.getProvider();
const orderWatcher = new OrderWatcher(provider, networkId, config);
return orderWatcher;
}
}

View File

@@ -0,0 +1,7 @@
import { ContractArtifact } from '@0xproject/sol-compiler';
import * as ZRXToken from './artifacts/ZRXToken.json';
export const artifacts = {
ZRXToken: (ZRXToken as any) as ContractArtifact,
};

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

@@ -1,610 +0,0 @@
{
"contract_name": "Exchange",
"abi": [
{
"constant": true,
"inputs": [
{
"name": "numerator",
"type": "uint256"
},
{
"name": "denominator",
"type": "uint256"
},
{
"name": "target",
"type": "uint256"
}
],
"name": "isRoundingError",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "bytes32"
}
],
"name": "filled",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "bytes32"
}
],
"name": "cancelled",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "fillOrdersUpTo",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "cancelTakerTokenAmount",
"type": "uint256"
}
],
"name": "cancelOrder",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "ZRX_TOKEN_CONTRACT",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmounts",
"type": "uint256[]"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "batchFillOrKillOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "fillOrKillOrder",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "orderHash",
"type": "bytes32"
}
],
"name": "getUnavailableTakerTokenAmount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "signer",
"type": "address"
},
{
"name": "hash",
"type": "bytes32"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "isValidSignature",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "numerator",
"type": "uint256"
},
{
"name": "denominator",
"type": "uint256"
},
{
"name": "target",
"type": "uint256"
}
],
"name": "getPartialAmount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "TOKEN_TRANSFER_PROXY_CONTRACT",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmounts",
"type": "uint256[]"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "batchFillOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "cancelTakerTokenAmounts",
"type": "uint256[]"
}
],
"name": "batchCancelOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "fillOrder",
"outputs": [
{
"name": "filledTakerTokenAmount",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
}
],
"name": "getOrderHash",
"outputs": [
{
"name": "",
"type": "bytes32"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "EXTERNAL_QUERY_GAS_LIMIT",
"outputs": [
{
"name": "",
"type": "uint16"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "VERSION",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"inputs": [
{
"name": "_zrxToken",
"type": "address"
},
{
"name": "_tokenTransferProxy",
"type": "address"
}
],
"payable": false,
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "maker",
"type": "address"
},
{
"indexed": false,
"name": "taker",
"type": "address"
},
{
"indexed": true,
"name": "feeRecipient",
"type": "address"
},
{
"indexed": false,
"name": "makerToken",
"type": "address"
},
{
"indexed": false,
"name": "takerToken",
"type": "address"
},
{
"indexed": false,
"name": "filledMakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "filledTakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "paidMakerFee",
"type": "uint256"
},
{
"indexed": false,
"name": "paidTakerFee",
"type": "uint256"
},
{
"indexed": true,
"name": "tokens",
"type": "bytes32"
},
{
"indexed": false,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogFill",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "maker",
"type": "address"
},
{
"indexed": true,
"name": "feeRecipient",
"type": "address"
},
{
"indexed": false,
"name": "makerToken",
"type": "address"
},
{
"indexed": false,
"name": "takerToken",
"type": "address"
},
{
"indexed": false,
"name": "cancelledMakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "cancelledTakerTokenAmount",
"type": "uint256"
},
{
"indexed": true,
"name": "tokens",
"type": "bytes32"
},
{
"indexed": false,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogCancel",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "errorId",
"type": "uint8"
},
{
"indexed": true,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogError",
"type": "event"
}
],
"networks": {
"1": {
"address": "0x12459c951127e0c374ff9105dda097662a027093"
},
"3": {
"address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac"
},
"4": {
"address": "0x1d16ef40fac01cec8adac2ac49427b9384192c05"
},
"42": {
"address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
},
"50": {
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
}
}
}

View File

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

View File

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

View File

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

View File

@@ -1,20 +0,0 @@
{
"contract_name": "ZRX",
"networks": {
"1": {
"address": "0xe41d2489571d322189246dafa5ebde1f4699f498"
},
"3": {
"address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d"
},
"4": {
"address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8"
},
"42": {
"address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570"
},
"50": {
"address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"
}
}
}

View File

@@ -1,32 +1,38 @@
export { ZeroEx } from './0x';
export { MessagePrefixType, MessagePrefixOpts } from '@0xproject/order-utils';
export { Web3ProviderEngine, RPCSubprovider } from '@0xproject/subproviders';
export {
BlockParamLiteral,
FilterObject,
BlockParam,
ContractEventArg,
ExchangeContractErrs,
LogWithDecodedArgs,
Order,
Provider,
SignedOrder,
ECSignature,
OrderStateValid,
OrderStateInvalid,
OrderState,
Token,
TransactionReceipt,
TransactionReceiptWithDecodedLogs,
ERC20AssetData,
ERC721AssetData,
AssetProxyId,
} from '@0xproject/types';
export { OrderWatcherConfig } from '@0xproject/order-watcher';
export {
BlockParamLiteral,
FilterObject,
BlockParam,
LogWithDecodedArgs,
ContractEventArg,
Provider,
TransactionReceipt,
TransactionReceiptWithDecodedLogs,
} from 'ethereum-types';
export {
EventCallback,
ContractEvent,
IndexedFilterValues,
BlockRange,
OrderCancellationRequest,
OrderFillRequest,
ContractEventArgs,
MethodOpts,
@@ -36,18 +42,25 @@ export {
DecodedLogEvent,
OnOrderStateChangeCallback,
ContractWrappersError,
EtherTokenContractEventArgs,
WithdrawalContractEventArgs,
DepositContractEventArgs,
EtherTokenEvents,
TransferContractEventArgs,
ApprovalContractEventArgs,
TokenContractEventArgs,
TokenEvents,
LogErrorContractEventArgs,
LogCancelContractEventArgs,
LogFillContractEventArgs,
ExchangeContractEventArgs,
ExchangeEvents,
WETH9Events,
WETH9WithdrawalEventArgs,
WETH9ApprovalEventArgs,
WETH9EventArgs,
WETH9DepositEventArgs,
WETH9TransferEventArgs,
ERC20TokenTransferEventArgs,
ERC20TokenApprovalEventArgs,
ERC20TokenEvents,
ERC20TokenEventArgs,
ERC721TokenApprovalEventArgs,
ERC721TokenApprovalForAllEventArgs,
ERC721TokenTransferEventArgs,
ERC721TokenEvents,
ExchangeCancelUpToEventArgs,
ExchangeAssetProxyRegisteredEventArgs,
ExchangeFillEventArgs,
ExchangeCancelEventArgs,
ExchangeEventArgs,
ContractWrappersConfig,
OrderInfo,
} from '@0xproject/contract-wrappers';

View File

@@ -8,8 +8,8 @@ export const zeroExPrivateNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {
@@ -29,7 +29,7 @@ export const zeroExPrivateNetworkConfigSchema = {
'networkId',
'zrxContractAddress',
'exchangeContractAddress',
'tokenRegistryContractAddress',
'tokenTransferProxyContractAddress',
'erc20ProxyContractAddress',
'erc721ProxyContractAddress',
],
};

View File

@@ -22,8 +22,8 @@ export const zeroExPublicNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {

View File

@@ -2,14 +2,13 @@ import { ContractWrappers } from '@0xproject/contract-wrappers';
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
import 'mocha';
import { ApprovalContractEventArgs, LogWithDecodedArgs, TokenEvents, ZeroEx } from '../src';
import { ERC20TokenApprovalEventArgs, ERC20TokenEvents, LogWithDecodedArgs, ZeroEx } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { TokenUtils } from './utils/token_utils';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
@@ -28,9 +27,7 @@ describe('ZeroEx library', () => {
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
// Instantiate the contract instances with the current provider
await (zeroEx.exchange as any)._getExchangeContractAsync();
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
// Add property to newProvider so that we can differentiate it from old provider
(provider as any).zeroExTestId = 1;
@@ -38,52 +35,43 @@ describe('ZeroEx library', () => {
// Check that contractInstances with old provider are removed after provider update
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined();
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
// Check that all nested zeroExContract/web3Wrapper instances return the updated provider
const nestedWeb3WrapperProvider = ((zeroEx as any)._contractWrappers as ContractWrappers).getProvider();
expect((nestedWeb3WrapperProvider as any).zeroExTestId).to.be.a('number');
const exchangeWeb3WrapperProvider = (zeroEx.exchange as any)._web3Wrapper.getProvider();
expect(exchangeWeb3WrapperProvider.zeroExTestId).to.be.a('number');
const tokenRegistryWeb3WrapperProvider = (zeroEx.tokenRegistry as any)._web3Wrapper.getProvider();
expect(tokenRegistryWeb3WrapperProvider.zeroExTestId).to.be.a('number');
});
});
describe('#isValidSignature', () => {
// The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes
// the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size.
const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const signature = {
v: 27,
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
};
const ethSignSignature =
'0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
it("should return false if the data doesn't pertain to the signature & address", async () => {
return expect(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address),
).to.become(false);
return expect((zeroEx.exchange as any).isValidSignatureAsync('0x0', address, ethSignSignature)).to.become(
false,
);
});
it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
return expect(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(
dataHex,
signature,
validUnrelatedAddress,
),
(zeroEx.exchange as any).isValidSignatureAsync(dataHex, validUnrelatedAddress, ethSignSignature),
).to.become(false);
});
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
const wrongSignature = _.assign({}, signature, { v: 28 });
return expect(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address),
).to.become(false);
const signatureArray = ethSignSignature.split('');
// tslint:disable-next-line:custom-no-magic-numbers
signatureArray[5] = 'C'; // V = 28, instead of 27
const wrongSignature = signatureArray.join('');
return expect((zeroEx.exchange as any).isValidSignatureAsync(dataHex, address, wrongSignature)).to.become(
false,
);
});
it('should return true if the signature does pertain to the dataHex & address', async () => {
return expect(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address),
).to.become(true);
return expect((zeroEx.exchange as any).isValidSignatureAsync(dataHex, address, ethSignSignature)).to.become(
true,
);
});
});
describe('#toUnitAmount', () => {
@@ -128,18 +116,16 @@ describe('ZeroEx library', () => {
it('returns transaction receipt with decoded logs', async () => {
const availableAddresses = await zeroEx.getAvailableAddressesAsync();
const coinbase = availableAddresses[0];
const tokens = await zeroEx.tokenRegistry.getTokensAsync();
const tokenUtils = new TokenUtils(tokens);
const zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
const proxyAddress = zeroEx.proxy.getContractAddress();
const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
const erc20ProxyAddress = zeroEx.erc20Proxy.getContractAddress();
const txHash = await zeroEx.erc20Token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
// tslint:disable-next-line:no-unnecessary-type-assertion
const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ApprovalContractEventArgs>;
expect(log.event).to.be.equal(TokenEvents.Approval);
const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ERC20TokenApprovalEventArgs>;
expect(log.event).to.be.equal(ERC20TokenEvents.Approval);
expect(log.args._owner).to.be.equal(coinbase);
expect(log.args._spender).to.be.equal(proxyAddress);
expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
expect(log.args._spender).to.be.equal(erc20ProxyAddress);
expect(log.args._value).to.be.bignumber.equal(zeroEx.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
});
});
describe('#config', () => {
@@ -151,15 +137,13 @@ describe('ZeroEx library', () => {
const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
});
it('allows to specify token registry token contract address', async () => {
it('allows to specify erc20Proxy contract address', async () => {
const zeroExConfig = {
tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS,
erc20ProxyContractAddress: ZeroEx.NULL_ADDRESS,
networkId: constants.TESTRPC_NETWORK_ID,
};
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal(
ZeroEx.NULL_ADDRESS,
);
const zeroExWithWrongERC20ProxyAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongERC20ProxyAddress.erc20Proxy.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
});
});
});

View File

@@ -1,48 +0,0 @@
import { web3Factory } from '@0xproject/dev-utils';
import { ZeroEx } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
chaiSetup.configure();
// Those tests are slower cause they're talking to a remote node
const TIMEOUT = 10000;
describe('Artifacts', () => {
describe('contracts are deployed on kovan', () => {
const kovanRpcUrl = constants.KOVAN_RPC_URL;
const provider = web3Factory.getRpcProvider({ rpcUrl: kovanRpcUrl });
const config = {
networkId: constants.KOVAN_NETWORK_ID,
};
const zeroEx = new ZeroEx(provider, config);
it('token registry contract is deployed', async () => {
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
}).timeout(TIMEOUT);
it('proxy contract is deployed', async () => {
await (zeroEx.proxy as any)._getTokenTransferProxyContractAsync();
}).timeout(TIMEOUT);
it('exchange contract is deployed', async () => {
await (zeroEx.exchange as any)._getExchangeContractAsync();
}).timeout(TIMEOUT);
});
describe('contracts are deployed on ropsten', () => {
const ropstenRpcUrl = constants.ROPSTEN_RPC_URL;
const provider = web3Factory.getRpcProvider({ rpcUrl: ropstenRpcUrl });
const config = {
networkId: constants.ROPSTEN_NETWORK_ID,
};
const zeroEx = new ZeroEx(provider, config);
it('token registry contract is deployed', async () => {
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
}).timeout(TIMEOUT);
it('proxy contract is deployed', async () => {
await (zeroEx.proxy as any)._getTokenTransferProxyContractAsync();
}).timeout(TIMEOUT);
it('exchange contract is deployed', async () => {
await (zeroEx.exchange as any)._getExchangeContractAsync();
}).timeout(TIMEOUT);
});
});

View File

@@ -1,5 +1,5 @@
import { devConstants } from '@0xproject/dev-utils';
import { runV1MigrationsAsync } from '@0xproject/migrations';
import { runV2MigrationsAsync } from '@0xproject/migrations';
import { provider } from './utils/web3_wrapper';
@@ -7,11 +7,11 @@ before('migrate contracts', async function(): Promise<void> {
// HACK: Since the migrations take longer then our global mocha timeout limit
// we manually increase it for this before hook.
const mochaTestTimeoutMs = 20000;
this.timeout(mochaTestTimeoutMs);
this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
const txDefaults = {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const artifactsDir = `../migrations/artifacts/1.0.0`;
await runV1MigrationsAsync(provider, artifactsDir, txDefaults);
const artifactsDir = `../migrations/artifacts/2.0.0`;
await runV2MigrationsAsync(provider, artifactsDir, txDefaults);
});

View File

@@ -1,34 +1,9 @@
import { Token } from '@0xproject/types';
import * as _ from 'lodash';
import { artifacts } from '../../src/artifacts';
import { InternalZeroExError } from '../../src/types';
import { constants } from './constants';
const PROTOCOL_TOKEN_SYMBOL = 'ZRX';
const WETH_TOKEN_SYMBOL = 'WETH';
export class TokenUtils {
private _tokens: Token[];
constructor(tokens: Token[]) {
this._tokens = tokens;
}
public getProtocolTokenOrThrow(): Token {
const zrxToken = _.find(this._tokens, { symbol: PROTOCOL_TOKEN_SYMBOL });
if (_.isUndefined(zrxToken)) {
throw new Error(InternalZeroExError.ZrxNotInTokenRegistry);
}
return zrxToken;
}
public getWethTokenOrThrow(): Token {
const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL });
if (_.isUndefined(wethToken)) {
throw new Error(InternalZeroExError.WethNotInTokenRegistry);
}
return wethToken;
}
public getDummyTokens(): Token[] {
const dummyTokens = _.filter(this._tokens, token => {
return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol);
});
return dummyTokens;
}
}
export const tokenUtils = {
getProtocolTokenAddress(): string {
return artifacts.ZRXToken.networks[constants.TESTRPC_NETWORK_ID].address;
},
};

View File

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

View File

@@ -9,6 +9,19 @@
{
"note": "Remove the output directory before writing to it",
"pr": 822
},
{
"note": "skip generation of wrappers that are already up to date",
"pr": 788
}
]
},
{
"timestamp": 1531919263,
"version": "0.3.4",
"changes": [
{
"note": "Dependencies updated"
}
]
},

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.3.4 - _July 18, 2018_
* Dependencies updated
## v0.3.3 - _July 9, 2018_
* Dependencies updated

View File

@@ -1,2 +1,2 @@
#!/usr/bin/env node
require('../lib/index.js')
require('../lib/src/index.js')

View File

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/abi-gen",
"version": "0.3.3",
"version": "0.3.4",
"engines": {
"node": ">=6.12"
},
@@ -12,6 +12,11 @@
"lint": "tslint --project .",
"clean": "shx rm -rf lib scripts",
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"test": "yarn run_mocha",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit",
"test:circleci": "yarn test:coverage",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"bin": {
@@ -27,15 +32,16 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/abi-gen/README.md",
"dependencies": {
"@0xproject/typescript-typings": "^0.4.2",
"@0xproject/utils": "^0.7.2",
"ethereum-types": "^0.0.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"chalk": "^2.3.0",
"ethereum-types": "^0.0.2",
"glob": "^7.1.2",
"handlebars": "^4.0.11",
"lodash": "^4.17.4",
"rimraf": "^2.6.2",
"mkdirp": "^0.5.1",
"sleep": "^5.1.1",
"tmp": "^0.0.33",
"to-snake-case": "^1.0.0",
"yargs": "^10.0.3"
},
@@ -43,16 +49,20 @@
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/tslint-config": "^0.4.21",
"@types/glob": "5.0.35",
"@types/rimraf": "^2.0.2",
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",
"@types/node": "^8.0.53",
"@types/sleep": "^0.0.7",
"@types/tmp": "^0.0.33",
"@types/yargs": "^10.0.0",
"chai": "^4.1.2",
"copyfiles": "^1.2.0",
"dirty-chai": "^2.0.1",
"make-promises-safe": "^1.1.0",
"mocha": "^5.2.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.8.0",
"tslint": "5.11.0",
"typescript": "2.7.1"
},
"publishConfig": {

View File

@@ -3,16 +3,12 @@
import { abiUtils, logUtils } from '@0xproject/utils';
import chalk from 'chalk';
import { AbiDefinition, ConstructorAbi, EventAbi, MethodAbi } from 'ethereum-types';
import * as fs from 'fs';
import { sync as globSync } from 'glob';
import * as Handlebars from 'handlebars';
import * as _ from 'lodash';
import * as mkdirp from 'mkdirp';
import * as rimraf from 'rimraf';
import * as yargs from 'yargs';
import toSnakeCase = require('to-snake-case');
import { ContextData, ContractsBackend, ParamKind } from './types';
import { utils } from './utils';
@@ -71,16 +67,6 @@ function registerPartials(partialsGlob: string): void {
}
}
function writeOutputFile(name: string, renderedTsCode: string): void {
let fileName = toSnakeCase(name);
// HACK: Snake case doesn't make a lot of sense for abbreviated names but we can't reliably detect abbreviations
// so we special-case the abbreviations we use.
fileName = fileName.replace('z_r_x', 'zrx').replace('e_r_c', 'erc');
const filePath = `${args.output}/${fileName}.ts`;
fs.writeFileSync(filePath, renderedTsCode);
logUtils.log(`Created: ${chalk.bold(filePath)}`);
}
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
if (args.partials) {
@@ -97,7 +83,6 @@ if (_.isEmpty(abiFileNames)) {
process.exit(1);
} else {
logUtils.log(`Found ${chalk.green(`${abiFileNames.length}`)} ${chalk.bold('ABI')} files`);
rimraf.sync(args.output);
mkdirp.sync(args.output);
}
for (const abiFileName of abiFileNames) {
@@ -120,6 +105,14 @@ for (const abiFileName of abiFileNames) {
process.exit(1);
}
const outFileName = utils.makeOutputFileName(namedContent.name);
const outFilePath = `${args.output}/${outFileName}.ts`;
if (utils.isOutputFileUpToDate(abiFileName, outFilePath)) {
logUtils.log(`Aready up to date: ${chalk.bold(outFilePath)}`);
continue;
}
let ctor = ABI.find((abi: AbiDefinition) => abi.type === ABI_TYPE_CONSTRUCTOR) as ConstructorAbi;
if (_.isUndefined(ctor)) {
ctor = utils.getEmptyConstructor(); // The constructor exists, but it's implicit in JSON's ABI definition
@@ -154,5 +147,6 @@ for (const abiFileName of abiFileNames) {
events: eventAbis,
};
const renderedTsCode = template(contextData);
writeOutputFile(namedContent.name, renderedTsCode);
utils.writeOutputFile(outFilePath, renderedTsCode);
logUtils.log(`Created: ${chalk.bold(outFilePath)}`);
}

View File

@@ -2,6 +2,7 @@ import { AbiType, ConstructorAbi, DataItem } from 'ethereum-types';
import * as fs from 'fs';
import * as _ from 'lodash';
import * as path from 'path';
import toSnakeCase = require('to-snake-case');
import { ContractsBackend, ParamKind } from './types';
@@ -92,4 +93,27 @@ export const utils = {
inputs: [],
};
},
makeOutputFileName(name: string): string {
let fileName = toSnakeCase(name);
// HACK: Snake case doesn't make a lot of sense for abbreviated names but we can't reliably detect abbreviations
// so we special-case the abbreviations we use.
fileName = fileName.replace('z_r_x', 'zrx').replace('e_r_c', 'erc');
return fileName;
},
writeOutputFile(filePath: string, renderedTsCode: string): void {
fs.writeFileSync(filePath, renderedTsCode);
},
isOutputFileUpToDate(abiFile: string, outputFile: string): boolean {
const abiFileModTimeMs = fs.statSync(abiFile).mtimeMs;
try {
const outFileModTimeMs = fs.statSync(outputFile).mtimeMs;
return outFileModTimeMs > abiFileModTimeMs;
} catch (err) {
if (err.code === 'ENOENT') {
return false;
} else {
throw err;
}
}
},
};

View File

@@ -0,0 +1,86 @@
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import * as fs from 'fs';
import 'mocha';
import * as tmp from 'tmp';
import { utils } from '../src/utils';
tmp.setGracefulCleanup(); // remove tmp files even if there are failures
chai.use(dirtyChai);
const expect = chai.expect;
describe('makeOutputFileName()', () => {
it('should handle Metacoin usage', () => {
expect(utils.makeOutputFileName('Metacoin')).to.equal('metacoin');
});
it('should handle special zrx_token case', () => {
expect(utils.makeOutputFileName('ZRXToken')).to.equal('zrx_token');
});
it('should handle special erc_token case', () => {
expect(utils.makeOutputFileName('ERC20Token')).to.equal('erc20_token');
});
});
describe('writeOutputFile()', () => {
let tempFilePath: string;
before(() => {
tempFilePath = tmp.fileSync(
{ discardDescriptor: true }, // close file (so we can update it)
).name;
});
it('should write content to output file', () => {
const content = 'hello world';
utils.writeOutputFile(tempFilePath, content);
expect(fs.readFileSync(tempFilePath).toString()).to.equal(content);
});
});
describe('isOutputFileUpToDate()', () => {
it('should throw ENOENT when there is no abi file', () => {
expect(utils.isOutputFileUpToDate.bind('nonexistant1', 'nonexistant2')).to.throw('ENOENT');
});
describe('when the abi input file exists', () => {
let abiFile: string;
before(() => {
abiFile = tmp.fileSync(
{ discardDescriptor: true }, // close file (set timestamp)
).name;
});
describe('without an existing output file', () => {
it('should return false', () => {
expect(utils.isOutputFileUpToDate(abiFile, 'nonexistant_file')).to.be.false();
});
});
describe('with an existing output file', () => {
let outputFile: string;
before(() => {
outputFile = tmp.fileSync(
{ discardDescriptor: true }, // close file (set timestamp)
).name;
const abiFileModTimeMs = fs.statSync(abiFile).mtimeMs;
const outfileModTimeMs = abiFileModTimeMs + 1;
fs.utimesSync(outputFile, outfileModTimeMs, outfileModTimeMs);
});
it('should return true when output file is newer than abi file', async () => {
expect(utils.isOutputFileUpToDate(abiFile, outputFile)).to.be.true();
});
it('should return false when output file exists but is older than abi file', () => {
const outFileModTimeMs = fs.statSync(outputFile).mtimeMs;
const abiFileModTimeMs = outFileModTimeMs + 1;
fs.utimesSync(abiFile, abiFileModTimeMs, abiFileModTimeMs);
expect(utils.isOutputFileUpToDate(abiFile, outputFile)).to.be.false();
});
});
});
});

View File

@@ -9,6 +9,15 @@
}
]
},
{
"timestamp": 1531919263,
"version": "0.2.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.2.13",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.2.14 - _July 18, 2018_
* Dependencies updated
## v0.2.13 - _July 9, 2018_
* Dependencies updated

View File

@@ -44,13 +44,13 @@
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
"tslint": "5.8.0",
"tslint": "5.11.0",
"typescript": "2.7.1"
},
"dependencies": {
"@0xproject/json-schemas": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.2",
"@0xproject/utils": "^0.7.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"lodash": "^4.17.4",
"valid-url": "^1.0.9"
},

View File

@@ -8,33 +8,33 @@ const HEX_REGEX = /^0x[0-9A-F]*$/i;
export const assert = {
isBigNumber(variableName: string, value: BigNumber): void {
const isBigNumber = _.isObject(value) && (value as any).isBigNumber;
this.assert(isBigNumber, this.typeAssertionMessage(variableName, 'BigNumber', value));
assert.assert(isBigNumber, assert.typeAssertionMessage(variableName, 'BigNumber', value));
},
isValidBaseUnitAmount(variableName: string, value: BigNumber): void {
assert.isBigNumber(variableName, value);
const isNegative = value.lessThan(0);
this.assert(!isNegative, `${variableName} cannot be a negative number, found value: ${value.toNumber()}`);
assert.assert(!isNegative, `${variableName} cannot be a negative number, found value: ${value.toNumber()}`);
const hasDecimals = value.decimalPlaces() !== 0;
this.assert(
assert.assert(
!hasDecimals,
`${variableName} should be in baseUnits (no decimals), found value: ${value.toNumber()}`,
);
},
isString(variableName: string, value: string): void {
this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value));
assert.assert(_.isString(value), assert.typeAssertionMessage(variableName, 'string', value));
},
isFunction(variableName: string, value: any): void {
this.assert(_.isFunction(value), this.typeAssertionMessage(variableName, 'function', value));
assert.assert(_.isFunction(value), assert.typeAssertionMessage(variableName, 'function', value));
},
isHexString(variableName: string, value: string): void {
this.assert(
assert.assert(
_.isString(value) && HEX_REGEX.test(value),
this.typeAssertionMessage(variableName, 'HexString', value),
assert.typeAssertionMessage(variableName, 'HexString', value),
);
},
isETHAddressHex(variableName: string, value: string): void {
this.assert(_.isString(value), this.typeAssertionMessage(variableName, 'string', value));
this.assert(addressUtils.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value));
assert.assert(_.isString(value), assert.typeAssertionMessage(variableName, 'string', value));
assert.assert(addressUtils.isAddress(value), assert.typeAssertionMessage(variableName, 'ETHAddressHex', value));
},
doesBelongToStringEnum(
variableName: string,
@@ -51,17 +51,17 @@ export const assert = {
);
},
hasAtMostOneUniqueValue(value: any[], errMsg: string): void {
this.assert(_.uniq(value).length <= 1, errMsg);
assert.assert(_.uniq(value).length <= 1, errMsg);
},
isNumber(variableName: string, value: number): void {
this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value));
assert.assert(_.isFinite(value), assert.typeAssertionMessage(variableName, 'number', value));
},
isBoolean(variableName: string, value: boolean): void {
this.assert(_.isBoolean(value), this.typeAssertionMessage(variableName, 'boolean', value));
assert.assert(_.isBoolean(value), assert.typeAssertionMessage(variableName, 'boolean', value));
},
isWeb3Provider(variableName: string, value: any): void {
const isWeb3Provider = _.isFunction(value.send) || _.isFunction(value.sendAsync);
this.assert(isWeb3Provider, this.typeAssertionMessage(variableName, 'Provider', value));
assert.assert(isWeb3Provider, assert.typeAssertionMessage(variableName, 'Provider', value));
},
doesConformToSchema(variableName: string, value: any, schema: Schema, subSchemas?: Schema[]): void {
if (_.isUndefined(value)) {
@@ -76,15 +76,15 @@ export const assert = {
const msg = `Expected ${variableName} to conform to schema ${schema.id}
Encountered: ${JSON.stringify(value, null, '\t')}
Validation errors: ${validationResult.errors.join(', ')}`;
this.assert(!hasValidationErrors, msg);
assert.assert(!hasValidationErrors, msg);
},
isWebUri(variableName: string, value: any): void {
const isValidUrl = !_.isUndefined(validUrl.isWebUri(value));
this.assert(isValidUrl, this.typeAssertionMessage(variableName, 'web uri', value));
assert.assert(isValidUrl, assert.typeAssertionMessage(variableName, 'web uri', value));
},
isUri(variableName: string, value: any): void {
const isValidUri = !_.isUndefined(validUrl.isUri(value));
this.assert(isValidUri, this.typeAssertionMessage(variableName, 'uri', value));
assert.assert(isValidUri, assert.typeAssertionMessage(variableName, 'uri', value));
},
assert(condition: boolean, message: string): void {
if (!condition) {

View File

@@ -49,7 +49,7 @@ describe('Assertions', () => {
});
describe('#isFunction', () => {
it('should not throw for valid input', () => {
const validInputs = [BigNumber, assert.isString];
const validInputs = [BigNumber, assert.isString.bind(assert)];
validInputs.forEach(input => expect(assert.isFunction.bind(assert, variableName, input)).to.not.throw());
});
it('should throw for invalid input', () => {

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1531919263,
"version": "0.3.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.3.5",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.3.6 - _July 18, 2018_
* Dependencies updated
## v0.3.5 - _July 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/base-contract",
"version": "0.3.5",
"version": "0.3.6",
"engines": {
"node": ">=6.12"
},
@@ -39,14 +39,14 @@
"mocha": "^4.0.1",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.8.0",
"tslint": "5.11.0",
"typescript": "2.7.1"
},
"dependencies": {
"ethereum-types": "^0.0.2",
"@0xproject/typescript-typings": "^0.4.2",
"@0xproject/utils": "^0.7.2",
"@0xproject/web3-wrapper": "^0.7.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"@0xproject/web3-wrapper": "^0.7.3",
"ethers": "3.0.22",
"lodash": "^4.17.4"
},

View File

@@ -72,15 +72,13 @@ export class BaseContract {
// 1. Optional param passed in to public method call
// 2. Global config passed in at library instantiation
// 3. Gas estimate calculation + safety margin
const removeUndefinedProperties = _.pickBy;
const txDataWithDefaults: TxData = {
const removeUndefinedProperties = _.pickBy.bind(_);
const txDataWithDefaults = {
...removeUndefinedProperties(txDefaults),
...removeUndefinedProperties(txData as any),
// HACK: TS can't prove that T is spreadable.
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
} as any;
...removeUndefinedProperties(txData),
};
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults as any);
txDataWithDefaults.gas = await estimateGasAsync(txDataWithDefaults);
}
return txDataWithDefaults;
}

View File

@@ -1,4 +1,22 @@
[
{
"version": "1.0.0",
"changes": [
{
"note":
"Remove WebSocketOrderbookChannel from the public interface and replace with orderbookChannelFactory"
}
]
},
{
"timestamp": 1531919263,
"version": "0.6.17",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1531149657,
"version": "0.6.16",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.6.17 - _July 18, 2018_
* Dependencies updated
## v0.6.16 - _July 9, 2018_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/connect",
"version": "0.6.16",
"version": "0.6.17",
"engines": {
"node": ">=6.12"
},
@@ -51,14 +51,14 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/connect/README.md",
"dependencies": {
"@0xproject/assert": "^0.2.13",
"@0xproject/json-schemas": "0.8.2",
"@0xproject/assert": "^0.2.14",
"@0xproject/json-schemas": "0.8.3",
"@0xproject/types": "^0.8.2",
"@0xproject/typescript-typings": "^0.4.2",
"@0xproject/utils": "^0.7.2",
"isomorphic-fetch": "^2.2.1",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"lodash": "^4.17.4",
"query-string": "^5.0.1",
"sinon": "^4.0.0",
"websocket": "^1.0.25"
},
"devDependencies": {
@@ -68,7 +68,8 @@
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/query-string": "^5.0.1",
"@types/websocket": "^0.0.34",
"@types/sinon": "^2.2.2",
"@types/websocket": "^0.0.39",
"async-child-process": "^1.1.1",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
@@ -80,7 +81,7 @@
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
"tslint": "5.8.0",
"tslint": "5.11.0",
"typedoc": "~0.8.0",
"typescript": "2.7.1"
},

View File

@@ -1,7 +1,7 @@
import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types';
import 'isomorphic-fetch';
import { fetchAsync } from '@0xproject/utils';
import * as _ from 'lodash';
import * as queryString from 'query-string';
@@ -38,7 +38,7 @@ const OPTS_TO_QUERY_FIELD_MAP = {
* that implement the standard relayer API v0
*/
export class HttpClient implements Client {
private _apiEndpointUrl: string;
private readonly _apiEndpointUrl: string;
/**
* Format parameters to be appended to http requests into query string form
*/
@@ -167,7 +167,7 @@ export class HttpClient implements Client {
const headers = new Headers({
'content-type': 'application/json',
});
const response = await fetch(url, {
const response = await fetchAsync(url, {
method: requestType,
body: JSON.stringify(payload),
headers,

View File

@@ -1,5 +1,5 @@
export { HttpClient } from './http_client';
export { WebSocketOrderbookChannel } from './ws_orderbook_channel';
export { orderbookChannelFactory } from './orderbook_channel_factory';
export {
Client,
FeesRequest,
@@ -14,7 +14,6 @@ export {
TokenPairsItem,
TokenPairsRequestOpts,
TokenTradeInfo,
WebSocketOrderbookChannelConfig,
} from './types';
export { Order, SignedOrder } from '@0xproject/types';

View File

@@ -0,0 +1,32 @@
import * as WebSocket from 'websocket';
import { OrderbookChannel, OrderbookChannelHandler } from './types';
import { assert } from './utils/assert';
import { WebSocketOrderbookChannel } from './ws_orderbook_channel';
export const orderbookChannelFactory = {
/**
* Instantiates a new WebSocketOrderbookChannel instance
* @param url The relayer API base WS url you would like to interact with
* @param handler An OrderbookChannelHandler instance that responds to various
* channel updates
* @return An OrderbookChannel Promise
*/
async createWebSocketOrderbookChannelAsync(
url: string,
handler: OrderbookChannelHandler,
): Promise<OrderbookChannel> {
assert.isUri('url', url);
assert.isOrderbookChannelHandler('handler', handler);
return new Promise<OrderbookChannel>((resolve, reject) => {
const client = new WebSocket.w3cwebsocket(url);
client.onopen = () => {
const orderbookChannel = new WebSocketOrderbookChannel(client, handler);
resolve(orderbookChannel);
};
client.onerror = err => {
reject(err);
};
});
},
};

View File

@@ -3,7 +3,6 @@ import { orderBookRequestSchema } from './orderbook_request_schema';
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
import { tokenPairsRequestOptsSchema } from './token_pairs_request_opts_schema';
import { webSocketOrderbookChannelConfigSchema } from './websocket_orderbook_channel_config_schema';
export const schemas = {
feesRequestSchema,
@@ -11,5 +10,4 @@ export const schemas = {
ordersRequestOptsSchema,
pagedRequestOptsSchema,
tokenPairsRequestOptsSchema,
webSocketOrderbookChannelConfigSchema,
};

View File

@@ -1,10 +0,0 @@
export const webSocketOrderbookChannelConfigSchema = {
id: '/WebSocketOrderbookChannelConfig',
type: 'object',
properties: {
heartbeatIntervalMs: {
type: 'number',
minimum: 10,
},
},
};

View File

@@ -11,17 +11,10 @@ export interface Client {
}
export interface OrderbookChannel {
subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler) => void;
subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
close: () => void;
}
/**
* heartbeatInterval: Interval in milliseconds that the orderbook channel should ping the underlying websocket. Default: 15000
*/
export interface WebSocketOrderbookChannelConfig {
heartbeatIntervalMs?: number;
}
/**
* baseTokenAddress: The address of token designated as the baseToken in the currency pair calculation of price
* quoteTokenAddress: The address of token designated as the quoteToken in the currency pair calculation of price
@@ -46,8 +39,8 @@ export interface OrderbookChannelHandler {
subscriptionOpts: OrderbookChannelSubscriptionOpts,
order: SignedOrder,
) => void;
onError: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts, err: Error) => void;
onClose: (channel: OrderbookChannel, subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
onError: (channel: OrderbookChannel, err: Error, subscriptionOpts?: OrderbookChannelSubscriptionOpts) => void;
onClose: (channel: OrderbookChannel) => void;
}
export type OrderbookChannelMessage =

View File

@@ -0,0 +1,26 @@
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
// tslint:disable-next-line:no-unused-variable
import { Schema, schemas } from '@0xproject/json-schemas';
// tslint:disable-next-line:no-unused-variable
import { ECSignature } from '@0xproject/types';
// tslint:disable-next-line:no-unused-variable
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
export const assert = {
...sharedAssert,
isOrderbookChannelSubscriptionOpts(variableName: string, subscriptionOpts: any): void {
sharedAssert.doesConformToSchema(
variableName,
subscriptionOpts,
schemas.relayerApiOrderbookChannelSubscribePayload,
);
},
isOrderbookChannelHandler(variableName: string, handler: any): void {
sharedAssert.isFunction(`${variableName}.onSnapshot`, _.get(handler, 'onSnapshot'));
sharedAssert.isFunction(`${variableName}.onUpdate`, _.get(handler, 'onUpdate'));
sharedAssert.isFunction(`${variableName}.onError`, _.get(handler, 'onError'));
sharedAssert.isFunction(`${variableName}.onClose`, _.get(handler, 'onClose'));
},
};

View File

@@ -8,10 +8,16 @@ import { relayerResponseJsonParsers } from './relayer_response_json_parsers';
export const orderbookChannelMessageParser = {
parse(utf8Data: string): OrderbookChannelMessage {
// parse the message
const messageObj = JSON.parse(utf8Data);
// ensure we have a type parameter to switch on
const type: string = _.get(messageObj, 'type');
assert.assert(!_.isUndefined(type), `Message is missing a type parameter: ${utf8Data}`);
assert.isString('type', type);
// ensure we have a request id for the resulting message
const requestId: number = _.get(messageObj, 'requestId');
assert.assert(!_.isUndefined(requestId), `Message is missing a requestId parameter: ${utf8Data}`);
assert.isNumber('requestId', requestId);
switch (type) {
case OrderbookChannelMessageTypes.Snapshot: {
assert.doesConformToSchema('message', messageObj, schemas.relayerApiOrderbookChannelSnapshotSchema);
@@ -28,7 +34,7 @@ export const orderbookChannelMessageParser = {
default: {
return {
type: OrderbookChannelMessageTypes.Unknown,
requestId: 0,
requestId,
payload: undefined,
};
}

View File

@@ -6,12 +6,12 @@ export const typeConverters = {
const bids = _.get(orderbook, 'bids', []);
const asks = _.get(orderbook, 'asks', []);
return {
bids: bids.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)),
asks: asks.map((order: any) => this.convertOrderStringFieldsToBigNumber(order)),
bids: bids.map((order: any) => typeConverters.convertOrderStringFieldsToBigNumber(order)),
asks: asks.map((order: any) => typeConverters.convertOrderStringFieldsToBigNumber(order)),
};
},
convertOrderStringFieldsToBigNumber(order: any): any {
return this.convertStringsFieldsToBigNumbers(order, [
return typeConverters.convertStringsFieldsToBigNumbers(order, [
'makerTokenAmount',
'takerTokenAmount',
'makerFee',

View File

@@ -1,166 +1,105 @@
import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import * as _ from 'lodash';
import * as WebSocket from 'websocket';
import { schemas as clientSchemas } from './schemas/schemas';
import {
OrderbookChannel,
OrderbookChannelHandler,
OrderbookChannelMessageTypes,
OrderbookChannelSubscriptionOpts,
WebsocketClientEventType,
WebsocketConnectionEventType,
WebSocketOrderbookChannelConfig,
} from './types';
import { assert } from './utils/assert';
import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser';
const DEFAULT_HEARTBEAT_INTERVAL_MS = 15000;
const MINIMUM_HEARTBEAT_INTERVAL_MS = 10;
/**
* This class includes all the functionality related to interacting with a websocket endpoint
* that implements the standard relayer API v0
*/
export class WebSocketOrderbookChannel implements OrderbookChannel {
private _apiEndpointUrl: string;
private _client: WebSocket.client;
private _connectionIfExists?: WebSocket.connection;
private _heartbeatTimerIfExists?: NodeJS.Timer;
private _subscriptionCounter = 0;
private _heartbeatIntervalMs: number;
private readonly _client: WebSocket.w3cwebsocket;
private readonly _handler: OrderbookChannelHandler;
private readonly _subscriptionOptsList: OrderbookChannelSubscriptionOpts[] = [];
/**
* Instantiates a new WebSocketOrderbookChannel instance
* @param url The relayer API base WS url you would like to interact with
* @param config The configuration object. Look up the type for the description.
* @param client A WebSocket client
* @param handler An OrderbookChannelHandler instance that responds to various
* channel updates
* @return An instance of WebSocketOrderbookChannel
*/
constructor(url: string, config?: WebSocketOrderbookChannelConfig) {
assert.isUri('url', url);
if (!_.isUndefined(config)) {
assert.doesConformToSchema('config', config, clientSchemas.webSocketOrderbookChannelConfigSchema);
}
this._apiEndpointUrl = url;
this._heartbeatIntervalMs =
_.isUndefined(config) || _.isUndefined(config.heartbeatIntervalMs)
? DEFAULT_HEARTBEAT_INTERVAL_MS
: config.heartbeatIntervalMs;
this._client = new WebSocket.client();
constructor(client: WebSocket.w3cwebsocket, handler: OrderbookChannelHandler) {
assert.isOrderbookChannelHandler('handler', handler);
// set private members
this._client = client;
this._handler = handler;
// attach client callbacks
this._client.onerror = err => {
this._handler.onError(this, err);
};
this._client.onclose = () => {
this._handler.onClose(this);
};
this._client.onmessage = message => {
this._handleWebSocketMessage(message);
};
}
/**
* Subscribe to orderbook snapshots and updates from the websocket
* @param subscriptionOpts An OrderbookChannelSubscriptionOpts instance describing which
* token pair to subscribe to
* @param handler An OrderbookChannelHandler instance that responds to various
* channel updates
*/
public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler): void {
assert.doesConformToSchema(
'subscriptionOpts',
subscriptionOpts,
schemas.relayerApiOrderbookChannelSubscribePayload,
);
assert.isFunction('handler.onSnapshot', _.get(handler, 'onSnapshot'));
assert.isFunction('handler.onUpdate', _.get(handler, 'onUpdate'));
assert.isFunction('handler.onError', _.get(handler, 'onError'));
assert.isFunction('handler.onClose', _.get(handler, 'onClose'));
this._subscriptionCounter += 1;
public subscribe(subscriptionOpts: OrderbookChannelSubscriptionOpts): void {
assert.isOrderbookChannelSubscriptionOpts('subscriptionOpts', subscriptionOpts);
assert.assert(this._client.readyState === WebSocket.w3cwebsocket.OPEN, 'WebSocket connection is closed');
this._subscriptionOptsList.push(subscriptionOpts);
// TODO: update requestId management to use UUIDs for v2
const subscribeMessage = {
type: 'subscribe',
channel: 'orderbook',
requestId: this._subscriptionCounter,
requestId: this._subscriptionOptsList.length - 1,
payload: subscriptionOpts,
};
this._getConnection((error, connection) => {
if (!_.isUndefined(error)) {
handler.onError(this, subscriptionOpts, error);
} else if (!_.isUndefined(connection) && connection.connected) {
connection.on(WebsocketConnectionEventType.Error, wsError => {
handler.onError(this, subscriptionOpts, wsError);
});
connection.on(WebsocketConnectionEventType.Close, (_code: number, _desc: string) => {
handler.onClose(this, subscriptionOpts);
});
connection.on(WebsocketConnectionEventType.Message, message => {
this._handleWebSocketMessage(subscribeMessage.requestId, subscriptionOpts, message, handler);
});
connection.sendUTF(JSON.stringify(subscribeMessage));
}
});
this._client.send(JSON.stringify(subscribeMessage));
}
/**
* Close the websocket and stop receiving updates
*/
public close(): void {
if (!_.isUndefined(this._connectionIfExists)) {
this._connectionIfExists.close();
}
if (!_.isUndefined(this._heartbeatTimerIfExists)) {
clearInterval(this._heartbeatTimerIfExists);
}
this._client.close();
}
private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void): void {
if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) {
callback(undefined, this._connectionIfExists);
} else {
this._client.on(WebsocketClientEventType.Connect, connection => {
this._connectionIfExists = connection;
if (this._heartbeatIntervalMs >= MINIMUM_HEARTBEAT_INTERVAL_MS) {
this._heartbeatTimerIfExists = setInterval(() => {
connection.ping('');
}, this._heartbeatIntervalMs);
} else {
callback(
new Error(
`Heartbeat interval is ${
this._heartbeatIntervalMs
}ms which is less than the required minimum of ${MINIMUM_HEARTBEAT_INTERVAL_MS}ms`,
),
undefined,
private _handleWebSocketMessage(message: any): void {
if (_.isUndefined(message.data)) {
this._handler.onError(this, new Error(`Message does not contain data. Url: ${this._client.url}`));
return;
}
try {
const data = message.data;
const parserResult = orderbookChannelMessageParser.parse(data);
const subscriptionOpts = this._subscriptionOptsList[parserResult.requestId];
if (_.isUndefined(subscriptionOpts)) {
this._handler.onError(
this,
new Error(`Message has unknown requestId. Url: ${this._client.url} Message: ${data}`),
);
return;
}
switch (parserResult.type) {
case OrderbookChannelMessageTypes.Snapshot: {
this._handler.onSnapshot(this, subscriptionOpts, parserResult.payload);
break;
}
case OrderbookChannelMessageTypes.Update: {
this._handler.onUpdate(this, subscriptionOpts, parserResult.payload);
break;
}
default: {
this._handler.onError(
this,
new Error(`Message has unknown type parameter. Url: ${this._client.url} Message: ${data}`),
subscriptionOpts,
);
}
callback(undefined, this._connectionIfExists);
});
this._client.on(WebsocketClientEventType.ConnectFailed, error => {
callback(error, undefined);
});
this._client.connect(this._apiEndpointUrl);
}
}
private _handleWebSocketMessage(
requestId: number,
subscriptionOpts: OrderbookChannelSubscriptionOpts,
message: WebSocket.IMessage,
handler: OrderbookChannelHandler,
): void {
if (!_.isUndefined(message.utf8Data)) {
try {
const utf8Data = message.utf8Data;
const parserResult = orderbookChannelMessageParser.parse(utf8Data);
if (parserResult.requestId === requestId) {
switch (parserResult.type) {
case OrderbookChannelMessageTypes.Snapshot: {
handler.onSnapshot(this, subscriptionOpts, parserResult.payload);
break;
}
case OrderbookChannelMessageTypes.Update: {
handler.onUpdate(this, subscriptionOpts, parserResult.payload);
break;
}
default: {
handler.onError(
this,
subscriptionOpts,
new Error(`Message has missing a type parameter: ${utf8Data}`),
);
}
}
}
} catch (error) {
handler.onError(this, subscriptionOpts, error);
}
} else {
handler.onError(this, subscriptionOpts, new Error(`Message does not contain utf8Data`));
} catch (error) {
this._handler.onError(this, error);
}
}
}

View File

@@ -0,0 +1,45 @@
import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import * as _ from 'lodash';
import 'mocha';
import { orderbookChannelFactory } from '../src/orderbook_channel_factory';
chai.config.includeStack = true;
chai.use(dirtyChai);
const expect = chai.expect;
const emptyOrderbookChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => {
_.noop();
},
onError: () => {
_.noop();
},
onClose: () => {
_.noop();
},
};
describe('orderbookChannelFactory', () => {
const websocketUrl = 'ws://localhost:8080';
describe('#createWebSocketOrderbookChannelAsync', () => {
it('throws when input is not a url', () => {
const badUrlInput = 54;
expect(
orderbookChannelFactory.createWebSocketOrderbookChannelAsync(
badUrlInput as any,
emptyOrderbookChannelHandler,
),
).to.be.rejected();
});
it('throws when handler has the incorrect members', () => {
const badHandlerInput = {};
expect(
orderbookChannelFactory.createWebSocketOrderbookChannelAsync(websocketUrl, badHandlerInput as any),
).to.be.rejected();
});
});
});

View File

@@ -2,60 +2,58 @@ import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import * as _ from 'lodash';
import 'mocha';
import * as Sinon from 'sinon';
import * as WebSocket from 'websocket';
import { WebSocketOrderbookChannel } from '../src/ws_orderbook_channel';
chai.config.includeStack = true;
chai.use(dirtyChai);
const expect = chai.expect;
const emptyOrderbookChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => {
_.noop();
},
onError: () => {
_.noop();
},
onClose: () => {
_.noop();
},
};
describe('WebSocketOrderbookChannel', () => {
const websocketUrl = 'ws://localhost:8080';
const orderbookChannel = new WebSocketOrderbookChannel(websocketUrl);
const openClient = new WebSocket.w3cwebsocket(websocketUrl);
Sinon.stub(openClient, 'readyState').get(() => WebSocket.w3cwebsocket.OPEN);
Sinon.stub(openClient, 'send').callsFake(_.noop.bind(_));
const openOrderbookChannel = new WebSocketOrderbookChannel(openClient, emptyOrderbookChannelHandler);
const subscriptionOpts = {
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
snapshot: true,
limit: 100,
};
const emptyOrderbookChannelHandler = {
onSnapshot: () => {
_.noop();
},
onUpdate: () => {
_.noop();
},
onError: () => {
_.noop();
},
onClose: () => {
_.noop();
},
};
describe('#subscribe', () => {
it('throws when subscriptionOpts does not conform to schema', () => {
const badSubscribeCall = orderbookChannel.subscribe.bind(
orderbookChannel,
{},
emptyOrderbookChannelHandler,
);
const badSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, {});
expect(badSubscribeCall).throws(
'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseTokenAddress", instance requires property "quoteTokenAddress"',
);
});
it('throws when handler has the incorrect members', () => {
const badSubscribeCall = orderbookChannel.subscribe.bind(orderbookChannel, subscriptionOpts, {});
expect(badSubscribeCall).throws(
'Expected handler.onSnapshot to be of type function, encountered: undefined',
);
});
it('does not throw when inputs are of correct types', () => {
const goodSubscribeCall = orderbookChannel.subscribe.bind(
orderbookChannel,
subscriptionOpts,
emptyOrderbookChannelHandler,
);
const goodSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, subscriptionOpts);
expect(goodSubscribeCall).to.not.throw();
});
it('throws when client is closed', () => {
const closedClient = new WebSocket.w3cwebsocket(websocketUrl);
Sinon.stub(closedClient, 'readyState').get(() => WebSocket.w3cwebsocket.CLOSED);
const closedOrderbookChannel = new WebSocketOrderbookChannel(closedClient, emptyOrderbookChannelHandler);
const badSubscribeCall = closedOrderbookChannel.subscribe.bind(closedOrderbookChannel, subscriptionOpts);
expect(badSubscribeCall).throws('WebSocket connection is closed');
});
});
});

View File

@@ -12,6 +12,15 @@
],
"timestamp": 1531149657
},
{
"timestamp": 1531919263,
"version": "0.1.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1529397769,
"version": "0.0.5",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v0.1.1 - _July 18, 2018_
* Dependencies updated
## v0.1.0 - _July 9, 2018_
* Update Blockstream dep. to V5.0 and no longer force unsubscribe on blockstream error (which are not recoverable)

View File

@@ -1,6 +1,6 @@
{
"name": "@0xproject/contract-wrappers",
"version": "0.1.0",
"version": "0.1.1",
"description": "Smart TS wrappers for 0x smart contracts",
"keywords": [
"0xproject",
@@ -43,12 +43,12 @@
"node": ">=6.0.0"
},
"devDependencies": {
"@0xproject/abi-gen": "^0.3.3",
"@0xproject/dev-utils": "^0.4.5",
"@0xproject/migrations": "^0.0.9",
"@0xproject/abi-gen": "^0.3.4",
"@0xproject/dev-utils": "^0.4.6",
"@0xproject/migrations": "^0.0.10",
"@0xproject/monorepo-scripts": "^0.2.2",
"@0xproject/sol-compiler": "^0.5.3",
"@0xproject/subproviders": "^0.10.5",
"@0xproject/sol-compiler": "^0.5.4",
"@0xproject/subproviders": "^0.10.6",
"@0xproject/tslint-config": "^0.4.21",
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
@@ -69,17 +69,17 @@
"shx": "^0.2.2",
"sinon": "^4.0.0",
"source-map-support": "^0.5.0",
"tslint": "5.8.0",
"typescript": "2.7.1",
"web3-provider-engine": "14.0.6"
"web3-provider-engine": "14.0.6",
"tslint": "5.11.0",
"typescript": "2.7.1"
},
"dependencies": {
"@0xproject/assert": "^0.3.0",
"@0xproject/base-contract": "^0.3.5",
"@0xproject/base-contract": "^0.3.6",
"@0xproject/order-utils": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.2",
"@0xproject/utils": "^0.7.2",
"@0xproject/web3-wrapper": "^0.7.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"@0xproject/web3-wrapper": "^0.7.3",
"@0xproject/fill-scenarios": "^1.0.0",
"@0xproject/json-schemas": "^1.0.0",
"@0xproject/types": "^1.0.0",

View File

@@ -1,5 +1,5 @@
import { ContractArtifact } from '@0xproject/sol-compiler';
import { AbiDecoder, intervalUtils } from '@0xproject/utils';
import { AbiDecoder, intervalUtils, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from 'ethereum-types';
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
@@ -41,6 +41,13 @@ export abstract class ContractWrapper {
};
private _onLogAddedSubscriptionToken: string | undefined;
private _onLogRemovedSubscriptionToken: string | undefined;
private static _onBlockAndLogStreamerError(isVerbose: boolean, err: Error): void {
// Since Blockstream errors are all recoverable, we simply log them if the verbose
// config is passed in.
if (isVerbose) {
logUtils.warn(err);
}
}
constructor(web3Wrapper: Web3Wrapper, networkId: number, blockPollingIntervalMs?: number) {
this._web3Wrapper = web3Wrapper;
this._networkId = networkId;
@@ -79,10 +86,11 @@ export abstract class ContractWrapper {
indexFilterValues: IndexedFilterValues,
abi: ContractAbi,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi);
if (_.isUndefined(this._blockAndLogStreamerIfExists)) {
this._startBlockAndLogStream();
this._startBlockAndLogStream(isVerbose);
}
const filterToken = filterUtils.generateUUID();
this._filters[filterToken] = filter;
@@ -151,21 +159,21 @@ export abstract class ContractWrapper {
}
});
}
private _startBlockAndLogStream(): void {
private _startBlockAndLogStream(isVerbose: boolean): void {
if (!_.isUndefined(this._blockAndLogStreamerIfExists)) {
throw new Error(ContractWrappersError.SubscriptionAlreadyPresent);
}
this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper),
this._web3Wrapper.getLogsAsync.bind(this._web3Wrapper),
this._onBlockAndLogStreamerError.bind(this),
ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose),
);
const catchAllLogFilter = {};
this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval(
this._reconcileBlockAsync.bind(this),
this._blockPollingIntervalMs,
this._onReconcileBlockError.bind(this),
ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose),
);
let isRemoved = false;
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
@@ -176,20 +184,10 @@ export abstract class ContractWrapper {
this._onLogStateChanged.bind(this, isRemoved),
);
}
private _onBlockAndLogStreamerError(err: Error): void {
// Propogate all Blockstream subscriber errors to all
// top-level subscriptions
const filterCallbacks = _.values(this._filterCallbacks);
_.each(filterCallbacks, filterCallback => {
filterCallback(err);
});
}
private _onReconcileBlockError(err: Error): void {
const filterTokens = _.keys(this._filterCallbacks);
_.each(filterTokens, filterToken => {
this._unsubscribe(filterToken, err);
});
}
// HACK: This should be a package-scoped method (which doesn't exist in TS)
// We don't want this method available in the public interface for all classes
// who inherit from ContractWrapper, and it is only used by the internal implementation
// of those higher classes.
// tslint:disable-next-line:no-unused-variable
private _setNetworkId(networkId: number): void {
this._networkId = networkId;

View File

@@ -347,6 +347,7 @@ export class ERC20TokenWrapper extends ContractWrapper {
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC20TokenEventArgs>(
@@ -354,6 +355,7 @@ export class ERC20TokenWrapper extends ContractWrapper {
eventName: ERC20TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
@@ -366,6 +368,7 @@ export class ERC20TokenWrapper extends ContractWrapper {
indexFilterValues,
artifacts.ERC20Token.compilerOutput.abi,
callback,
isVerbose,
);
return subscriptionToken;
}

View File

@@ -342,15 +342,17 @@ export class ERC721TokenWrapper extends ContractWrapper {
const normalizedSenderAddress = senderAddress.toLowerCase();
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
const ownerAddress = await this.getOwnerOfAsync(tokenAddress, tokenId);
const isApprovedForAll = await this.isApprovedForAllAsync(
normalizedTokenAddress,
ownerAddress,
normalizedSenderAddress,
);
if (!isApprovedForAll) {
const approvedAddress = await this.getApprovedIfExistsAsync(normalizedTokenAddress, tokenId);
if (approvedAddress !== senderAddress) {
throw new Error(ContractWrappersError.ERC721NoApproval);
if (normalizedSenderAddress !== ownerAddress) {
const isApprovedForAll = await this.isApprovedForAllAsync(
normalizedTokenAddress,
ownerAddress,
normalizedSenderAddress,
);
if (!isApprovedForAll) {
const approvedAddress = await this.getApprovedIfExistsAsync(normalizedTokenAddress, tokenId);
if (approvedAddress !== normalizedSenderAddress) {
throw new Error(ContractWrappersError.ERC721NoApproval);
}
}
}
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
@@ -372,6 +374,7 @@ export class ERC721TokenWrapper extends ContractWrapper {
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC721TokenEventArgs>(
@@ -379,6 +382,7 @@ export class ERC721TokenWrapper extends ContractWrapper {
eventName: ERC721TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents);
@@ -391,6 +395,7 @@ export class ERC721TokenWrapper extends ContractWrapper {
indexFilterValues,
artifacts.ERC721Token.compilerOutput.abi,
callback,
isVerbose,
);
return subscriptionToken;
}

View File

@@ -146,6 +146,7 @@ export class EtherTokenWrapper extends ContractWrapper {
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_owner: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends WETH9EventArgs>(
@@ -153,6 +154,7 @@ export class EtherTokenWrapper extends ContractWrapper {
eventName: WETH9Events,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
assert.isETHAddressHex('etherTokenAddress', etherTokenAddress);
const normalizedEtherTokenAddress = etherTokenAddress.toLowerCase();
@@ -165,6 +167,7 @@ export class EtherTokenWrapper extends ContractWrapper {
indexFilterValues,
artifacts.EtherToken.compilerOutput.abi,
callback,
isVerbose,
);
return subscriptionToken;
}

View File

@@ -1,4 +1,5 @@
import { schemas } from '@0xproject/json-schemas';
import { assetDataUtils } from '@0xproject/order-utils';
import { AssetProxyId, Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
@@ -988,12 +989,14 @@ export class ExchangeWrapper extends ContractWrapper {
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ExchangeEventArgs>(
eventName: ExchangeEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
): string {
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
@@ -1005,6 +1008,7 @@ export class ExchangeWrapper extends ContractWrapper {
indexFilterValues,
artifacts.Exchange.compilerOutput.abi,
callback,
isVerbose,
);
return subscriptionToken;
}
@@ -1068,9 +1072,9 @@ export class ExchangeWrapper extends ContractWrapper {
* Returns the ZRX asset data used by the exchange contract.
* @return ZRX asset data
*/
public async getZRXAssetDataAsync(): Promise<string> {
const exchangeInstance = await this._getExchangeContractAsync();
const zrxAssetData = exchangeInstance.ZRX_ASSET_DATA.callAsync();
public getZRXAssetData(): string {
const zrxTokenAddress = this.getZRXTokenAddress();
const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenAddress);
return zrxAssetData;
}
// tslint:disable:no-unused-variable

View File

@@ -1,7 +1,10 @@
export { ContractWrappers } from './contract_wrappers';
export { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
export { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
export {
ContractWrappersError,
@@ -23,7 +26,15 @@ export {
OrderInfo,
} from './types';
export { Order, SignedOrder, ECSignature, OrderStateValid, OrderStateInvalid, OrderState } from '@0xproject/types';
export {
Order,
SignedOrder,
ECSignature,
OrderStateValid,
OrderStateInvalid,
OrderState,
AssetProxyId,
} from '@0xproject/types';
export {
BlockParamLiteral,
@@ -57,6 +68,7 @@ export {
ERC721TokenApprovalForAllEventArgs,
ERC721TokenTransferEventArgs,
ERC721TokenEvents,
ERC721TokenEventArgs,
} from './contract_wrappers/generated/erc721_token';
export {

View File

@@ -8,8 +8,8 @@ export const contractWrappersPrivateNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
blockPollingIntervalMs: { type: 'number' },
orderWatcherConfig: {
type: 'object',
@@ -30,7 +30,7 @@ export const contractWrappersPrivateNetworkConfigSchema = {
'networkId',
'zrxContractAddress',
'exchangeContractAddress',
'tokenRegistryContractAddress',
'tokenTransferProxyContractAddress',
'erc20ProxyContractAddress',
'erc721ProxyContractAddress',
],
};

View File

@@ -22,8 +22,8 @@ export const contractWrappersPublicNetworkConfigSchema = {
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
tokenRegistryContractAddress: { $ref: '/Address' },
tokenTransferProxyContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
blockPollingIntervalMs: { type: 'number' },
orderWatcherConfig: {
type: 'object',

View File

@@ -1,5 +1,5 @@
import { assert as sharedAssert } from '@0xproject/assert';
// We need those two unused imports because they're actually used by sharedAssert which gets injected here
// 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 { isValidSignatureAsync } from '@0xproject/order-utils';
import { ECSignature } from '@0xproject/types'; // tslint:disable-line:no-unused-variable

View File

@@ -1,11 +1,10 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { EmptyWalletSubprovider } from '@0xproject/subproviders';
import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0xproject/subproviders';
import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { Provider } from 'ethereum-types';
import 'mocha';
import Web3ProviderEngine = require('web3-provider-engine');
import {
BlockParamLiteral,

View File

@@ -1,11 +1,10 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { EmptyWalletSubprovider } from '@0xproject/subproviders';
import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0xproject/subproviders';
import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { Provider } from 'ethereum-types';
import 'mocha';
import Web3ProviderEngine = require('web3-provider-engine');
import {
BlockParamLiteral,

View File

@@ -336,15 +336,19 @@ describe('EtherTokenWrapper', () => {
describe('#getLogsAsync', () => {
let etherTokenAddress: string;
let erc20ProxyAddress: string;
const blockRange: BlockRange = {
fromBlock: 0,
toBlock: BlockParamLiteral.Latest,
};
let blockRange: BlockRange;
let txHash: string;
before(() => {
before(async () => {
addressWithETH = userAddresses[0];
etherTokenAddress = tokenUtils.getWethTokenAddress();
erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
// Start the block range after all migrations to avoid unexpected logs
const currentBlock = await web3Wrapper.getBlockNumberAsync();
const fromBlock = currentBlock + 1;
blockRange = {
fromBlock,
toBlock: BlockParamLiteral.Latest,
};
});
it('should get logs with decoded args emitted by Approval', async () => {
txHash = await contractWrappers.erc20Token.setUnlimitedProxyAllowanceAsync(

View File

@@ -1,6 +1,6 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { DoneCallback, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -53,7 +53,6 @@ describe('ExchangeWrapper', () => {
await blockchainLifecycle.startAsync();
contractWrappers = new ContractWrappers(provider, config);
exchangeContractAddress = contractWrappers.exchange.getContractAddress();
const erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
fillScenarios = new FillScenarios(
@@ -61,13 +60,14 @@ describe('ExchangeWrapper', () => {
userAddresses,
zrxTokenAddress,
exchangeContractAddress,
erc20ProxyAddress,
contractWrappers.erc20Proxy.getContractAddress(),
contractWrappers.erc721Proxy.getContractAddress(),
);
[coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
[makerAssetData, takerAssetData] = [
assetProxyUtils.encodeERC20AssetData(makerTokenAddress),
assetProxyUtils.encodeERC20AssetData(takerTokenAddress),
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
assetDataUtils.encodeERC20AssetData(takerTokenAddress),
];
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
makerAssetData,
@@ -264,8 +264,8 @@ describe('ExchangeWrapper', () => {
});
});
describe('#getZRXAssetData', () => {
it('should get the asset data', async () => {
const ZRX_ASSET_DATA = await contractWrappers.exchange.getZRXAssetDataAsync();
it('should get the asset data', () => {
const ZRX_ASSET_DATA = contractWrappers.exchange.getZRXAssetData();
const ASSET_DATA_HEX_LENGTH = 74;
expect(ZRX_ASSET_DATA).to.have.length(ASSET_DATA_HEX_LENGTH);
});

View File

@@ -7,7 +7,7 @@ before('migrate contracts', async function(): Promise<void> {
// HACK: Since the migrations take longer then our global mocha timeout limit
// we manually increase it for this before hook.
const mochaTestTimeoutMs = 50000;
this.timeout(mochaTestTimeoutMs);
this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
const txDefaults = {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,

View File

@@ -49,44 +49,6 @@ describe('SubscriptionTest', () => {
_.each(stubs, s => s.restore());
stubs = [];
});
it('Should receive the Error when an error occurs while fetching the block', (done: DoneCallback) => {
(async () => {
const errMsg = 'Error fetching block';
const callback = callbackErrorReporter.assertNodeCallbackError(done, errMsg);
stubs = [Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws(new Error(errMsg))];
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Approval,
indexFilterValues,
callback,
);
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
coinbase,
addressWithoutFunds,
allowanceAmount,
);
})().catch(done);
});
it('Should receive the Error when an error occurs while reconciling the new block', (done: DoneCallback) => {
(async () => {
const errMsg = 'Error fetching logs';
const callback = callbackErrorReporter.assertNodeCallbackError(done, errMsg);
stubs = [Sinon.stub((contractWrappers as any)._web3Wrapper, 'getLogsAsync').throws(new Error(errMsg))];
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Approval,
indexFilterValues,
callback,
);
await contractWrappers.erc20Token.setAllowanceAsync(
tokenAddress,
coinbase,
addressWithoutFunds,
allowanceAmount,
);
})().catch(done);
});
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
(async () => {
const callback = (err: Error | null, _logEvent?: DecodedLogEvent<ERC20TokenApprovalEventArgs>) =>

View File

@@ -25,6 +25,7 @@
"DummyERC721Token",
"ERC20Proxy",
"ERC20Token",
"ERC721Token",
"ERC721Proxy",
"Exchange",
"ExchangeWrapper",

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "contracts",
"version": "2.1.34",
"version": "2.1.35",
"engines": {
"node": ">=6.12"
},
@@ -46,11 +46,11 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/contracts/README.md",
"devDependencies": {
"@0xproject/abi-gen": "^0.3.3",
"@0xproject/dev-utils": "^0.4.5",
"@0xproject/abi-gen": "^0.3.4",
"@0xproject/dev-utils": "^0.4.6",
"@0xproject/tslint-config": "^0.4.21",
"@0xproject/subproviders": "^0.10.5",
"@0xproject/sol-cov": "^0.1.2",
"@0xproject/subproviders": "^0.10.6",
"@0xproject/sol-cov": "^0.1.3",
"@types/lodash": "4.14.104",
"@types/bn.js": "^4.11.0",
"@types/node": "^8.0.53",
@@ -67,18 +67,18 @@
"shx": "^0.2.2",
"solc": "^0.4.24",
"solhint": "^1.2.1",
"tslint": "5.8.0",
"tslint": "5.11.0",
"typescript": "2.7.1",
"yargs": "^10.0.3"
},
"dependencies": {
"@0xproject/base-contract": "^0.3.5",
"@0xproject/base-contract": "^0.3.6",
"@0xproject/order-utils": "^1.0.0",
"@0xproject/sol-compiler": "^0.5.3",
"@0xproject/sol-compiler": "^0.5.4",
"@0xproject/types": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.2",
"@0xproject/utils": "^0.7.2",
"@0xproject/web3-wrapper": "^0.7.2",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/utils": "^0.7.3",
"@0xproject/web3-wrapper": "^0.7.3",
"ethereum-types": "^0.0.2",
"bn.js": "^4.11.8",
"ethereumjs-abi": "^0.6.4",

View File

@@ -18,7 +18,7 @@
pragma solidity ^0.4.10;
import "../../current/multisig/MultiSigWalletWithTimeLock.sol";
import "../../2.0.0/multisig/MultiSigWalletWithTimeLock.sol";
contract MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress is MultiSigWalletWithTimeLock {
@@ -79,4 +79,4 @@ contract MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress is MultiSigWall
}
return true;
}
}
}

View File

@@ -40,7 +40,6 @@ contract Forwarder is
address _exchange,
address _etherToken,
address _zrxToken,
bytes4 _erc20AssetProxyId,
bytes memory _zrxAssetData,
bytes memory _wethAssetData
)

View File

@@ -16,16 +16,14 @@
*/
pragma solidity ^0.4.10;
pragma solidity 0.4.10;
import "../../multisig/MultiSigWalletWithTimeLock.sol";
import "../../utils/LibBytes/LibBytes.sol";
contract AssetProxyOwner is
MultiSigWalletWithTimeLock
{
using LibBytes for bytes;
event AssetProxyRegistration(address assetProxyContract, bool isRegistered);
@@ -40,7 +38,7 @@ contract AssetProxyOwner is
modifier validRemoveAuthorizedAddressAtIndexTx(uint256 transactionId) {
Transaction storage tx = transactions[transactionId];
require(isAssetProxyRegistered[tx.destination]);
require(tx.data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR);
require(readBytes4(tx.data, 0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR);
_;
}
@@ -97,4 +95,25 @@ contract AssetProxyOwner is
tx.executed = false;
}
}
/// @dev Reads an unpadded bytes4 value from a position in a byte array.
/// @param b Byte array containing a bytes4 value.
/// @param index Index in byte array of bytes4 value.
/// @return bytes4 value from byte array.
function readBytes4(
bytes memory b,
uint256 index
)
internal
returns (bytes4 result)
{
require(b.length >= index + 4);
assembly {
result := mload(add(b, 32))
// Solidity does not require us to clean the trailing bytes.
// We do it anyway
result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
}
return result;
}
}

View File

@@ -154,6 +154,9 @@ contract MixinExchangeCore is
// Compute the order hash
orderInfo.orderHash = getOrderHash(order);
// Fetch filled amount
orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash];
// If order.makerAssetAmount is zero, we also reject the order.
// While the Exchange contract handles them correctly, they create
// edge cases in the supporting infrastructure because they have
@@ -172,6 +175,12 @@ contract MixinExchangeCore is
return orderInfo;
}
// Validate order availability
if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) {
orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED);
return orderInfo;
}
// Validate order expiration
// solhint-disable-next-line not-rely-on-time
if (block.timestamp >= order.expirationTimeSeconds) {
@@ -189,13 +198,6 @@ contract MixinExchangeCore is
return orderInfo;
}
// Fetch filled amount and validate order availability
orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash];
if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) {
orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED);
return orderInfo;
}
// All other statuses are ruled out: order is Fillable
orderInfo.orderStatus = uint8(OrderStatus.FILLABLE);
return orderInfo;

View File

@@ -529,4 +529,20 @@ contract MixinWrapperFunctions is
cancelOrder(orders[i]);
}
}
/// @dev Fetches information for all passed in orders.
/// @param orders Array of order specifications.
/// @return Array of OrderInfo instances that correspond to each order.
function getOrdersInfo(LibOrder.Order[] memory orders)
public
view
returns (LibOrder.OrderInfo[] memory)
{
uint256 length = orders.length;
LibOrder.OrderInfo[] memory ordersInfo = new LibOrder.OrderInfo[](length);
for (uint256 i = 0; i < length; i++) {
ordersInfo[i] = getOrderInfo(orders[i]);
}
return ordersInfo;
}
}

View File

@@ -149,4 +149,12 @@ contract IWrapperFunctions {
/// @param orders Array of order specifications.
function batchCancelOrders(LibOrder.Order[] memory orders)
public;
/// @dev Fetches information for all passed in orders
/// @param orders Array of order specifications.
/// @return Array of OrderInfo instances that correspond to each order.
function getOrdersInfo(LibOrder.Order[] memory orders)
public
view
returns (LibOrder.OrderInfo[] memory);
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity 0.4.24;
pragma solidity 0.4.10;
import "../../protocol/AssetProxyOwner/AssetProxyOwner.sol";
@@ -26,7 +26,7 @@ contract TestAssetProxyOwner is
AssetProxyOwner
{
constructor(
function TestAssetProxyOwner(
address[] memory _owners,
address[] memory _assetProxyContracts,
uint256 _required,
@@ -38,7 +38,6 @@ contract TestAssetProxyOwner is
function testValidRemoveAuthorizedAddressAtIndexTx(uint256 id)
public
view
validRemoveAuthorizedAddressAtIndexTx(id)
returns (bool)
{
@@ -51,9 +50,23 @@ contract TestAssetProxyOwner is
/// @return Successful if data is a call to `removeAuthorizedAddressAtIndex`.
function isFunctionRemoveAuthorizedAddressAtIndex(bytes memory data)
public
pure
returns (bool)
{
return data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR;
return readBytes4(data, 0) == REMOVE_AUTHORIZED_ADDRESS_AT_INDEX_SELECTOR;
}
/// @dev Reads an unpadded bytes4 value from a position in a byte array.
/// @param b Byte array containing a bytes4 value.
/// @param index Index in byte array of bytes4 value.
/// @return bytes4 value from byte array.
function publicReadBytes4(
bytes memory b,
uint256 index
)
public
returns (bytes4 result)
{
result = readBytes4(b, index);
return result;
}
}

View File

@@ -457,7 +457,8 @@ library LibBytes {
/// @return bytes4 value from byte array.
function readBytes4(
bytes memory b,
uint256 index)
uint256 index
)
internal
pure
returns (bytes4 result)

View File

@@ -7,8 +7,14 @@ contract SafeMath {
pure
returns (uint256)
{
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(a == 0 || c / a == b);
require(
c / a == b,
"UINT256_OVERFLOW"
);
return c;
}
@@ -26,7 +32,10 @@ contract SafeMath {
pure
returns (uint256)
{
assert(b <= a);
require(
b <= a,
"UINT256_OVERFLOW"
);
return a - b;
}
@@ -36,7 +45,10 @@ contract SafeMath {
returns (uint256)
{
uint256 c = a + b;
assert(c >= a);
require(
c >= a,
"UINT256_OVERFLOW"
);
return c;
}

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { assetDataUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { RevertReason } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -23,6 +23,7 @@ import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { LogDecoder } from '../utils/log_decoder';
import { typeEncodingUtils } from '../utils/type_encoding_utils';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
@@ -107,7 +108,7 @@ describe('Asset Transfer Proxies', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
// Construct ERC20 asset data
const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
@@ -137,7 +138,7 @@ describe('Asset Transfer Proxies', () => {
it('should do nothing if transferring 0 amount of a token', async () => {
// Construct ERC20 asset data
const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0);
@@ -167,7 +168,7 @@ describe('Asset Transfer Proxies', () => {
it('should throw if allowances are too low', async () => {
// Construct ERC20 asset data
const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
// Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0);
const amount = new BigNumber(10);
@@ -196,7 +197,7 @@ describe('Asset Transfer Proxies', () => {
it('should throw if requesting address is not authorized', async () => {
// Construct ERC20 asset data
const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
@@ -227,7 +228,7 @@ describe('Asset Transfer Proxies', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
// Construct ERC721 asset data
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -254,7 +255,7 @@ describe('Asset Transfer Proxies', () => {
it('should call onERC721Received when transferring to a smart contract without receiver data', async () => {
// Construct ERC721 asset data
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -272,7 +273,7 @@ describe('Asset Transfer Proxies', () => {
to: erc721Proxy.address,
data,
from: exchangeAddress,
gas: constants.TRANSFER_FROM_GAS,
gas: constants.MAX_TRANSFER_FROM_GAS,
}),
);
// Verify that no log was emitted by erc721 receiver
@@ -288,8 +289,8 @@ describe('Asset Transfer Proxies', () => {
it('should call onERC721Received when transferring to a smart contract with receiver data', async () => {
// Construct ERC721 asset data
const receiverData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt()));
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(
const receiverData = ethUtil.bufferToHex(typeEncodingUtils.encodeUint256(generatePseudoRandomSalt()));
const encodedAssetData = assetDataUtils.encodeERC721AssetData(
erc721Token.address,
erc721MakerTokenId,
receiverData,
@@ -311,7 +312,7 @@ describe('Asset Transfer Proxies', () => {
to: erc721Proxy.address,
data,
from: exchangeAddress,
gas: constants.TRANSFER_FROM_GAS,
gas: constants.MAX_TRANSFER_FROM_GAS,
}),
);
// Validate log emitted by erc721 receiver
@@ -327,8 +328,8 @@ describe('Asset Transfer Proxies', () => {
it('should throw if there is receiver data but contract does not have onERC721Received', async () => {
// Construct ERC721 asset data
const receiverData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt()));
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(
const receiverData = ethUtil.bufferToHex(typeEncodingUtils.encodeUint256(generatePseudoRandomSalt()));
const encodedAssetData = assetDataUtils.encodeERC721AssetData(
erc721Token.address,
erc721MakerTokenId,
receiverData,
@@ -349,7 +350,7 @@ describe('Asset Transfer Proxies', () => {
to: erc721Proxy.address,
data,
from: exchangeAddress,
gas: constants.TRANSFER_FROM_GAS,
gas: constants.MAX_TRANSFER_FROM_GAS,
}),
RevertReason.TransferFailed,
);
@@ -357,7 +358,7 @@ describe('Asset Transfer Proxies', () => {
it('should throw if transferring 0 amount of a token', async () => {
// Construct ERC721 asset data
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -381,7 +382,7 @@ describe('Asset Transfer Proxies', () => {
it('should throw if transferring > 1 amount of a token', async () => {
// Construct ERC721 asset data
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -405,7 +406,7 @@ describe('Asset Transfer Proxies', () => {
it('should throw if allowances are too low', async () => {
// Construct ERC721 asset data
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Remove transfer approval for makerAddress.
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Token.approve.sendTransactionAsync(constants.NULL_ADDRESS, erc721MakerTokenId, {
@@ -433,7 +434,7 @@ describe('Asset Transfer Proxies', () => {
it('should throw if requesting address is not authorized', async () => {
// Construct ERC721 asset data
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(1);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { RevertReason, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
@@ -15,13 +15,14 @@ import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_pr
import { ExchangeCancelEventArgs, ExchangeContract } from '../../generated_contract_wrappers/exchange';
import { artifacts } from '../utils/artifacts';
import { expectTransactionFailedAsync } from '../utils/assertions';
import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { OrderFactory } from '../utils/order_factory';
import { ERC20BalancesByOwner } from '../utils/types';
import { ERC20BalancesByOwner, OrderStatus } from '../utils/types';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
@@ -87,7 +88,7 @@ describe('Exchange core', () => {
artifacts.Exchange,
provider,
txDefaults,
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
assetDataUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@@ -114,8 +115,8 @@ describe('Exchange core', () => {
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
@@ -129,11 +130,11 @@ describe('Exchange core', () => {
describe('fillOrder', () => {
beforeEach(async () => {
erc20Balances = await erc20Wrapper.getBalancesAsync();
signedOrder = orderFactory.newSignedOrder();
signedOrder = await orderFactory.newSignedOrderAsync();
});
it('should throw if signature is invalid', async () => {
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
});
@@ -151,7 +152,7 @@ describe('Exchange core', () => {
});
it('should throw if no value is filled', async () => {
signedOrder = orderFactory.newSignedOrder();
signedOrder = await orderFactory.newSignedOrderAsync();
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
return expectTransactionFailedAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
@@ -163,7 +164,7 @@ describe('Exchange core', () => {
describe('cancelOrder', () => {
beforeEach(async () => {
erc20Balances = await erc20Wrapper.getBalancesAsync();
signedOrder = orderFactory.newSignedOrder();
signedOrder = await orderFactory.newSignedOrderAsync();
});
it('should throw if not sent by maker', async () => {
@@ -174,7 +175,7 @@ describe('Exchange core', () => {
});
it('should throw if makerAssetAmount is 0', async () => {
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(0),
});
@@ -185,7 +186,7 @@ describe('Exchange core', () => {
});
it('should throw if takerAssetAmount is 0', async () => {
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
takerAssetAmount: new BigNumber(0),
});
@@ -229,8 +230,9 @@ describe('Exchange core', () => {
});
it('should throw if order is expired', async () => {
signedOrder = orderFactory.newSignedOrder({
expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
const currentTimestamp = await getLatestBlockTimestampAsync();
signedOrder = await orderFactory.newSignedOrderAsync({
expirationTimeSeconds: new BigNumber(currentTimestamp).sub(10),
});
return expectTransactionFailedAsync(
exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
@@ -239,7 +241,7 @@ describe('Exchange core', () => {
});
it('should throw if rounding error is greater than 0.1%', async () => {
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1001),
takerAssetAmount: new BigNumber(3),
});
@@ -288,22 +290,22 @@ describe('Exchange core', () => {
// Since we cancelled with orderEpoch=1, orders with orderEpoch<=1 will not be processed
erc20Balances = await erc20Wrapper.getBalancesAsync();
const signedOrders = [
orderFactory.newSignedOrder({
await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18),
salt: new BigNumber(0),
}),
orderFactory.newSignedOrder({
await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(79), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(79), 18),
salt: new BigNumber(1),
}),
orderFactory.newSignedOrder({
await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(979), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(979), 18),
salt: new BigNumber(2),
}),
orderFactory.newSignedOrder({
await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18),
salt: new BigNumber(3),
@@ -350,11 +352,11 @@ describe('Exchange core', () => {
// Construct Exchange parameters
const makerAssetId = erc721TakerAssetIds[0];
const takerAssetId = erc721TakerAssetIds[1];
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -373,11 +375,11 @@ describe('Exchange core', () => {
// Construct Exchange parameters
const makerAssetId = erc721MakerAssetIds[0];
const takerAssetId = erc721MakerAssetIds[1];
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -396,11 +398,11 @@ describe('Exchange core', () => {
// Construct Exchange parameters
const makerAssetId = erc721MakerAssetIds[0];
const takerAssetId = erc721TakerAssetIds[0];
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(2),
takerAssetAmount: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -419,11 +421,11 @@ describe('Exchange core', () => {
// Construct Exchange parameters
const makerAssetId = erc721MakerAssetIds[0];
const takerAssetId = erc721TakerAssetIds[0];
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(500),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -441,11 +443,11 @@ describe('Exchange core', () => {
it('should throw on partial fill', async () => {
// Construct Exchange parameters
const makerAssetId = erc721MakerAssetIds[0];
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
});
// Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
@@ -459,14 +461,12 @@ describe('Exchange core', () => {
// Construct Exchange parameters
const makerAssetId = erc721MakerAssetIds[0];
const takerAssetId = erc721TakerAssetIds[0];
const makerAssetData = assetProxyUtils
.encodeERC721AssetData(erc721Token.address, makerAssetId)
.slice(0, -2);
signedOrder = orderFactory.newSignedOrder({
const makerAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId).slice(0, -2);
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1),
makerAssetData,
takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -481,6 +481,124 @@ describe('Exchange core', () => {
);
});
});
describe('getOrderInfo', () => {
beforeEach(async () => {
signedOrder = await orderFactory.newSignedOrderAsync();
});
it('should return the correct orderInfo for an unfilled valid order', async () => {
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.FILLABLE;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for a fully filled order', async () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount;
const expectedOrderStatus = OrderStatus.FULLY_FILLED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for a partially filled order', async () => {
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = takerAssetFillAmount;
const expectedOrderStatus = OrderStatus.FILLABLE;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for a cancelled and unfilled order', async () => {
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.CANCELLED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for a cancelled and partially filled order', async () => {
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = takerAssetFillAmount;
const expectedOrderStatus = OrderStatus.CANCELLED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an expired and unfilled order', async () => {
const currentTimestamp = await getLatestBlockTimestampAsync();
const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber();
await increaseTimeAndMineBlockAsync(timeUntilExpiration);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.EXPIRED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an expired and partially filled order', async () => {
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const currentTimestamp = await getLatestBlockTimestampAsync();
const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber();
await increaseTimeAndMineBlockAsync(timeUntilExpiration);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = takerAssetFillAmount;
const expectedOrderStatus = OrderStatus.EXPIRED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an expired and fully filled order', async () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
const currentTimestamp = await getLatestBlockTimestampAsync();
const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber();
await increaseTimeAndMineBlockAsync(timeUntilExpiration);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount;
// FULLY_FILLED takes precedence over EXPIRED
const expectedOrderStatus = OrderStatus.FULLY_FILLED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an order with a makerAssetAmount of 0', async () => {
signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(0) });
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.INVALID_MAKER_ASSET_AMOUNT;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an order with a takerAssetAmount of 0', async () => {
signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(0) });
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.INVALID_TAKER_ASSET_AMOUNT;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
});
// tslint:disable:max-file-line-count
// tslint:enable:no-unnecessary-type-assertion

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
import { assetDataUtils } from '@0xproject/order-utils';
import { AssetProxyId, RevertReason } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -180,7 +180,7 @@ describe('AssetProxyDispatcher', () => {
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Construct metadata for ERC20 proxy
const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
@@ -207,7 +207,7 @@ describe('AssetProxyDispatcher', () => {
it('should throw if dispatching to unregistered proxy', async () => {
// Construct metadata for ERC20 proxy
const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10);
return expectTransactionFailedAsync(

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, EIP712Utils, orderHashUtils } from '@0xproject/order-utils';
import { assetDataUtils, EIP712Utils, orderHashUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -38,8 +38,8 @@ describe('Exchange libs', () => {
exchangeAddress: libs.address,
makerAddress,
feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
makerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
takerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
makerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
takerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
@@ -71,7 +71,7 @@ describe('Exchange libs', () => {
});
describe('getOrderHash', () => {
it('should output the correct orderHash', async () => {
signedOrder = orderFactory.newSignedOrder();
signedOrder = await orderFactory.newSignedOrderAsync();
const orderHashHex = await libs.publicGetOrderHash.callAsync(signedOrder);
expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
});

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
import { assetDataUtils } from '@0xproject/order-utils';
import { RevertReason } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
@@ -100,7 +100,7 @@ describe('matchOrders', () => {
artifacts.Exchange,
provider,
txDefaults,
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
assetDataUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@@ -126,8 +126,8 @@ describe('matchOrders', () => {
const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS,
exchangeAddress: exchange.address,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
};
const privateKeyLeft = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddressLeft)];
orderFactoryLeft = new OrderFactory(privateKeyLeft, defaultOrderParams);
@@ -150,16 +150,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts when orders completely fill each other', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -182,16 +182,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts when orders completely fill each other and taker doesnt take a profit', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -225,16 +225,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts when left order is completely filled and right order is partially filled', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(20), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -257,16 +257,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts when right order is completely filled and left order is partially filled', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -289,16 +289,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts when consecutive calls are used to completely fill the left order', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -326,10 +326,10 @@ describe('matchOrders', () => {
// Note: This order needs makerAssetAmount=90/takerAssetAmount=[anything <= 45] to fully fill the right order.
// However, we use 100/50 to ensure a partial fill as we want to go down the "left fill"
// branch in the contract twice for this test.
const signedOrderRight2 = orderFactoryRight.newSignedOrder({
const signedOrderRight2 = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -356,17 +356,17 @@ describe('matchOrders', () => {
it('should transfer the correct amounts when consecutive calls are used to completely fill the right order', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -394,7 +394,7 @@ describe('matchOrders', () => {
// Note: This order needs makerAssetAmount=96/takerAssetAmount=48 to fully fill the right order.
// However, we use 100/50 to ensure a partial fill as we want to go down the "right fill"
// branch in the contract twice for this test.
const signedOrderLeft2 = orderFactoryLeft.newSignedOrder({
const signedOrderLeft2 = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
@@ -425,16 +425,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts if fee recipient is the same across both matched orders', async () => {
const feeRecipientAddress = feeRecipientAddressLeft;
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress,
@@ -451,16 +451,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts if taker is also the left order maker', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -478,16 +478,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts if taker is also the right order maker', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -505,16 +505,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts if taker is also the left fee recipient', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -532,16 +532,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts if taker is also the right fee recipient', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -559,16 +559,16 @@ describe('matchOrders', () => {
it('should transfer the correct amounts if left maker is the left fee recipient and right maker is the right fee recipient', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: makerAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: makerAddressRight,
@@ -585,16 +585,16 @@ describe('matchOrders', () => {
it('Should throw if left order is not fillable', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -610,16 +610,16 @@ describe('matchOrders', () => {
it('Should throw if right order is not fillable', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -635,16 +635,16 @@ describe('matchOrders', () => {
it('should throw if there is not a positive spread', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -658,16 +658,16 @@ describe('matchOrders', () => {
it('should throw if the left maker asset is not equal to the right taker asset ', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -685,18 +685,18 @@ describe('matchOrders', () => {
it('should throw if the right maker asset is not equal to the left taker asset', async () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -711,18 +711,18 @@ describe('matchOrders', () => {
it('should transfer correct amounts when left order maker asset is an ERC721 token', async () => {
// Create orders to match
const erc721TokenToTransfer = erc721LeftMakerAssetIds[0];
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
makerAssetAmount: new BigNumber(1),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: new BigNumber(1),
feeRecipientAddress: feeRecipientAddressRight,
@@ -746,18 +746,18 @@ describe('matchOrders', () => {
it('should transfer correct amounts when right order maker asset is an ERC721 token', async () => {
// Create orders to match
const erc721TokenToTransfer = erc721RightMakerAssetIds[0];
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAddress: makerAddressLeft,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: new BigNumber(1),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight,
makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: new BigNumber(1),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressRight,

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { addSignedMessagePrefix, assetProxyUtils, MessagePrefixType, orderHashUtils } from '@0xproject/order-utils';
import { addSignedMessagePrefix, assetDataUtils, MessagePrefixType, orderHashUtils } from '@0xproject/order-utils';
import { RevertReason, SignatureType, SignedOrder } from '@0xproject/types';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
@@ -78,8 +78,8 @@ describe('MixinSignatureValidator', () => {
exchangeAddress: signatureValidator.address,
makerAddress,
feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
makerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
takerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
makerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
takerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
};
signerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
notSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(notSignerAddress)];
@@ -95,7 +95,7 @@ describe('MixinSignatureValidator', () => {
describe('isValidSignature', () => {
beforeEach(async () => {
signedOrder = orderFactory.newSignedOrder();
signedOrder = await orderFactory.newSignedOrderAsync();
});
it('should revert when signature is empty', async () => {

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { assetDataUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { OrderWithoutExchangeAddress, RevertReason, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -88,7 +88,7 @@ describe('Exchange transactions', () => {
artifacts.Exchange,
provider,
txDefaults,
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
assetDataUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@@ -107,8 +107,8 @@ describe('Exchange transactions', () => {
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerTokenAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerTokenAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerTokenAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerTokenAddress),
};
makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
@@ -121,7 +121,7 @@ describe('Exchange transactions', () => {
let takerAssetFillAmount: BigNumber;
beforeEach(async () => {
erc20Balances = await erc20Wrapper.getBalancesAsync();
signedOrder = orderFactory.newSignedOrder();
signedOrder = await orderFactory.newSignedOrderAsync();
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
@@ -226,7 +226,7 @@ describe('Exchange transactions', () => {
it("should cancel an order if called from the order's sender", async () => {
const orderSalt = new BigNumber(0);
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
senderAddress: exchangeWrapperContract.address,
salt: orderSalt,
});
@@ -265,7 +265,7 @@ describe('Exchange transactions', () => {
it("should not cancel an order if not called from the order's sender", async () => {
const orderSalt = new BigNumber(0);
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
senderAddress: exchangeWrapperContract.address,
salt: orderSalt,
});
@@ -349,14 +349,14 @@ describe('Exchange transactions', () => {
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerTokenAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerTokenAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerTokenAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerTokenAddress),
};
whitelistOrderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams);
});
beforeEach(async () => {
signedOrder = whitelistOrderFactory.newSignedOrder();
signedOrder = await whitelistOrderFactory.newSignedOrderAsync();
erc20Balances = await erc20Wrapper.getBalancesAsync();
});

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { RevertReason, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
@@ -13,13 +13,14 @@ import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_pr
import { ExchangeContract } from '../../generated_contract_wrappers/exchange';
import { artifacts } from '../utils/artifacts';
import { expectTransactionFailedAsync } from '../utils/assertions';
import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { OrderFactory } from '../utils/order_factory';
import { ERC20BalancesByOwner } from '../utils/types';
import { ERC20BalancesByOwner, OrderStatus } from '../utils/types';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
@@ -84,7 +85,7 @@ describe('Exchange wrappers', () => {
artifacts.Exchange,
provider,
txDefaults,
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
assetDataUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
@@ -111,8 +112,8 @@ describe('Exchange wrappers', () => {
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
@@ -126,7 +127,7 @@ describe('Exchange wrappers', () => {
});
describe('fillOrKillOrder', () => {
it('should transfer the correct amounts', async () => {
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
});
@@ -170,8 +171,9 @@ describe('Exchange wrappers', () => {
});
it('should throw if a signedOrder is expired', async () => {
const signedOrder = orderFactory.newSignedOrder({
expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
const currentTimestamp = await getLatestBlockTimestampAsync();
const signedOrder = await orderFactory.newSignedOrderAsync({
expirationTimeSeconds: new BigNumber(currentTimestamp).sub(10),
});
return expectTransactionFailedAsync(
@@ -181,7 +183,7 @@ describe('Exchange wrappers', () => {
});
it('should throw if entire takerAssetFillAmount not filled', async () => {
const signedOrder = orderFactory.newSignedOrder();
const signedOrder = await orderFactory.newSignedOrderAsync();
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerAssetFillAmount: signedOrder.takerAssetAmount.div(2),
@@ -196,7 +198,7 @@ describe('Exchange wrappers', () => {
describe('fillOrderNoThrow', () => {
it('should transfer the correct amounts', async () => {
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
});
@@ -245,7 +247,7 @@ describe('Exchange wrappers', () => {
});
it('should not change erc20Balances if maker erc20Balances are too low to fill order', async () => {
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18),
});
@@ -255,7 +257,7 @@ describe('Exchange wrappers', () => {
});
it('should not change erc20Balances if taker erc20Balances are too low to fill order', async () => {
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18),
});
@@ -265,7 +267,7 @@ describe('Exchange wrappers', () => {
});
it('should not change erc20Balances if maker allowances are too low to fill order', async () => {
const signedOrder = orderFactory.newSignedOrder();
const signedOrder = await orderFactory.newSignedOrderAsync();
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), {
from: makerAddress,
@@ -285,7 +287,7 @@ describe('Exchange wrappers', () => {
});
it('should not change erc20Balances if taker allowances are too low to fill order', async () => {
const signedOrder = orderFactory.newSignedOrder();
const signedOrder = await orderFactory.newSignedOrderAsync();
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), {
from: takerAddress,
@@ -306,10 +308,10 @@ describe('Exchange wrappers', () => {
it('should not change erc20Balances if makerAssetAddress is ZRX, makerAssetAmount + makerFee > maker balance', async () => {
const makerZRXBalance = new BigNumber(erc20Balances[makerAddress][zrxToken.address]);
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: makerZRXBalance,
makerFee: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
});
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
@@ -318,10 +320,10 @@ describe('Exchange wrappers', () => {
it('should not change erc20Balances if makerAssetAddress is ZRX, makerAssetAmount + makerFee > maker allowance', async () => {
const makerZRXAllowance = await zrxToken.allowance.callAsync(makerAddress, erc20Proxy.address);
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(makerZRXAllowance),
makerFee: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
});
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
@@ -330,10 +332,10 @@ describe('Exchange wrappers', () => {
it('should not change erc20Balances if takerAssetAddress is ZRX, takerAssetAmount + takerFee > taker balance', async () => {
const takerZRXBalance = new BigNumber(erc20Balances[takerAddress][zrxToken.address]);
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
takerAssetAmount: takerZRXBalance,
takerFee: new BigNumber(1),
takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
takerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
});
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
@@ -342,10 +344,10 @@ describe('Exchange wrappers', () => {
it('should not change erc20Balances if takerAssetAddress is ZRX, takerAssetAmount + takerFee > taker allowance', async () => {
const takerZRXAllowance = await zrxToken.allowance.callAsync(takerAddress, erc20Proxy.address);
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
takerAssetAmount: new BigNumber(takerZRXAllowance),
takerFee: new BigNumber(1),
takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
takerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
});
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
@@ -356,11 +358,11 @@ describe('Exchange wrappers', () => {
// Construct Exchange parameters
const makerAssetId = erc721MakerAssetId;
const takerAssetId = erc721TakerAssetId;
const signedOrder = orderFactory.newSignedOrder({
const signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -388,9 +390,9 @@ describe('Exchange wrappers', () => {
let signedOrders: SignedOrder[];
beforeEach(async () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder(),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync(),
];
});
@@ -696,11 +698,11 @@ describe('Exchange wrappers', () => {
it('should throw when a signedOrder does not use the same takerAssetAddress', async () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync({
takerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
}),
orderFactory.newSignedOrder(),
await orderFactory.newSignedOrderAsync(),
];
return expectTransactionFailedAsync(
@@ -796,10 +798,10 @@ describe('Exchange wrappers', () => {
it('should not fill a signedOrder that does not use the same takerAssetAddress', async () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync({
takerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
}),
];
const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18);
@@ -914,11 +916,11 @@ describe('Exchange wrappers', () => {
it('should throw when a signedOrder does not use the same makerAssetAddress', async () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
}),
orderFactory.newSignedOrder(),
await orderFactory.newSignedOrderAsync(),
];
return expectTransactionFailedAsync(
@@ -1012,10 +1014,10 @@ describe('Exchange wrappers', () => {
it('should not fill a signedOrder that does not use the same makerAssetAddress', async () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
}),
];
@@ -1069,5 +1071,189 @@ describe('Exchange wrappers', () => {
expect(erc20Balances).to.be.deep.equal(newBalances);
});
});
describe('getOrdersInfo', () => {
beforeEach(async () => {
signedOrders = [
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync(),
await orderFactory.newSignedOrderAsync(),
];
});
it('should get the correct information for multiple unfilled orders', async () => {
const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
expect(ordersInfo.length).to.be.equal(3);
_.forEach(signedOrders, (signedOrder, index) => {
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.FILLABLE;
const orderInfo = ordersInfo[index];
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
it('should get the correct information for multiple partially filled orders', async () => {
const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2));
await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts });
const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
expect(ordersInfo.length).to.be.equal(3);
_.forEach(signedOrders, (signedOrder, index) => {
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2);
const expectedOrderStatus = OrderStatus.FILLABLE;
const orderInfo = ordersInfo[index];
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
it('should get the correct information for multiple fully filled orders', async () => {
await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress);
const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
expect(ordersInfo.length).to.be.equal(3);
_.forEach(signedOrders, (signedOrder, index) => {
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount;
const expectedOrderStatus = OrderStatus.FULLY_FILLED;
const orderInfo = ordersInfo[index];
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
it('should get the correct information for multiple cancelled and unfilled orders', async () => {
await exchangeWrapper.batchCancelOrdersAsync(signedOrders, makerAddress);
const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
expect(ordersInfo.length).to.be.equal(3);
_.forEach(signedOrders, (signedOrder, index) => {
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.CANCELLED;
const orderInfo = ordersInfo[index];
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
it('should get the correct information for multiple cancelled and partially filled orders', async () => {
const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2));
await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts });
await exchangeWrapper.batchCancelOrdersAsync(signedOrders, makerAddress);
const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
expect(ordersInfo.length).to.be.equal(3);
_.forEach(signedOrders, (signedOrder, index) => {
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2);
const expectedOrderStatus = OrderStatus.CANCELLED;
const orderInfo = ordersInfo[index];
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
it('should get the correct information for multiple expired and unfilled orders', async () => {
const currentTimestamp = await getLatestBlockTimestampAsync();
const timeUntilExpiration = signedOrders[0].expirationTimeSeconds.minus(currentTimestamp).toNumber();
await increaseTimeAndMineBlockAsync(timeUntilExpiration);
const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
expect(ordersInfo.length).to.be.equal(3);
_.forEach(signedOrders, (signedOrder, index) => {
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.EXPIRED;
const orderInfo = ordersInfo[index];
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
it('should get the correct information for multiple expired and partially filled orders', async () => {
const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2));
await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts });
const currentTimestamp = await getLatestBlockTimestampAsync();
const timeUntilExpiration = signedOrders[0].expirationTimeSeconds.minus(currentTimestamp).toNumber();
await increaseTimeAndMineBlockAsync(timeUntilExpiration);
const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
expect(ordersInfo.length).to.be.equal(3);
_.forEach(signedOrders, (signedOrder, index) => {
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2);
const expectedOrderStatus = OrderStatus.EXPIRED;
const orderInfo = ordersInfo[index];
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
it('should get the correct information for a mix of unfilled, partially filled, fully filled, cancelled, and expired orders', async () => {
const unfilledOrder = await orderFactory.newSignedOrderAsync();
const partiallyFilledOrder = await orderFactory.newSignedOrderAsync();
await exchangeWrapper.fillOrderAsync(partiallyFilledOrder, takerAddress, {
takerAssetFillAmount: partiallyFilledOrder.takerAssetAmount.div(2),
});
const fullyFilledOrder = await orderFactory.newSignedOrderAsync();
await exchangeWrapper.fillOrderAsync(fullyFilledOrder, takerAddress);
const cancelledOrder = await orderFactory.newSignedOrderAsync();
await exchangeWrapper.cancelOrderAsync(cancelledOrder, makerAddress);
const currentTimestamp = await getLatestBlockTimestampAsync();
const expiredOrder = await orderFactory.newSignedOrderAsync({
expirationTimeSeconds: new BigNumber(currentTimestamp),
});
signedOrders = [unfilledOrder, partiallyFilledOrder, fullyFilledOrder, cancelledOrder, expiredOrder];
const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
expect(ordersInfo.length).to.be.equal(5);
const expectedUnfilledOrderHash = orderHashUtils.getOrderHashHex(unfilledOrder);
const expectedUnfilledTakerAssetFilledAmount = new BigNumber(0);
const expectedUnfilledOrderStatus = OrderStatus.FILLABLE;
const unfilledOrderInfo = ordersInfo[0];
expect(unfilledOrderInfo.orderHash).to.be.equal(expectedUnfilledOrderHash);
expect(unfilledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
expectedUnfilledTakerAssetFilledAmount,
);
expect(unfilledOrderInfo.orderStatus).to.be.equal(expectedUnfilledOrderStatus);
const expectedPartialOrderHash = orderHashUtils.getOrderHashHex(partiallyFilledOrder);
const expectedPartialTakerAssetFilledAmount = partiallyFilledOrder.takerAssetAmount.div(2);
const expectedPartialOrderStatus = OrderStatus.FILLABLE;
const partialOrderInfo = ordersInfo[1];
expect(partialOrderInfo.orderHash).to.be.equal(expectedPartialOrderHash);
expect(partialOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
expectedPartialTakerAssetFilledAmount,
);
expect(partialOrderInfo.orderStatus).to.be.equal(expectedPartialOrderStatus);
const expectedFilledOrderHash = orderHashUtils.getOrderHashHex(fullyFilledOrder);
const expectedFilledTakerAssetFilledAmount = fullyFilledOrder.takerAssetAmount;
const expectedFilledOrderStatus = OrderStatus.FULLY_FILLED;
const filledOrderInfo = ordersInfo[2];
expect(filledOrderInfo.orderHash).to.be.equal(expectedFilledOrderHash);
expect(filledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
expectedFilledTakerAssetFilledAmount,
);
expect(filledOrderInfo.orderStatus).to.be.equal(expectedFilledOrderStatus);
const expectedCancelledOrderHash = orderHashUtils.getOrderHashHex(cancelledOrder);
const expectedCancelledTakerAssetFilledAmount = new BigNumber(0);
const expectedCancelledOrderStatus = OrderStatus.CANCELLED;
const cancelledOrderInfo = ordersInfo[3];
expect(cancelledOrderInfo.orderHash).to.be.equal(expectedCancelledOrderHash);
expect(cancelledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
expectedCancelledTakerAssetFilledAmount,
);
expect(cancelledOrderInfo.orderStatus).to.be.equal(expectedCancelledOrderStatus);
const expectedExpiredOrderHash = orderHashUtils.getOrderHashHex(expiredOrder);
const expectedExpiredTakerAssetFilledAmount = new BigNumber(0);
const expectedExpiredOrderStatus = OrderStatus.EXPIRED;
const expiredOrderInfo = ordersInfo[4];
expect(expiredOrderInfo.orderHash).to.be.equal(expectedExpiredOrderHash);
expect(expiredOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
expectedExpiredTakerAssetFilledAmount,
);
expect(expiredOrderInfo.orderStatus).to.be.equal(expectedExpiredOrderStatus);
});
});
});
}); // tslint:disable-line:max-file-line-count

View File

@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId, RevertReason, SignedOrder } from '@0xproject/types';
import { assetDataUtils } from '@0xproject/order-utils';
import { RevertReason, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -88,8 +88,8 @@ describe(ContractName.Forwarder, () => {
weth = new DummyERC20TokenContract(wethContract.abi, wethContract.address, provider);
erc20Wrapper.addDummyTokenContract(weth);
const wethAssetData = assetProxyUtils.encodeERC20AssetData(wethContract.address);
const zrxAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const wethAssetData = assetDataUtils.encodeERC20AssetData(wethContract.address);
const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
provider,
@@ -114,8 +114,8 @@ describe(ContractName.Forwarder, () => {
exchangeAddress: exchangeInstance.address,
makerAddress,
feeRecipientAddress,
makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress),
takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress),
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
@@ -131,7 +131,6 @@ describe(ContractName.Forwarder, () => {
exchangeInstance.address,
wethContract.address,
zrxToken.address,
AssetProxyId.ERC20,
zrxAssetData,
wethAssetData,
);
@@ -149,14 +148,14 @@ describe(ContractName.Forwarder, () => {
await blockchainLifecycle.startAsync();
feeProportion = 0;
erc20Balances = await erc20Wrapper.getBalancesAsync();
signedOrder = orderFactory.newSignedOrder();
signedOrder = await orderFactory.newSignedOrderAsync();
signedOrders = [signedOrder];
feeOrder = orderFactory.newSignedOrder({
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
feeOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
feeOrders = [feeOrder];
orderWithFee = orderFactory.newSignedOrder({
orderWithFee = await orderFactory.newSignedOrderAsync({
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
signedOrdersWithFee = [orderWithFee];
@@ -239,8 +238,8 @@ describe(ContractName.Forwarder, () => {
expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0));
});
it('should fill the order when token is ZRX with fees', async () => {
orderWithFee = orderFactory.newSignedOrder({
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
orderWithFee = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
signedOrdersWithFee = [orderWithFee];
@@ -261,8 +260,8 @@ describe(ContractName.Forwarder, () => {
expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0));
});
it('should fail if sent an ETH amount too high', async () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
const fillAmount = signedOrder.takerAssetAmount.times(2);
@@ -275,12 +274,12 @@ describe(ContractName.Forwarder, () => {
);
});
it('should fail if fee abstraction amount is too high', async () => {
orderWithFee = orderFactory.newSignedOrder({
orderWithFee = await orderFactory.newSignedOrderAsync({
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), DECIMALS_DEFAULT),
});
signedOrdersWithFee = [orderWithFee];
feeOrder = orderFactory.newSignedOrder({
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
feeOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
feeOrders = [feeOrder];
@@ -295,11 +294,11 @@ describe(ContractName.Forwarder, () => {
});
it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => {
const makerAssetId = erc721MakerAssetIds[0];
const erc721SignedOrder = orderFactory.newSignedOrder({
const erc721SignedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
const erc20SignedOrder = orderFactory.newSignedOrder();
const erc20SignedOrder = await orderFactory.newSignedOrderAsync();
signedOrders = [erc20SignedOrder, erc721SignedOrder];
const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
return expectTransactionFailedAsync(
@@ -419,8 +418,8 @@ describe(ContractName.Forwarder, () => {
expect(takerBalanceAfter).to.be.bignumber.eq(takerBalanceBefore.plus(makerAssetAmount));
});
it('should buy the exact amount of assets when buying zrx with fee abstraction', async () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
});
signedOrdersWithFee = [signedOrder];
@@ -448,8 +447,8 @@ describe(ContractName.Forwarder, () => {
expect(takerWeiBalanceAfter).to.be.bignumber.equal(takerWeiBalanceBefore.minus(expectedCostAfterGas));
});
it('throws if fees are higher than 5% when buying zrx', async () => {
const highFeeZRXOrder = orderFactory.newSignedOrder({
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
const highFeeZRXOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
makerAssetAmount: signedOrder.makerAssetAmount,
takerFee: signedOrder.makerAssetAmount.times(0.06),
});
@@ -471,7 +470,7 @@ describe(ContractName.Forwarder, () => {
);
});
it('throws if fees are higher than 5% when buying erc20', async () => {
const highFeeERC20Order = orderFactory.newSignedOrder({
const highFeeERC20Order = await orderFactory.newSignedOrderAsync({
takerFee: signedOrder.makerAssetAmount.times(0.06),
});
signedOrdersWithFee = [highFeeERC20Order];
@@ -545,9 +544,9 @@ describe(ContractName.Forwarder, () => {
describe('marketBuyTokensWithEth - ERC721', async () => {
it('buys ERC721 assets', async () => {
const makerAssetId = erc721MakerAssetIds[0];
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
feeOrders = [];
signedOrders = [signedOrder];
@@ -567,10 +566,10 @@ describe(ContractName.Forwarder, () => {
});
it('buys ERC721 assets with fee abstraction', async () => {
const makerAssetId = erc721MakerAssetIds[0];
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
signedOrders = [signedOrder];
const makerAssetAmount = new BigNumber(signedOrders.length);
@@ -589,10 +588,10 @@ describe(ContractName.Forwarder, () => {
});
it('buys ERC721 assets with fee abstraction and pays fee to fee recipient', async () => {
const makerAssetId = erc721MakerAssetIds[0];
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
signedOrders = [signedOrder];
feeProportion = 100;
@@ -631,15 +630,15 @@ describe(ContractName.Forwarder, () => {
it('buys multiple ERC721 assets with fee abstraction and pays fee to fee recipient', async () => {
const makerAssetId1 = erc721MakerAssetIds[0];
const makerAssetId2 = erc721MakerAssetIds[1];
const signedOrder1 = orderFactory.newSignedOrder({
const signedOrder1 = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId1),
});
const signedOrder2 = orderFactory.newSignedOrder({
const signedOrder2 = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId2),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId2),
});
signedOrders = [signedOrder1, signedOrder2];
feeProportion = 10;
@@ -666,23 +665,23 @@ describe(ContractName.Forwarder, () => {
// There are two fee orders, but the first fee order is partially filled while
// the Forwarding contract tx is in the mempool.
const erc721MakerAssetAmount = new BigNumber(1);
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: erc721MakerAssetAmount,
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
signedOrders = [signedOrder];
const firstFeeOrder = orderFactory.newSignedOrder({
const firstFeeOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
});
const secondFeeOrder = orderFactory.newSignedOrder({
const secondFeeOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
});
feeOrders = [firstFeeOrder, secondFeeOrder];
@@ -730,24 +729,24 @@ describe(ContractName.Forwarder, () => {
// There are two fee orders, but the first fee order is partially filled while
// the Forwarding contract tx is in the mempool.
const erc721MakerAssetAmount = new BigNumber(1);
signedOrder = orderFactory.newSignedOrder({
signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: erc721MakerAssetAmount,
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
const zrxMakerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT);
signedOrders = [signedOrder];
const firstFeeOrder = orderFactory.newSignedOrder({
const firstFeeOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: zrxMakerAssetAmount,
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
});
const secondFeeOrder = orderFactory.newSignedOrder({
const secondFeeOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: zrxMakerAssetAmount,
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT),
makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
makerAssetData: assetDataUtils.encodeERC20AssetData(zrxToken.address),
takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT),
});
feeOrders = [firstFeeOrder, secondFeeOrder];
@@ -779,11 +778,11 @@ describe(ContractName.Forwarder, () => {
});
it('throws when mixed ERC721 and ERC20 assets', async () => {
const makerAssetId = erc721MakerAssetIds[0];
const erc721SignedOrder = orderFactory.newSignedOrder({
const erc721SignedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
const erc20SignedOrder = orderFactory.newSignedOrder();
const erc20SignedOrder = await orderFactory.newSignedOrderAsync();
signedOrders = [erc721SignedOrder, erc20SignedOrder];
const makerAssetAmount = new BigNumber(signedOrders.length);
const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);
@@ -797,11 +796,11 @@ describe(ContractName.Forwarder, () => {
});
it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => {
const makerAssetId = erc721MakerAssetIds[0];
const erc721SignedOrder = orderFactory.newSignedOrder({
const erc721SignedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1),
makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
});
const erc20SignedOrder = orderFactory.newSignedOrder();
const erc20SignedOrder = await orderFactory.newSignedOrderAsync();
signedOrders = [erc20SignedOrder, erc721SignedOrder];
const makerAssetAmount = new BigNumber(signedOrders.length);
const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount);

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { generatePseudoRandomSalt } from '@0xproject/order-utils';
import { RevertReason } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import BN = require('bn.js');
@@ -12,6 +12,7 @@ import { artifacts } from '../utils/artifacts';
import { expectContractCallFailed } from '../utils/assertions';
import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
import { typeEncodingUtils } from '../utils/type_encoding_utils';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure();
@@ -74,20 +75,20 @@ describe('LibBytes', () => {
shortData = '0xffffaa';
const encodedShortData = ethUtil.toBuffer(shortData);
const shortDataLength = new BigNumber(encodedShortData.byteLength);
const encodedShortDataLength = assetProxyUtils.encodeUint256(shortDataLength);
const encodedShortDataLength = typeEncodingUtils.encodeUint256(shortDataLength);
shortTestBytesAsBuffer = Buffer.concat([encodedShortDataLength, encodedShortData]);
shortTestBytes = ethUtil.bufferToHex(shortTestBytesAsBuffer);
// Create test bytes one word in length
wordOfData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt()));
wordOfData = ethUtil.bufferToHex(typeEncodingUtils.encodeUint256(generatePseudoRandomSalt()));
const encodedWordOfData = ethUtil.toBuffer(wordOfData);
const wordOfDataLength = new BigNumber(encodedWordOfData.byteLength);
const encodedWordOfDataLength = assetProxyUtils.encodeUint256(wordOfDataLength);
const encodedWordOfDataLength = typeEncodingUtils.encodeUint256(wordOfDataLength);
wordOfTestBytesAsBuffer = Buffer.concat([encodedWordOfDataLength, encodedWordOfData]);
wordOfTestBytes = ethUtil.bufferToHex(wordOfTestBytesAsBuffer);
// Create long test bytes (combines short test bytes with word of test bytes)
longData = ethUtil.bufferToHex(Buffer.concat([encodedShortData, encodedWordOfData]));
const longDataLength = new BigNumber(encodedShortData.byteLength + encodedWordOfData.byteLength);
const encodedLongDataLength = assetProxyUtils.encodeUint256(longDataLength);
const encodedLongDataLength = typeEncodingUtils.encodeUint256(longDataLength);
longTestBytesAsBuffer = Buffer.concat([encodedLongDataLength, encodedShortData, encodedWordOfData]);
longTestBytes = ethUtil.bufferToHex(longTestBytesAsBuffer);
});

View File

@@ -18,9 +18,9 @@ import {
expectContractCreationFailedWithoutReason,
expectTransactionFailedWithoutReasonAsync,
} from '../utils/assertions';
import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
import { increaseTimeAndMineBlockAsync } from '../utils/increase_time';
import { MultiSigWrapper } from '../utils/multi_sig_wrapper';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
@@ -148,6 +148,25 @@ describe('AssetProxyOwner', () => {
});
});
describe('readBytes4', () => {
it('should revert if byte array has a length < 4', async () => {
const byteArrayLessThan4Bytes = '0x010101';
return expectContractCallFailedWithoutReasonAsync(
testAssetProxyOwner.publicReadBytes4.callAsync(byteArrayLessThan4Bytes, new BigNumber(0)),
);
});
it('should return the first 4 bytes of a byte array of arbitrary length', async () => {
const byteArrayLongerThan32Bytes =
'0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
const first4Bytes = await testAssetProxyOwner.publicReadBytes4.callAsync(
byteArrayLongerThan32Bytes,
new BigNumber(0),
);
const expectedFirst4Bytes = byteArrayLongerThan32Bytes.slice(0, 10);
expect(first4Bytes).to.equal(expectedFirst4Bytes);
});
});
describe('registerAssetProxy', () => {
it('should throw if not called by multisig', async () => {
const isRegistered = true;
@@ -238,8 +257,6 @@ describe('AssetProxyOwner', () => {
const registerAssetProxySubmitLog = registerAssetProxySubmitRes.logs[0] as LogWithDecodedArgs<
AssetProxyOwnerSubmissionEventArgs
>;
const registerAssetProxyTxId = registerAssetProxySubmitLog.args.transactionId;
await multiSigWrapper.confirmTransactionAsync(registerAssetProxyTxId, owners[1]);
const addAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(authorized);
const erc20AddAuthorizedAddressSubmitRes = await multiSigWrapper.submitTransactionAsync(
@@ -257,9 +274,12 @@ describe('AssetProxyOwner', () => {
>;
const erc721AddAuthorizedAddressSubmitLog = erc721AddAuthorizedAddressSubmitRes
.logs[0] as LogWithDecodedArgs<AssetProxyOwnerSubmissionEventArgs>;
const registerAssetProxyTxId = registerAssetProxySubmitLog.args.transactionId;
const erc20AddAuthorizedAddressTxId = erc20AddAuthorizedAddressSubmitLog.args.transactionId;
const erc721AddAuthorizedAddressTxId = erc721AddAuthorizedAddressSubmitLog.args.transactionId;
await multiSigWrapper.confirmTransactionAsync(registerAssetProxyTxId, owners[1]);
await multiSigWrapper.confirmTransactionAsync(erc20AddAuthorizedAddressTxId, owners[1]);
await multiSigWrapper.confirmTransactionAsync(erc721AddAuthorizedAddressTxId, owners[1]);
await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());

View File

@@ -9,9 +9,9 @@ import {
} from '../../generated_contract_wrappers/multi_sig_wallet_with_time_lock';
import { artifacts } from '../utils/artifacts';
import { expectTransactionFailedWithoutReasonAsync } from '../utils/assertions';
import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
import { increaseTimeAndMineBlockAsync } from '../utils/increase_time';
import { MultiSigWrapper } from '../utils/multi_sig_wrapper';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';

View File

@@ -1,4 +1,4 @@
import { assetProxyUtils } from '@0xproject/order-utils';
import { assetDataUtils } from '@0xproject/order-utils';
import { AssetProxyId } from '@0xproject/types';
import { BigNumber, errorUtils } from '@0xproject/utils';
import * as _ from 'lodash';
@@ -17,7 +17,7 @@ interface ProxyIdToAssetWrappers {
* the logic that uses it does not need to care what standard a token belongs to.
*/
export class AssetWrapper {
private _proxyIdToAssetWrappers: ProxyIdToAssetWrappers;
private readonly _proxyIdToAssetWrappers: ProxyIdToAssetWrappers;
constructor(assetWrappers: AbstractAssetWrapper[]) {
this._proxyIdToAssetWrappers = {};
_.each(assetWrappers, assetWrapper => {
@@ -26,7 +26,7 @@ export class AssetWrapper {
});
}
public async getBalanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const proxyId = assetProxyUtils.decodeAssetDataId(assetData);
const proxyId = assetDataUtils.decodeAssetProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20: {
const erc20Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC20Wrapper;
@@ -35,7 +35,7 @@ export class AssetWrapper {
}
case AssetProxyId.ERC721: {
const assetWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
const assetProxyData = assetProxyUtils.decodeERC721AssetData(assetData);
const assetProxyData = assetDataUtils.decodeERC721AssetData(assetData);
const isOwner = await assetWrapper.isOwnerAsync(
userAddress,
assetProxyData.tokenAddress,
@@ -49,7 +49,7 @@ export class AssetWrapper {
}
}
public async setBalanceAsync(userAddress: string, assetData: string, desiredBalance: BigNumber): Promise<void> {
const proxyId = assetProxyUtils.decodeAssetDataId(assetData);
const proxyId = assetDataUtils.decodeAssetProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20: {
const erc20Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC20Wrapper;
@@ -61,7 +61,7 @@ export class AssetWrapper {
throw new Error(`Balance for ERC721 token can only be set to 0 or 1. Got: ${desiredBalance}`);
}
const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
const assetProxyData = assetProxyUtils.decodeERC721AssetData(assetData);
const assetProxyData = assetDataUtils.decodeERC721AssetData(assetData);
const doesTokenExist = erc721Wrapper.doesTokenExistAsync(
assetProxyData.tokenAddress,
assetProxyData.tokenId,
@@ -107,7 +107,7 @@ export class AssetWrapper {
}
}
public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const proxyId = assetProxyUtils.decodeAssetDataId(assetData);
const proxyId = assetDataUtils.decodeAssetProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20: {
const erc20Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC20Wrapper;
@@ -116,7 +116,7 @@ export class AssetWrapper {
}
case AssetProxyId.ERC721: {
const assetWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
const erc721ProxyData = assetProxyUtils.decodeERC721AssetData(assetData);
const erc721ProxyData = assetDataUtils.decodeERC721AssetData(assetData);
const isProxyApprovedForAll = await assetWrapper.isProxyApprovedForAllAsync(
userAddress,
erc721ProxyData.tokenAddress,
@@ -141,7 +141,7 @@ export class AssetWrapper {
assetData: string,
desiredAllowance: BigNumber,
): Promise<void> {
const proxyId = assetProxyUtils.decodeAssetDataId(assetData);
const proxyId = assetDataUtils.decodeAssetProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20: {
const erc20Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC20Wrapper;
@@ -159,7 +159,7 @@ export class AssetWrapper {
);
}
const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
const assetProxyData = assetProxyUtils.decodeERC721AssetData(assetData);
const assetProxyData = assetDataUtils.decodeERC721AssetData(assetData);
const doesTokenExist = await erc721Wrapper.doesTokenExistAsync(
assetProxyData.tokenAddress,

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