Refactor 0x.js to simply re-export it's own sub-dependencies rather then wrapping them in a ZeroEx object

This commit is contained in:
Fabio Berger
2018-08-13 18:10:11 -07:00
parent 283175df98
commit b10cba600d
17 changed files with 61 additions and 10672 deletions

View File

@@ -15,30 +15,19 @@
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && yarn build:all && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"watch_without_deps": "tsc -w",
"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 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",
"rebuild_and_test": "run-s build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"clean": "shx rm -rf _bundles lib test_temp scripts src/generated_contract_wrappers",
"clean": "shx rm -rf _bundles lib scripts src/generated_contract_wrappers",
"build:umd:prod": "NODE_ENV=production webpack",
"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",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
"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": {
"contracts": "ZRXToken",
"postpublish": {
"assets": [
"packages/0x.js/_bundles/index.js",
@@ -102,6 +91,7 @@
"@0xproject/base-contract": "^1.0.4",
"@0xproject/contract-wrappers": "^1.0.1-rc.2",
"@0xproject/order-utils": "^1.0.1-rc.2",
"@0xproject/order-watcher": "1.0.1-rc.2",
"@0xproject/sol-compiler": "^1.0.4",
"@0xproject/subproviders": "^1.0.4",
"@0xproject/types": "^1.0.1-rc.3",

View File

@@ -1,279 +0,0 @@
import { assert } from '@0xproject/assert';
import {
ContractWrappers,
ContractWrappersConfig,
ERC20ProxyWrapper,
ERC20TokenWrapper,
ERC721ProxyWrapper,
ERC721TokenWrapper,
EtherTokenWrapper,
ExchangeWrapper,
} from '@0xproject/contract-wrappers';
import {
assetDataUtils,
ecSignOrderHashAsync,
generatePseudoRandomSalt,
isValidSignatureAsync,
orderHashUtils,
} from '@0xproject/order-utils';
// 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, ERC20AssetData, ERC721AssetData, Order, SignedOrder, SignerType } 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';
/**
* The ZeroEx class is the single entry-point into the 0x.js library. It contains all of the library's functionality
* and all calls to the library should be made through a ZeroEx instance.
*/
export class ZeroEx {
/**
* When creating an order without a specified taker or feeRecipient you must supply the Solidity
* address null type (as opposed to Javascripts `null`, `undefined` or empty string). We expose
* this constant for your convenience.
*/
public static NULL_ADDRESS = constants.NULL_ADDRESS;
/**
* An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract.
*/
public exchange: ExchangeWrapper;
/**
* An instance of the ERC20TokenWrapper class containing methods for interacting with any ERC20 token smart contract.
*/
public erc20Token: ERC20TokenWrapper;
/**
* An instance of the ERC721TokenWrapper class containing methods for interacting with any ERC721 token smart contract.
*/
public erc721Token: ERC721TokenWrapper;
/**
* An instance of the EtherTokenWrapper class containing methods for interacting with the
* wrapped ETH ERC20 token smart contract.
*/
public etherToken: EtherTokenWrapper;
/**
* An instance of the ERC20ProxyWrapper class containing methods for interacting with the
* ERC20 proxy smart contract.
*/
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
* and will not collide with other outstanding orders that are identical in all other parameters.
* @return A pseudo-random 256-bit number that can be used as a salt.
*/
public static generatePseudoRandomSalt(): BigNumber {
return generatePseudoRandomSalt();
}
/**
* 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 orderHashUtils.getOrderHashHex(order);
}
/**
* Checks if the supplied hex encoded order hash is valid.
* Note: Valid means it has the expected format, not that an order with the orderHash exists.
* Use this method when processing orderHashes submitted as user input.
* @param orderHash Hex encoded orderHash.
* @return Whether the supplied orderHash has the expected format.
*/
public static isValidOrderHash(orderHash: string): boolean {
return orderHashUtils.isValidOrderHash(orderHash);
}
/**
* A unit amount is defined as the amount of a token above the specified decimal places (integer part).
* E.g: If a currency has 18 decimal places, 1e18 or one quintillion of the currency is equivalent
* to 1 unit.
* @param amount The amount in baseUnits that you would like converted to units.
* @param decimals The number of decimal places the unit amount has.
* @return The amount in units.
*/
public static toUnitAmount(amount: BigNumber, decimals: number): BigNumber {
assert.isValidBaseUnitAmount('amount', amount);
assert.isNumber('decimals', decimals);
const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
return unitAmount;
}
/**
* A baseUnit is defined as the smallest denomination of a token. An amount expressed in baseUnits
* is the amount expressed in the smallest denomination.
* E.g: 1 unit of a token with 18 decimal places is expressed in baseUnits as 1000000000000000000
* @param amount The amount of units that you would like converted to baseUnits.
* @param decimals The number of decimal places the unit amount has.
* @return The amount in baseUnits.
*/
public static toBaseUnitAmount(amount: BigNumber, decimals: number): BigNumber {
assert.isBigNumber('amount', amount);
assert.isNumber('decimals', decimals);
const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, decimals);
return baseUnitAmount;
}
/**
* Encodes an ERC20 token address into a hex encoded assetData string, usable in the makerAssetData or
* takerAssetData fields in a 0x order.
* @param tokenAddress The ERC20 token address to encode
* @return The hex encoded assetData string
*/
public static encodeERC20AssetData(tokenAddress: string): string {
return assetDataUtils.encodeERC20AssetData(tokenAddress);
}
/**
* Decodes an ERC20 assetData hex string into it's corresponding ERC20 tokenAddress & assetProxyId
* @param assetData Hex encoded assetData string to decode
* @return An object containing the decoded tokenAddress & assetProxyId
*/
public static decodeERC20AssetData(assetData: string): ERC20AssetData {
return assetDataUtils.decodeERC20AssetData(assetData);
}
/**
* Encodes an ERC721 token address into a hex encoded assetData string, usable in the makerAssetData or
* takerAssetData fields in a 0x order.
* @param tokenAddress The ERC721 token address to encode
* @param tokenId The ERC721 tokenId to encode
* @return The hex encoded assetData string
*/
public static encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber): string {
return assetDataUtils.encodeERC721AssetData(tokenAddress, tokenId);
}
/**
* Decodes an ERC721 assetData hex string into it's corresponding ERC721 tokenAddress, tokenId & assetProxyId
* @param assetData Hex encoded assetData string to decode
* @return An object containing the decoded tokenAddress, tokenId & assetProxyId
*/
public static decodeERC721AssetData(assetData: string): ERC721AssetData {
return assetDataUtils.decodeERC721AssetData(assetData);
}
/**
* Decode and return the assetProxyId from the assetData
* @param assetData Hex encoded assetData string to decode
* @return The assetProxyId
*/
public static decodeAssetProxyId(assetData: string): AssetProxyId {
return assetDataUtils.decodeAssetProxyId(assetData);
}
/**
* Decode any assetData into it's corresponding assetData object
* @param assetData Hex encoded assetData string to decode
* @return Either a ERC20 or ERC721 assetData object
*/
public static decodeAssetDataOrThrow(assetData: string): ERC20AssetData | ERC721AssetData {
return assetDataUtils.decodeAssetDataOrThrow(assetData);
}
/**
* Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library.
* @param provider The Provider instance you would like the 0x.js library to use for interacting with
* the Ethereum network.
* @param config The configuration object. Look up the type for the description.
* @return An instance of the 0x.js ZeroEx class.
*/
constructor(provider: Provider, config: ContractWrappersConfig) {
assert.isWeb3Provider('provider', provider);
this._contractWrappers = new ContractWrappers(provider, config);
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.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.
* @param provider The Web3Provider you would like the 0x.js library to use from now on.
* @param networkId The id of the network your provider is connected to
*/
public setProvider(provider: Provider, networkId: number): void {
this._contractWrappers.setProvider(provider, networkId);
}
/**
* Get the provider instance currently used by 0x.js
* @return Web3 provider instance
*/
public getProvider(): Provider {
return this._contractWrappers.getProvider();
}
/**
* Get user Ethereum addresses available through the supplied web3 provider available for sending transactions.
* @return An array of available user Ethereum addresses.
*/
public async getAvailableAddressesAsync(): Promise<string[]> {
// Hack: Get Web3Wrapper from ContractWrappers
const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
const availableAddresses = await web3Wrapper.getAvailableAddressesAsync();
return availableAddresses;
}
/**
* Signs an orderHash and returns it's elliptic curve signature.
* This method currently supports TestRPC, Geth and Parity above and below V1.6.6
* @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 signerType the signer type that will perform the `eth_sign` operation. E.g Default, Metamask, Ledger or Trezor.
* Some implementations exhibit different behaviour. Default will assume a spec compliant eth_sign implementation.
* This parameter is defaulted to `SignerType.Default`.
* @return A hex encoded string of the Elliptic curve signature parameters generated by signing the orderHash and signature type.
*/
public async ecSignOrderHashAsync(
orderHash: string,
signerAddress: string,
signerType: SignerType = SignerType.Default,
): Promise<string> {
const signature = await ecSignOrderHashAsync(
this._contractWrappers.getProvider(),
orderHash,
signerAddress,
signerType,
);
return signature;
}
/**
* Waits for a transaction to be mined and returns the transaction receipt.
* @param txHash Transaction hash
* @param pollingIntervalMs How often (in ms) should we check if the transaction is mined.
* @param timeoutMs How long (in ms) to poll for transaction mined until aborting.
* @return Transaction receipt with decoded log args.
*/
public async awaitTransactionMinedAsync(
txHash: string,
pollingIntervalMs: number = 1000,
timeoutMs?: number,
): Promise<TransactionReceiptWithDecodedLogs> {
// Hack: Get Web3Wrapper from ContractWrappers
const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper;
const transactionReceiptWithDecodedLogs = await web3Wrapper.awaitTransactionMinedAsync(
txHash,
pollingIntervalMs,
timeoutMs,
);
return transactionReceiptWithDecodedLogs;
}
}

View File

@@ -1,7 +0,0 @@
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,47 +1,35 @@
export { ZeroEx } from './0x';
export { Web3ProviderEngine, RPCSubprovider } from '@0xproject/subproviders';
export {
ExchangeContractErrs,
Order,
SignedOrder,
SignerType,
ECSignature,
OrderStateValid,
OrderStateInvalid,
OrderState,
Token,
ERC20AssetData,
ERC721AssetData,
AssetProxyId,
} from '@0xproject/types';
export {
BlockParamLiteral,
FilterObject,
BlockParam,
LogWithDecodedArgs,
ContractEventArg,
Provider,
TransactionReceipt,
TransactionReceiptWithDecodedLogs,
} from 'ethereum-types';
export {
assetDataUtils,
ecSignOrderHashAsync,
generatePseudoRandomSalt,
isValidSignatureAsync,
orderHashUtils,
} from '@0xproject/order-utils';
export {
ContractWrappers,
ERC20TokenWrapper,
ERC721TokenWrapper,
EtherTokenWrapper,
ExchangeWrapper,
ERC20ProxyWrapper,
ERC721ProxyWrapper,
ForwarderWrapper,
ContractWrappersError,
EventCallback,
ContractEvent,
IndexedFilterValues,
BlockRange,
OrderFillRequest,
ContractEventArgs,
ContractWrappersConfig,
MethodOpts,
OrderTransactionOpts,
TransactionOpts,
LogEvent,
DecodedLogEvent,
OnOrderStateChangeCallback,
ContractWrappersError,
OrderStatus,
OrderInfo,
WETH9Events,
WETH9WithdrawalEventArgs,
WETH9ApprovalEventArgs,
@@ -56,11 +44,43 @@ export {
ERC721TokenApprovalForAllEventArgs,
ERC721TokenTransferEventArgs,
ERC721TokenEvents,
ERC721TokenEventArgs,
ExchangeCancelUpToEventArgs,
ExchangeAssetProxyRegisteredEventArgs,
ExchangeFillEventArgs,
ExchangeCancelEventArgs,
ExchangeEventArgs,
ContractWrappersConfig,
OrderInfo,
ExchangeEvents,
} from '@0xproject/contract-wrappers';
export { OrderWatcher, OnOrderStateChangeCallback, OrderWatcherConfig } from '@0xproject/order-watcher';
export { Web3ProviderEngine, RPCSubprovider, Callback, ErrorCallback, Subprovider } from '@0xproject/subproviders';
export { BigNumber } from '@0xproject/utils';
export {
Order,
SignedOrder,
ECSignature,
OrderStateValid,
OrderStateInvalid,
OrderState,
AssetProxyId,
ExchangeContractErrs,
SignerType,
Token,
ERC20AssetData,
ERC721AssetData,
} from '@0xproject/types';
export {
BlockParamLiteral,
FilterObject,
BlockParam,
ContractEventArg,
LogWithDecodedArgs,
Provider,
TransactionReceipt,
TransactionReceiptWithDecodedLogs,
} from 'ethereum-types';

View File

@@ -1,5 +0,0 @@
export const zeroExConfigSchema = {
id: '/ZeroExConfig',
oneOf: [{ $ref: '/ZeroExPrivateNetworkConfig' }, { $ref: '/ZeroExPublicNetworkConfig' }],
type: 'object',
};

View File

@@ -1,35 +0,0 @@
export const zeroExPrivateNetworkConfigSchema = {
id: '/ZeroExPrivateNetworkConfig',
properties: {
networkId: {
type: 'number',
minimum: 1,
},
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {
pollingIntervalMs: {
type: 'number',
minimum: 0,
},
numConfirmations: {
type: 'number',
minimum: 0,
},
},
},
},
type: 'object',
required: [
'networkId',
'zrxContractAddress',
'exchangeContractAddress',
'erc20ProxyContractAddress',
'erc721ProxyContractAddress',
],
};

View File

@@ -1,43 +0,0 @@
const networkNameToId: { [networkName: string]: number } = {
mainnet: 1,
ropsten: 3,
rinkeby: 4,
kovan: 42,
ganache: 50,
};
export const zeroExPublicNetworkConfigSchema = {
id: '/ZeroExPublicNetworkConfig',
properties: {
networkId: {
type: 'number',
enum: [
networkNameToId.mainnet,
networkNameToId.ropsten,
networkNameToId.rinkeby,
networkNameToId.kovan,
networkNameToId.ganache,
],
},
gasPrice: { $ref: '/Number' },
zrxContractAddress: { $ref: '/Address' },
exchangeContractAddress: { $ref: '/Address' },
erc20ProxyContractAddress: { $ref: '/Address' },
erc721ProxyContractAddress: { $ref: '/Address' },
orderWatcherConfig: {
type: 'object',
properties: {
pollingIntervalMs: {
type: 'number',
minimum: 0,
},
numConfirmations: {
type: 'number',
minimum: 0,
},
},
},
},
type: 'object',
required: ['networkId'],
};

View File

@@ -1,7 +0,0 @@
export enum InternalZeroExError {
NoAbiDecoder = 'NO_ABI_DECODER',
ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY',
WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY',
}
// tslint:disable:max-file-line-count

View File

@@ -1,4 +0,0 @@
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
TESTRPC_NETWORK_ID: 50,
};

View File

@@ -1,150 +0,0 @@
import { ContractWrappers } from '@0xproject/contract-wrappers';
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import 'mocha';
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 { provider, web3Wrapper } from './utils/web3_wrapper';
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
chaiSetup.configure();
const expect = chai.expect;
describe('ZeroEx library', () => {
let zeroEx: ZeroEx;
before(async () => {
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
};
zeroEx = new ZeroEx(provider, config);
});
describe('#setProvider', () => {
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
// Instantiate the contract instances with the current provider
await (zeroEx.exchange as any)._getExchangeContractAsync();
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
// Add property to newProvider so that we can differentiate it from old provider
(provider as any).zeroExTestId = 1;
zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID);
// Check that contractInstances with old provider are removed after provider update
expect((zeroEx.exchange as any)._exchangeContractIfExists).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');
});
});
describe('#isValidSignature', () => {
const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const ethSignSignature =
'0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
const bytes32Zeros = '0x0000000000000000000000000000000000000000000000000000000000000000';
it("should return false if the data doesn't pertain to the signature & address", async () => {
return expect(
(zeroEx.exchange as any).isValidSignatureAsync(bytes32Zeros, 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).isValidSignatureAsync(dataHex, validUnrelatedAddress, ethSignSignature),
).to.become(false);
});
it("should return false if the signature doesn't pertain to the dataHex & address", async () => {
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).isValidSignatureAsync(dataHex, address, ethSignSignature)).to.become(
true,
);
});
});
describe('#toUnitAmount', () => {
it('should throw if invalid baseUnit amount supplied as argument', () => {
const invalidBaseUnitAmount = new BigNumber(1000000000.4);
const decimals = 6;
expect(() => ZeroEx.toUnitAmount(invalidBaseUnitAmount, decimals)).to.throw(
'amount should be in baseUnits (no decimals), found value: 1000000000.4',
);
});
it('Should return the expected unit amount for the decimals passed in', () => {
const baseUnitAmount = new BigNumber(1000000000);
const decimals = 6;
const unitAmount = ZeroEx.toUnitAmount(baseUnitAmount, decimals);
const expectedUnitAmount = new BigNumber(1000);
expect(unitAmount).to.be.bignumber.equal(expectedUnitAmount);
});
});
describe('#toBaseUnitAmount', () => {
it('Should return the expected base unit amount for the decimals passed in', () => {
const unitAmount = new BigNumber(1000);
const decimals = 6;
const baseUnitAmount = ZeroEx.toBaseUnitAmount(unitAmount, decimals);
const expectedUnitAmount = new BigNumber(1000000000);
expect(baseUnitAmount).to.be.bignumber.equal(expectedUnitAmount);
});
it('should throw if unitAmount has more decimals then specified as the max decimal precision', () => {
const unitAmount = new BigNumber(0.823091);
const decimals = 5;
expect(() => ZeroEx.toBaseUnitAmount(unitAmount, decimals)).to.throw(
'Invalid unit amount: 0.823091 - Too many decimal places',
);
});
});
describe('#awaitTransactionMinedAsync', () => {
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
it('returns transaction receipt with decoded logs', async () => {
const availableAddresses = await zeroEx.getAvailableAddressesAsync();
const coinbase = availableAddresses[0];
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<ERC20TokenApprovalEventArgs>;
expect(log.event).to.be.equal(ERC20TokenEvents.Approval);
expect(log.args._owner).to.be.equal(coinbase);
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', () => {
it('allows to specify exchange contract address', async () => {
const zeroExConfig = {
exchangeContractAddress: ZeroEx.NULL_ADDRESS,
networkId: constants.TESTRPC_NETWORK_ID,
};
const zeroExWithWrongExchangeAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongExchangeAddress.exchange.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
});
it('allows to specify erc20Proxy contract address', async () => {
const zeroExConfig = {
erc20ProxyContractAddress: ZeroEx.NULL_ADDRESS,
networkId: constants.TESTRPC_NETWORK_ID,
};
const zeroExWithWrongERC20ProxyAddress = new ZeroEx(provider, zeroExConfig);
expect(zeroExWithWrongERC20ProxyAddress.erc20Proxy.getContractAddress()).to.be.equal(ZeroEx.NULL_ADDRESS);
});
});
});

