Refactor 0x.js to V2

This commit is contained in:
Fabio Berger 2018-07-11 18:53:50 +02:00
parent abf87a643d
commit b6ac132c78
14 changed files with 160 additions and 145 deletions

View File

@ -31,7 +31,7 @@
"stage_docs": "wsrun docs:stage $PKG --fast-exit --parallel --exclude-missing", "stage_docs": "wsrun docs:stage $PKG --fast-exit --parallel --exclude-missing",
"lint": "wsrun lint $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.", "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 -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"
}, },
"config": { "config": {
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic" "mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"

View File

@ -18,9 +18,10 @@
"watch_without_deps": "yarn pre_build && tsc -w", "watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && yarn build:all && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "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;", "build:all": "run-p build:umd:prod build:commonjs; exit 0;",
"pre_build": "run-s generate_contract_wrappers copy_artifacts", "pre_build": "run-s update_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts", "copy_artifacts": "copyfiles -u 2 './src/artifacts/**/*.json' ./lib/src/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", "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/**/*", "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
"test:circleci": "run-s test:coverage", "test:circleci": "run-s test:coverage",
"test": "yarn run_mocha", "test": "yarn run_mocha",
@ -29,7 +30,7 @@
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"clean": "shx rm -rf _bundles lib test_temp scripts src/generated_contract_wrappers", "clean": "shx rm -rf _bundles lib test_temp scripts src/generated_contract_wrappers",
"build:umd:prod": "NODE_ENV=production webpack", "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", "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", "manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "node scripts/stage_docs.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" "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": { "config": {
"compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry", "contracts": "ZRXToken",
"postpublish": { "postpublish": {
"assets": [ "assets": [
"packages/0x.js/_bundles/index.js", "packages/0x.js/_bundles/index.js",
@ -101,13 +102,14 @@
"dependencies": { "dependencies": {
"@0xproject/assert": "^0.2.13", "@0xproject/assert": "^0.2.13",
"@0xproject/base-contract": "^0.3.5", "@0xproject/base-contract": "^0.3.5",
"@0xproject/contract-wrappers": "^0.0.5", "@0xproject/contract-wrappers": "^0.1.0",
"@0xproject/order-utils": "^0.0.8", "@0xproject/order-utils": "^1.0.0",
"@0xproject/sol-compiler": "^0.5.3", "@0xproject/sol-compiler": "^0.5.3",
"@0xproject/types": "^0.8.2", "@0xproject/types": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.2", "@0xproject/typescript-typings": "^0.4.2",
"@0xproject/utils": "^0.7.2", "@0xproject/utils": "^0.7.2",
"@0xproject/web3-wrapper": "^0.7.2", "@0xproject/web3-wrapper": "^0.7.2",
"ethereum-types": "^0.0.2",
"ethers": "3.0.22", "ethers": "3.0.22",
"lodash": "^4.17.4" "lodash": "^4.17.4"
}, },

View File

@ -4,19 +4,22 @@ import {
ContractWrappersConfig, ContractWrappersConfig,
ERC20ProxyWrapper, ERC20ProxyWrapper,
ERC20TokenWrapper, ERC20TokenWrapper,
ERC721ProxyWrapper,
ERC721TokenWrapper,
EtherTokenWrapper, EtherTokenWrapper,
ExchangeWrapper, ExchangeWrapper,
} from '@0xproject/contract-wrappers'; } from '@0xproject/contract-wrappers';
import { import {
ecSignOrderHashAsync,
generatePseudoRandomSalt, generatePseudoRandomSalt,
getOrderHashHex, isValidSignatureAsync,
isValidOrderHash, MessagePrefixOpts,
isValidSignature, orderHashUtils,
signOrderHashAsync,
} from '@0xproject/order-utils'; } from '@0xproject/order-utils';
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types'; import { ECSignature, Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { constants } from './utils/constants'; import { constants } from './utils/constants';
@ -36,21 +39,28 @@ export class ZeroEx {
*/ */
public exchange: ExchangeWrapper; public exchange: ExchangeWrapper;
/** /**
* An instance of the ERC20TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
*/ */
public erc20Token: ERC20TokenWrapper;
/** /**
* An instance of the 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 * An instance of the EtherTokenWrapper class containing methods for interacting with the
* wrapped ETH ERC20 token smart contract. * wrapped ETH ERC20 token smart contract.
*/ */
public etherToken: EtherTokenWrapper; public etherToken: EtherTokenWrapper;
/** /**
* An instance of the TokenTransferProxyWrapper class containing methods for interacting with the * An instance of the ERC20ProxyWrapper class containing methods for interacting with the
* tokenTransferProxy smart contract. * ERC20 proxy smart contract.
*/ */
public proxy: TokenTransferProxyWrapper; public erc20Proxy: ERC20ProxyWrapper;
/**
* An instance of the ERC721ProxyWrapper class containing methods for interacting with the
* ERC721 proxy smart contract.
*/
public erc721Proxy: ERC721ProxyWrapper;
private _contractWrappers: ContractWrappers; private _contractWrappers: ContractWrappers;
/** /**
* Generates a pseudo-random 256-bit salt. * Generates a pseudo-random 256-bit salt.
@ -61,24 +71,13 @@ export class ZeroEx {
public static generatePseudoRandomSalt(): BigNumber { public static generatePseudoRandomSalt(): BigNumber {
return generatePseudoRandomSalt(); 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. * Computes the orderHash for a supplied order.
* @param order An object that conforms to the Order or SignedOrder interface definitions. * @param order An object that conforms to the Order or SignedOrder interface definitions.
* @return The resulting orderHash from hashing the supplied order. * @return The resulting orderHash from hashing the supplied order.
*/ */
public static getOrderHashHex(order: Order | SignedOrder): string { public static getOrderHashHex(order: Order | SignedOrder): string {
return getOrderHashHex(order); return orderHashUtils.getOrderHashHex(order);
} }
/** /**
* Checks if the supplied hex encoded order hash is valid. * Checks if the supplied hex encoded order hash is valid.
@ -88,7 +87,7 @@ export class ZeroEx {
* @return Whether the supplied orderHash has the expected format. * @return Whether the supplied orderHash has the expected format.
*/ */
public static isValidOrderHash(orderHash: string): boolean { 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). * A unit amount is defined as the amount of a token above the specified decimal places (integer part).
@ -129,11 +128,30 @@ export class ZeroEx {
assert.isWeb3Provider('provider', provider); assert.isWeb3Provider('provider', provider);
this._contractWrappers = new ContractWrappers(provider, config); this._contractWrappers = new ContractWrappers(provider, config);
this.proxy = this._contractWrappers.proxy; this.erc20Proxy = this._contractWrappers.erc20Proxy;
this.token = this._contractWrappers.token; this.erc721Proxy = this._contractWrappers.erc721Proxy;
this.erc20Token = this._contractWrappers.erc20Token;
this.erc721Token = this._contractWrappers.erc721Token;
this.exchange = this._contractWrappers.exchange; this.exchange = this._contractWrappers.exchange;
this.etherToken = this._contractWrappers.etherToken; this.etherToken = this._contractWrappers.etherToken;
} }
/**
* Verifies that the provided signature is valid according to the 0x Protocol smart contracts
* @param provider The Web3Provider to use. Some signature types involve checking contract state.
* @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 * 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. * subscriptions so you will need to re-subscribe to all events relevant to your app after this call.
@ -166,23 +184,21 @@ export class ZeroEx {
* @param orderHash Hex encoded orderHash to sign. * @param orderHash Hex encoded orderHash to sign.
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address * @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. * must be available via the Provider supplied to 0x.js.
* @param shouldAddPersonalMessagePrefix Some signers add the personal message prefix `\x19Ethereum Signed Message` * @param MessagePrefixOpts Options regarding the desired prefix and whether to add it before calling `eth_sign`
* 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.
* @return An object containing the Elliptic curve signature parameters generated by signing the orderHash. * @return An object containing the Elliptic curve signature parameters generated by signing the orderHash.
*/ */
public async signOrderHashAsync( public async ecSignOrderHashAsync(
orderHash: string, orderHash: string,
signerAddress: string, signerAddress: string,
shouldAddPersonalMessagePrefix: boolean, messagePrefixOpts: MessagePrefixOpts,
): Promise<ECSignature> { ): Promise<ECSignature> {
return signOrderHashAsync( const signature = await ecSignOrderHashAsync(
this._contractWrappers.getProvider(), this._contractWrappers.getProvider(),
orderHash, orderHash,
signerAddress, signerAddress,
shouldAddPersonalMessagePrefix, messagePrefixOpts,
); );
return signature;
} }
/** /**
* Waits for a transaction to be mined and returns the transaction receipt. * Waits for a transaction to be mined and returns the transaction receipt.

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,
};

View File

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

View File

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

View File

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

View File

@ -5,11 +5,11 @@ import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
import 'mocha'; import 'mocha';
import { ApprovalContractEventArgs, LogWithDecodedArgs, TokenEvents, ZeroEx } from '../src'; import { ERC20TokenApprovalEventArgs, ERC20TokenEvents, LogWithDecodedArgs, ZeroEx } from '../src';
import { chaiSetup } from './utils/chai_setup'; import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants'; import { constants } from './utils/constants';
import { TokenUtils } from './utils/token_utils'; import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper'; import { provider, web3Wrapper } from './utils/web3_wrapper';
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
@ -45,40 +45,34 @@ describe('ZeroEx library', () => {
}); });
}); });
describe('#isValidSignature', () => { 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 dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const signature = { const ethSignSignature =
v: 27, '0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
r: '0x61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33',
s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254',
};
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
it("should return false if the data doesn't pertain to the signature & address", async () => { it("should return false if the data doesn't pertain to the signature & address", async () => {
return expect( return expect((zeroEx.exchange as any).isValidSignatureAsync('0x0', address, ethSignSignature)).to.become(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync('0x0', signature, address), false,
).to.become(false); );
}); });
it("should return false if the address doesn't pertain to the signature & data", async () => { it("should return false if the address doesn't pertain to the signature & data", async () => {
const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42'; const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42';
return expect( return expect(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync( (zeroEx.exchange as any).isValidSignatureAsync(dataHex, validUnrelatedAddress, ethSignSignature),
dataHex,
signature,
validUnrelatedAddress,
),
).to.become(false); ).to.become(false);
}); });
it("should return false if the signature doesn't pertain to the dataHex & address", async () => { it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
const wrongSignature = _.assign({}, signature, { v: 28 }); const signatureArray = ethSignSignature.split('');
return expect( // tslint:disable-next-line:custom-no-magic-numbers
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address), signatureArray[5] = 'C'; // V = 28, instead of 27
).to.become(false); 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 () => { it('should return true if the signature does pertain to the dataHex & address', async () => {
return expect( return expect((zeroEx.exchange as any).isValidSignatureAsync(dataHex, address, ethSignSignature)).to.become(
(zeroEx.exchange as any)._isValidSignatureUsingContractCallAsync(dataHex, signature, address), true,
).to.become(true); );
}); });
}); });
describe('#toUnitAmount', () => { describe('#toUnitAmount', () => {
@ -123,18 +117,16 @@ describe('ZeroEx library', () => {
it('returns transaction receipt with decoded logs', async () => { it('returns transaction receipt with decoded logs', async () => {
const availableAddresses = await zeroEx.getAvailableAddressesAsync(); const availableAddresses = await zeroEx.getAvailableAddressesAsync();
const coinbase = availableAddresses[0]; const coinbase = availableAddresses[0];
const tokens = await zeroEx.tokenRegistry.getTokensAsync(); const zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
const tokenUtils = new TokenUtils(tokens); const erc20ProxyAddress = zeroEx.erc20Proxy.getContractAddress();
const zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address; const txHash = await zeroEx.erc20Token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const proxyAddress = zeroEx.proxy.getContractAddress();
const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash); const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ApprovalContractEventArgs>; const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ERC20TokenApprovalEventArgs>;
expect(log.event).to.be.equal(TokenEvents.Approval); expect(log.event).to.be.equal(ERC20TokenEvents.Approval);
expect(log.args._owner).to.be.equal(coinbase); expect(log.args._owner).to.be.equal(coinbase);
expect(log.args._spender).to.be.equal(proxyAddress); expect(log.args._spender).to.be.equal(erc20ProxyAddress);
expect(log.args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); expect(log.args._value).to.be.bignumber.equal(zeroEx.erc20Token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
}); });
}); });
describe('#config', () => { describe('#config', () => {
@ -146,15 +138,13 @@ describe('ZeroEx library', () => {
const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig); const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS); 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 = { const zeroExConfig = {
tokenRegistryContractAddress: ZeroEx.NULL_ADDRESS, erc20ProxyContractAddress: ZeroEx.NULL_ADDRESS,
networkId: constants.TESTRPC_NETWORK_ID, networkId: constants.TESTRPC_NETWORK_ID,
}; };
const zeroExWithWrongTokenRegistryAddress = new ZeroEx(provider, zeroExConfig); const zeroExWithWrongERC20ProxyAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongTokenRegistryAddress.tokenRegistry.getContractAddress()).to.be.equal( expect(zeroExWithWrongERC20ProxyAddress.erc20Proxy.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
ZeroEx.NULL_ADDRESS,
);
}); });
}); });
}); });

View File

@ -1,5 +1,5 @@
import { devConstants } from '@0xproject/dev-utils'; import { devConstants } from '@0xproject/dev-utils';
import { runV1MigrationsAsync } from '@0xproject/migrations'; import { runV2MigrationsAsync } from '@0xproject/migrations';
import { provider } from './utils/web3_wrapper'; import { provider } from './utils/web3_wrapper';
@ -12,6 +12,6 @@ before('migrate contracts', async function(): Promise<void> {
gas: devConstants.GAS_LIMIT, gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS, from: devConstants.TESTRPC_FIRST_ADDRESS,
}; };
const artifactsDir = `../migrations/artifacts/1.0.0`; const artifactsDir = `../migrations/artifacts/2.0.0`;
await runV1MigrationsAsync(provider, artifactsDir, txDefaults); await runV2MigrationsAsync(provider, artifactsDir, txDefaults);
}); });

View File

@ -1,34 +1,12 @@
import { Token } from '@0xproject/types'; import { generatePseudoRandomSalt } from '@0xproject/order-utils';
import * as _ from 'lodash'; import { BigNumber } from '@0xproject/utils';
import { InternalZeroExError } from '../../src/types'; import { artifacts } from '../../src/artifacts';
const PROTOCOL_TOKEN_SYMBOL = 'ZRX'; import { constants } from './constants';
const WETH_TOKEN_SYMBOL = 'WETH';
export class TokenUtils { export const tokenUtils = {
private _tokens: Token[]; getProtocolTokenAddress(): string {
constructor(tokens: Token[]) { return artifacts.ZRXToken.networks[constants.TESTRPC_NETWORK_ID].address;
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;
}
}

View File

@ -1,8 +1,12 @@
import { web3Factory } from '@0xproject/dev-utils'; import { devConstants, web3Factory } from '@0xproject/dev-utils';
import { Provider } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; 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 provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true });
const web3Wrapper = new Web3Wrapper(provider); const web3Wrapper = new Web3Wrapper(provider);
export { provider, web3Wrapper }; export { provider, web3Wrapper, txDefaults };

View File

@ -2,6 +2,9 @@ export { ContractWrappers } from './contract_wrappers';
export { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper'; export { ERC20TokenWrapper } from './contract_wrappers/erc20_token_wrapper';
export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper';
export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper'; export { ERC20ProxyWrapper } from './contract_wrappers/erc20_proxy_wrapper';
export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper';
export { ERC721TokenWrapper } from './contract_wrappers/erc721_token_wrapper';
export { ERC721ProxyWrapper } from './contract_wrappers/erc721_proxy_wrapper';
export { export {
ContractWrappersError, ContractWrappersError,

View File

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

View File

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