View File

@@ -1,17 +0,0 @@
import { devConstants } from '@0xproject/dev-utils';
import { runV2MigrationsAsync } from '@0xproject/migrations';
import { provider } from './utils/web3_wrapper';
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); // tslint:disable-line:no-invalid-this
const txDefaults = {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
const artifactsDir = `../migrations/artifacts/2.0.0`;
await runV2MigrationsAsync(provider, artifactsDir, txDefaults);
});

View File

@@ -1,13 +0,0 @@
import * as chai from 'chai';
import chaiAsPromised = require('chai-as-promised');
import ChaiBigNumber = require('chai-bignumber');
import * as dirtyChai from 'dirty-chai';
export const chaiSetup = {
configure(): void {
chai.config.includeStack = true;
chai.use(ChaiBigNumber());
chai.use(dirtyChai);
chai.use(chaiAsPromised);
},
};

View File

@@ -1,9 +0,0 @@
export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
ROPSTEN_NETWORK_ID: 3,
KOVAN_NETWORK_ID: 42,
TESTRPC_NETWORK_ID: 50,
KOVAN_RPC_URL: 'https://kovan.infura.io/',
ROPSTEN_RPC_URL: 'https://ropsten.infura.io/',
ZRX_DECIMALS: 18,
};

View File

@@ -1,9 +0,0 @@
import { artifacts } from '../../src/artifacts';
import { constants } from './constants';
export const tokenUtils = {
getProtocolTokenAddress(): string {
return artifacts.ZRXToken.networks[constants.TESTRPC_NETWORK_ID].address;
},
};

View File

@@ -1,12 +0,0 @@
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, txDefaults };