diff options
Diffstat (limited to 'packages')
163 files changed, 10365 insertions, 1406 deletions
diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json index bdc575903..5e4a726b1 100644 --- a/packages/0x.js/CHANGELOG.json +++ b/packages/0x.js/CHANGELOG.json @@ -1,5 +1,19 @@ [ { + "version": "0.38.0", + "changes": [ + { + "note": "Renamed createOrderStateWatcher to createOrderWatcherAsync since it is now async", + "pr": 579 + }, + { + "note": + "Renamed ZeroExError to ContractWrappersErrors since they now lives in the @0xproject/contract-wrappers subpackage", + "pr": 579 + } + ] + }, + { "timestamp": 1525477860, "version": "0.37.2", "changes": [ diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json index a23e01938..d1091b9e9 100644 --- a/packages/0x.js/package.json +++ b/packages/0x.js/package.json @@ -16,7 +16,7 @@ "prebuild": "run-s clean generate_contract_wrappers", "build": "run-p build:umd:prod build:commonjs; exit 0;", "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'", - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "lint": "tslint --project .", "test:circleci": "run-s test:coverage", "test": "run-s clean test:commonjs", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", @@ -43,6 +43,13 @@ "docPublishConfigs": { "extraFileIncludes": [ "../types/src/index.ts", + "../contract-wrappers/src/types.ts", + "../contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts", + "../contract-wrappers/src/contract_wrappers/exchange_wrapper.ts", + "../contract-wrappers/src/contract_wrappers/token_registry_wrapper.ts", + "../contract-wrappers/src/contract_wrappers/token_transfer_proxy_wrapper.ts", + "../contract-wrappers/src/contract_wrappers/token_wrapper.ts", + "../order-watcher/src/order_watcher/order_watcher.ts", "./src/contract_wrappers/generated/ether_token.ts", "./src/contract_wrappers/generated/token.ts", "./src/contract_wrappers/generated/exchange.ts" @@ -65,15 +72,11 @@ "@0xproject/dev-utils": "^0.4.1", "@0xproject/migrations": "^0.0.5", "@0xproject/monorepo-scripts": "^0.1.19", - "@0xproject/subproviders": "^0.10.1", "@0xproject/tslint-config": "^0.4.17", - "@types/bintrees": "^1.0.2", "@types/lodash": "4.14.104", "@types/mocha": "^2.2.42", "@types/node": "^8.0.53", - "@types/request": "2.47.0", "@types/sinon": "^2.2.2", - "@types/uuid": "^3.4.2", "awesome-typescript-loader": "^3.1.3", "chai": "^4.0.1", "chai-as-promised": "^7.1.0", @@ -86,35 +89,26 @@ "nyc": "^11.0.1", "opn-cli": "^3.1.0", "prettier": "^1.11.1", - "request": "^2.81.0", "shx": "^0.2.2", "sinon": "^4.0.0", "source-map-support": "^0.5.0", "tslint": "5.8.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1", - "web3-provider-engine": "^14.0.4", "webpack": "^3.1.0" }, "dependencies": { "@0xproject/assert": "^0.2.9", "@0xproject/base-contract": "^0.3.1", - "@0xproject/json-schemas": "^0.7.23", + "@0xproject/contract-wrappers": "^0.0.1", + "@0xproject/order-watcher": "^0.0.1", "@0xproject/order-utils": "^0.0.4", "@0xproject/types": "^0.6.3", "@0xproject/typescript-typings": "^0.3.1", "@0xproject/utils": "^0.6.1", "@0xproject/web3-wrapper": "^0.6.3", - "bintrees": "^1.0.2", - "bn.js": "^4.11.8", - "ethereumjs-abi": "^0.6.4", - "ethereumjs-blockstream": "^2.0.6", - "ethereumjs-util": "^5.1.1", "ethers": "^3.0.15", - "js-sha3": "^0.7.0", - "lodash": "^4.17.4", - "uuid": "^3.1.0", - "web3": "^0.20.0" + "lodash": "^4.17.4" }, "publishConfig": { "access": "public" diff --git a/packages/0x.js/src/0x.ts b/packages/0x.js/src/0x.ts index 78f9f6beb..9bcb0dddc 100644 --- a/packages/0x.js/src/0x.ts +++ b/packages/0x.js/src/0x.ts @@ -1,4 +1,13 @@ -import { schemas, SchemaValidator } from '@0xproject/json-schemas'; +import { assert } from '@0xproject/assert'; +import { + ContractWrappers, + EtherTokenWrapper, + ExchangeWrapper, + TokenRegistryWrapper, + TokenTransferProxyWrapper, + TokenWrapper, + ContractWrappersConfig, +} from '@0xproject/contract-wrappers'; import { generatePseudoRandomSalt, getOrderHashHex, @@ -6,27 +15,13 @@ import { isValidSignature, signOrderHashAsync, } from '@0xproject/order-utils'; +import { OrderWatcher, OrderWatcherConfig } from '@0xproject/order-watcher'; import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types'; -import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils'; +import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; -import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; -import { artifacts } from './artifacts'; -import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; -import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; -import { TokenRegistryWrapper } from './contract_wrappers/token_registry_wrapper'; -import { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper'; -import { TokenWrapper } from './contract_wrappers/token_wrapper'; -import { OrderStateWatcher } from './order_watcher/order_state_watcher'; -import { zeroExConfigSchema } from './schemas/zero_ex_config_schema'; -import { zeroExPrivateNetworkConfigSchema } from './schemas/zero_ex_private_network_config_schema'; -import { zeroExPublicNetworkConfigSchema } from './schemas/zero_ex_public_network_config_schema'; -import { OrderStateWatcherConfig, ZeroExConfig, ZeroExError } from './types'; -import { assert } from './utils/assert'; import { constants } from './utils/constants'; -import { decorators } from './utils/decorators'; -import { utils } from './utils/utils'; /** * The ZeroEx class is the single entry-point into the 0x.js library. It contains all of the library's functionality @@ -62,7 +57,7 @@ export class ZeroEx { * tokenTransferProxy smart contract. */ public proxy: TokenTransferProxyWrapper; - private _web3Wrapper: Web3Wrapper; + private _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 @@ -136,40 +131,15 @@ export class ZeroEx { * @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: ZeroExConfig) { + constructor(provider: Provider, config: ContractWrappersConfig) { assert.isWeb3Provider('provider', provider); - assert.doesConformToSchema('config', config, zeroExConfigSchema, [ - zeroExPrivateNetworkConfigSchema, - zeroExPublicNetworkConfigSchema, - ]); - const artifactJSONs = _.values(artifacts); - const abiArrays = _.map(artifactJSONs, artifact => artifact.abi); - const defaults = { - gasPrice: config.gasPrice, - }; - this._web3Wrapper = new Web3Wrapper(provider, defaults); - _.forEach(abiArrays, abi => { - this._web3Wrapper.abiDecoder.addABI(abi); - }); - this.proxy = new TokenTransferProxyWrapper( - this._web3Wrapper, - config.networkId, - config.tokenTransferProxyContractAddress, - ); - this.token = new TokenWrapper(this._web3Wrapper, config.networkId, this.proxy); - this.exchange = new ExchangeWrapper( - this._web3Wrapper, - config.networkId, - this.token, - config.exchangeContractAddress, - config.zrxContractAddress, - ); - this.tokenRegistry = new TokenRegistryWrapper( - this._web3Wrapper, - config.networkId, - config.tokenRegistryContractAddress, - ); - this.etherToken = new EtherTokenWrapper(this._web3Wrapper, config.networkId, this.token); + this._contractWrappers = new ContractWrappers(provider, config); + + this.proxy = this._contractWrappers.proxy; + this.token = this._contractWrappers.token; + this.exchange = this._contractWrappers.exchange; + this.tokenRegistry = this._contractWrappers.tokenRegistry; + this.etherToken = this._contractWrappers.etherToken; } /** * Sets a new web3 provider for 0x.js. Updating the provider will stop all @@ -178,31 +148,23 @@ export class ZeroEx { * @param networkId The id of the network your provider is connected to */ public setProvider(provider: Provider, networkId: number): void { - this._web3Wrapper.setProvider(provider); - (this.exchange as any)._invalidateContractInstances(); - (this.exchange as any)._setNetworkId(networkId); - (this.tokenRegistry as any)._invalidateContractInstance(); - (this.tokenRegistry as any)._setNetworkId(networkId); - (this.token as any)._invalidateContractInstances(); - (this.token as any)._setNetworkId(networkId); - (this.proxy as any)._invalidateContractInstance(); - (this.proxy as any)._setNetworkId(networkId); - (this.etherToken as any)._invalidateContractInstance(); - (this.etherToken as any)._setNetworkId(networkId); + this._contractWrappers.setProvider(provider, networkId); } /** * Get the provider instance currently used by 0x.js * @return Web3 provider instance */ public getProvider(): Provider { - return this._web3Wrapper.getProvider(); + 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[]> { - const availableAddresses = await this._web3Wrapper.getAvailableAddressesAsync(); + // Hack: Get Web3Wrapper from ZeroExContract + const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper; + const availableAddresses = await web3Wrapper.getAvailableAddressesAsync(); return availableAddresses; } /** @@ -223,7 +185,7 @@ export class ZeroEx { shouldAddPersonalMessagePrefix: boolean, ): Promise<ECSignature> { return signOrderHashAsync( - this._web3Wrapper.getProvider(), + this._contractWrappers.getProvider(), orderHash, signerAddress, shouldAddPersonalMessagePrefix, @@ -241,7 +203,9 @@ export class ZeroEx { pollingIntervalMs = 1000, timeoutMs?: number, ): Promise<TransactionReceiptWithDecodedLogs> { - const transactionReceiptWithDecodedLogs = await this._web3Wrapper.awaitTransactionMinedAsync( + // Hack: Get Web3Wrapper from ZeroExContract + const web3Wrapper: Web3Wrapper = (this._contractWrappers as any)._web3Wrapper; + const transactionReceiptWithDecodedLogs = await web3Wrapper.awaitTransactionMinedAsync( txHash, pollingIntervalMs, timeoutMs, @@ -249,22 +213,17 @@ export class ZeroEx { return transactionReceiptWithDecodedLogs; } /** - * Instantiates and returns a new OrderStateWatcher instance. + * 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 OrderStateWatcher class. - */ - public createOrderStateWatcher(config?: OrderStateWatcherConfig) { - return new OrderStateWatcher(this._web3Wrapper, this.token, this.exchange, config); - } - /* - * HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from - * an `ExchangeWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders, creating a dependency cycle. - * In order to break this - we create this function here and pass it as a parameter to the `TokenWrapper` - * and `ProxyWrapper`. - */ - private async _getTokenTransferProxyAddressAsync(): Promise<string> { - const tokenTransferProxyAddress = await (this.exchange as any)._getTokenTransferProxyAddressAsync(); - return tokenTransferProxyAddress; + * @return An instance of the 0x.js OrderWatcher class. + */ + public async createOrderWatcherAsync(config?: OrderWatcherConfig): Promise<OrderWatcher> { + // Hack: Get Web3Wrapper from ZeroExContract + 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; } } diff --git a/packages/0x.js/src/artifacts.ts b/packages/0x.js/src/artifacts.ts deleted file mode 100644 index a91d9ae1f..000000000 --- a/packages/0x.js/src/artifacts.ts +++ /dev/null @@ -1,18 +0,0 @@ -import * as DummyTokenArtifact from './compact_artifacts/DummyToken.json'; -import * as EtherTokenArtifact from './compact_artifacts/EtherToken.json'; -import * as ExchangeArtifact from './compact_artifacts/Exchange.json'; -import * as TokenArtifact from './compact_artifacts/Token.json'; -import * as TokenRegistryArtifact from './compact_artifacts/TokenRegistry.json'; -import * as TokenTransferProxyArtifact from './compact_artifacts/TokenTransferProxy.json'; -import * as ZRXArtifact from './compact_artifacts/ZRX.json'; -import { Artifact } from './types'; - -export const artifacts = { - ZRXArtifact: (ZRXArtifact as any) as Artifact, - DummyTokenArtifact: (DummyTokenArtifact as any) as Artifact, - TokenArtifact: (TokenArtifact as any) as Artifact, - ExchangeArtifact: (ExchangeArtifact as any) as Artifact, - EtherTokenArtifact: (EtherTokenArtifact as any) as Artifact, - TokenRegistryArtifact: (TokenRegistryArtifact as any) as Artifact, - TokenTransferProxyArtifact: (TokenTransferProxyArtifact as any) as Artifact, -}; diff --git a/packages/0x.js/src/index.ts b/packages/0x.js/src/index.ts index 3b973bd54..c79dbdb77 100644 --- a/packages/0x.js/src/index.ts +++ b/packages/0x.js/src/index.ts @@ -1,61 +1,51 @@ export { ZeroEx } from './0x'; export { - ZeroExError, - EventCallback, - ExchangeContractErrs, - ContractEvent, - Token, - IndexedFilterValues, - BlockRange, - OrderCancellationRequest, - OrderFillRequest, - ContractEventArgs, - ZeroExConfig, - MethodOpts, - OrderTransactionOpts, - TransactionOpts, - LogEvent, - DecodedLogEvent, - EventWatcherCallback, - OnOrderStateChangeCallback, - OrderStateValid, - OrderStateInvalid, - OrderState, -} from './types'; - -export { BlockParamLiteral, FilterObject, BlockParam, ContractEventArg, + ExchangeContractErrs, LogWithDecodedArgs, Order, Provider, SignedOrder, ECSignature, + OrderStateValid, + OrderStateInvalid, + OrderState, + Token, TransactionReceipt, TransactionReceiptWithDecodedLogs, } from '@0xproject/types'; export { + EventCallback, + ContractEvent, + IndexedFilterValues, + BlockRange, + OrderCancellationRequest, + OrderFillRequest, + ContractEventArgs, + MethodOpts, + OrderTransactionOpts, + TransactionOpts, + LogEvent, + DecodedLogEvent, + OnOrderStateChangeCallback, + ContractWrappersError, EtherTokenContractEventArgs, WithdrawalContractEventArgs, DepositContractEventArgs, EtherTokenEvents, -} from './contract_wrappers/generated/ether_token'; - -export { TransferContractEventArgs, ApprovalContractEventArgs, TokenContractEventArgs, TokenEvents, -} from './contract_wrappers/generated/token'; - -export { LogErrorContractEventArgs, LogCancelContractEventArgs, LogFillContractEventArgs, ExchangeContractEventArgs, ExchangeEvents, -} from './contract_wrappers/generated/exchange'; + ContractWrappersConfig, +} from '@0xproject/contract-wrappers'; diff --git a/packages/0x.js/src/types.ts b/packages/0x.js/src/types.ts index ae9f98c5f..a8cf62c64 100644 --- a/packages/0x.js/src/types.ts +++ b/packages/0x.js/src/types.ts @@ -1,276 +1,20 @@ -import { BigNumber } from '@0xproject/utils'; - import { BlockParam, BlockParamLiteral, ContractAbi, ContractEventArg, + ExchangeContractErrs, FilterObject, - LogEntryEvent, LogWithDecodedArgs, Order, + OrderState, SignedOrder, } from '@0xproject/types'; -import * as Web3 from 'web3'; - -import { EtherTokenContractEventArgs, EtherTokenEvents } from './contract_wrappers/generated/ether_token'; -import { ExchangeContractEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange'; -import { TokenContractEventArgs, TokenEvents } from './contract_wrappers/generated/token'; - -export enum ZeroExError { - ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST', - ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST', - EtherTokenContractDoesNotExist = 'ETHER_TOKEN_CONTRACT_DOES_NOT_EXIST', - TokenTransferProxyContractDoesNotExist = 'TOKEN_TRANSFER_PROXY_CONTRACT_DOES_NOT_EXIST', - TokenRegistryContractDoesNotExist = 'TOKEN_REGISTRY_CONTRACT_DOES_NOT_EXIST', - TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST', - UnhandledError = 'UNHANDLED_ERROR', - UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES', - ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK', - InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER', - InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER', - InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT', - InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL', - InvalidJump = 'INVALID_JUMP', - OutOfGas = 'OUT_OF_GAS', - NoNetworkId = 'NO_NETWORK_ID', - SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND', - SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT', -} - export enum InternalZeroExError { NoAbiDecoder = 'NO_ABI_DECODER', ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY', WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY', } -export type OrderAddresses = [string, string, string, string, string]; - -export type OrderValues = [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber, BigNumber]; - -export type LogEvent = LogEntryEvent; -export interface DecodedLogEvent<ArgsType> { - isRemoved: boolean; - log: LogWithDecodedArgs<ArgsType>; -} - -export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void; -export type EventWatcherCallback = (err: null | Error, log?: LogEvent) => void; - -export enum ExchangeContractErrCodes { - ERROR_FILL_EXPIRED, // Order has already expired - ERROR_FILL_NO_VALUE, // Order has already been fully filled or cancelled - ERROR_FILL_TRUNCATION, // Rounding error too large - ERROR_FILL_BALANCE_ALLOWANCE, // Insufficient balance or allowance for token transfer - ERROR_CANCEL_EXPIRED, // Order has already expired - ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled -} - -export enum ExchangeContractErrs { - OrderFillExpired = 'ORDER_FILL_EXPIRED', - OrderCancelExpired = 'ORDER_CANCEL_EXPIRED', - OrderCancelAmountZero = 'ORDER_CANCEL_AMOUNT_ZERO', - OrderAlreadyCancelledOrFilled = 'ORDER_ALREADY_CANCELLED_OR_FILLED', - OrderFillAmountZero = 'ORDER_FILL_AMOUNT_ZERO', - OrderRemainingFillAmountZero = 'ORDER_REMAINING_FILL_AMOUNT_ZERO', - OrderFillRoundingError = 'ORDER_FILL_ROUNDING_ERROR', - FillBalanceAllowanceError = 'FILL_BALANCE_ALLOWANCE_ERROR', - InsufficientTakerBalance = 'INSUFFICIENT_TAKER_BALANCE', - InsufficientTakerAllowance = 'INSUFFICIENT_TAKER_ALLOWANCE', - InsufficientMakerBalance = 'INSUFFICIENT_MAKER_BALANCE', - InsufficientMakerAllowance = 'INSUFFICIENT_MAKER_ALLOWANCE', - InsufficientTakerFeeBalance = 'INSUFFICIENT_TAKER_FEE_BALANCE', - InsufficientTakerFeeAllowance = 'INSUFFICIENT_TAKER_FEE_ALLOWANCE', - InsufficientMakerFeeBalance = 'INSUFFICIENT_MAKER_FEE_BALANCE', - InsufficientMakerFeeAllowance = 'INSUFFICIENT_MAKER_FEE_ALLOWANCE', - TransactionSenderIsNotFillOrderTaker = 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER', - MultipleMakersInSingleCancelBatchDisallowed = 'MULTIPLE_MAKERS_IN_SINGLE_CANCEL_BATCH_DISALLOWED', - InsufficientRemainingFillAmount = 'INSUFFICIENT_REMAINING_FILL_AMOUNT', - MultipleTakerTokensInFillUpToDisallowed = 'MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED', - BatchOrdersMustHaveSameExchangeAddress = 'BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS', - BatchOrdersMustHaveAtLeastOneItem = 'BATCH_ORDERS_MUST_HAVE_AT_LEAST_ONE_ITEM', -} - -export interface ContractEvent { - logIndex: number; - transactionIndex: number; - transactionHash: string; - blockHash: string; - blockNumber: number; - address: string; - type: string; - event: string; - args: ContractEventArgs; -} - -export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs; - -// [address, name, symbol, decimals, ipfsHash, swarmHash] -export type TokenMetadata = [string, string, string, number, string, string]; - -export interface Token { - name: string; - address: string; - symbol: string; - decimals: number; -} - -export interface TxOpts { - from: string; - gas?: number; - value?: BigNumber; - gasPrice?: BigNumber; -} - -export interface TokenAddressBySymbol { - [symbol: string]: string; -} - -export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents; - -export interface IndexedFilterValues { - [index: string]: ContractEventArg; -} - -export interface BlockRange { - fromBlock: BlockParam; - toBlock: BlockParam; -} - -export type DoneCallback = (err?: Error) => void; - -export interface OrderCancellationRequest { - order: Order | SignedOrder; - takerTokenCancelAmount: BigNumber; -} - -export interface OrderFillRequest { - signedOrder: SignedOrder; - takerTokenFillAmount: BigNumber; -} - -export type AsyncMethod = (...args: any[]) => Promise<any>; -export type SyncMethod = (...args: any[]) => any; - -/** - * orderExpirationCheckingIntervalMs: How often to check for expired orders. Default=50. - * eventPollingIntervalMs: How often to poll the Ethereum node for new events. Default=200. - * expirationMarginMs: Amount of time before order expiry that you'd like to be notified - * of an orders expiration. Default=0. - * cleanupJobIntervalMs: How often to run a cleanup job which revalidates all the orders. Default=1hr. - * stateLayer: Optional blockchain state layer OrderWatcher will monitor for new events. Default=latest. - */ -export interface OrderStateWatcherConfig { - orderExpirationCheckingIntervalMs?: number; - eventPollingIntervalMs?: number; - expirationMarginMs?: number; - cleanupJobIntervalMs?: number; - stateLayer: BlockParamLiteral; -} - -/** - * networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 3-ropsten, 4-rinkeby, 42-kovan, 50-testrpc) - * gasPrice: Gas price to use with every transaction - * exchangeContractAddress: The address of an exchange contract to use - * zrxContractAddress: The address of the ZRX contract to use - * tokenRegistryContractAddress: The address of a token registry contract to use - * tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use - * orderWatcherConfig: All the configs related to the orderWatcher - */ -export interface ZeroExConfig { - networkId: number; - gasPrice?: BigNumber; - exchangeContractAddress?: string; - zrxContractAddress?: string; - tokenRegistryContractAddress?: string; - tokenTransferProxyContractAddress?: string; - orderWatcherConfig?: OrderStateWatcherConfig; -} - -export type ArtifactContractName = 'ZRX' | 'TokenTransferProxy' | 'TokenRegistry' | 'Token' | 'Exchange' | 'EtherToken'; - -export interface Artifact { - contract_name: ArtifactContractName; - abi: ContractAbi; - networks: { - [networkId: number]: { - address: string; - }; - }; -} - -/** - * expectedFillTakerTokenAmount: If specified, the validation method will ensure that the - * supplied order maker has a sufficient allowance/balance to fill this amount of the order's - * takerTokenAmount. If not specified, the validation method ensures that the maker has a sufficient - * allowance/balance to fill the entire remaining order amount. - */ -export interface ValidateOrderFillableOpts { - expectedFillTakerTokenAmount?: BigNumber; -} - -/** - * defaultBlock: The block up to which to query the blockchain state. Setting this to a historical block number - * let's the user query the blockchain's state at an arbitrary point in time. In order for this to work, the - * backing Ethereum node must keep the entire historical state of the chain (e.g setting `--pruning=archive` - * flag when running Parity). - */ -export interface MethodOpts { - defaultBlock?: BlockParam; -} - -/** - * gasPrice: Gas price in Wei to use for a transaction - * gasLimit: The amount of gas to send with a transaction - */ -export interface TransactionOpts { - gasPrice?: BigNumber; - gasLimit?: number; -} - -/** - * shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before - * broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default=true. - */ -export interface OrderTransactionOpts extends TransactionOpts { - shouldValidate?: boolean; -} - -export enum TradeSide { - Maker = 'maker', - Taker = 'taker', -} - -export enum TransferType { - Trade = 'trade', - Fee = 'fee', -} - -export interface OrderRelevantState { - makerBalance: BigNumber; - makerProxyAllowance: BigNumber; - makerFeeBalance: BigNumber; - makerFeeProxyAllowance: BigNumber; - filledTakerTokenAmount: BigNumber; - cancelledTakerTokenAmount: BigNumber; - remainingFillableMakerTokenAmount: BigNumber; - remainingFillableTakerTokenAmount: BigNumber; -} - -export interface OrderStateValid { - isValid: true; - orderHash: string; - orderRelevantState: OrderRelevantState; -} - -export interface OrderStateInvalid { - isValid: false; - orderHash: string; - error: ExchangeContractErrs; -} - -export type OrderState = OrderStateValid | OrderStateInvalid; - -export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void; // tslint:disable:max-file-line-count diff --git a/packages/0x.js/src/utils/constants.ts b/packages/0x.js/src/utils/constants.ts index 07da6745d..7cd5eb574 100644 --- a/packages/0x.js/src/utils/constants.ts +++ b/packages/0x.js/src/utils/constants.ts @@ -3,9 +3,4 @@ import { BigNumber } from '@0xproject/utils'; export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', TESTRPC_NETWORK_ID: 50, - INVALID_JUMP_PATTERN: 'invalid JUMP at', - OUT_OF_GAS_PATTERN: 'out of gas', - INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string', - UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), - DEFAULT_BLOCK_POLLING_INTERVAL: 1000, }; diff --git a/packages/0x.js/test/0x.js_test.ts b/packages/0x.js/test/0x.js_test.ts index 6dccdaea7..ce2fa34bf 100644 --- a/packages/0x.js/test/0x.js_test.ts +++ b/packages/0x.js/test/0x.js_test.ts @@ -1,3 +1,4 @@ +import { ContractWrappers } from '@0xproject/contract-wrappers'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; @@ -41,9 +42,9 @@ describe('ZeroEx library', () => { expect((zeroEx.exchange as any)._exchangeContractIfExists).to.be.undefined(); expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined(); - // Check that all nested web3 wrapper instances return the updated provider - const nestedWeb3WrapperProvider = (zeroEx as any)._web3Wrapper.getProvider(); - expect(nestedWeb3WrapperProvider.zeroExTestId).to.be.a('number'); + // 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(); diff --git a/packages/0x.js/test/assert_test.ts b/packages/0x.js/test/assert_test.ts deleted file mode 100644 index e69de29bb..000000000 --- a/packages/0x.js/test/assert_test.ts +++ /dev/null diff --git a/packages/0x.js/test/utils/report_callback_errors.ts b/packages/0x.js/test/utils/report_callback_errors.ts deleted file mode 100644 index 27c9745c9..000000000 --- a/packages/0x.js/test/utils/report_callback_errors.ts +++ /dev/null @@ -1,66 +0,0 @@ -import * as chai from 'chai'; -import * as _ from 'lodash'; - -import { DoneCallback } from '../../src/types'; - -const expect = chai.expect; - -export const reportNoErrorCallbackErrors = (done: DoneCallback, expectToBeCalledOnce = true) => { - return <T>(f?: (value: T) => void) => { - const wrapped = (value: T) => { - if (_.isUndefined(f)) { - done(); - return; - } - try { - f(value); - if (expectToBeCalledOnce) { - done(); - } - } catch (err) { - done(err); - } - }; - return wrapped; - }; -}; - -export const reportNodeCallbackErrors = (done: DoneCallback, expectToBeCalledOnce = true) => { - return <T>(f?: (value: T) => void) => { - const wrapped = (error: Error | null, value: T | undefined) => { - if (!_.isNull(error)) { - done(error); - } else { - if (_.isUndefined(f)) { - done(); - return; - } - try { - f(value as T); - if (expectToBeCalledOnce) { - done(); - } - } catch (err) { - done(err); - } - } - }; - return wrapped; - }; -}; - -export const assertNodeCallbackError = (done: DoneCallback, errMsg: string) => { - const wrapped = <T>(error: Error | null, value: T | undefined) => { - if (_.isNull(error)) { - done(new Error('Expected callback to receive an error')); - } else { - try { - expect(error.message).to.be.equal(errMsg); - done(); - } catch (err) { - done(err); - } - } - }; - return wrapped; -}; diff --git a/packages/0x.js/test/utils/token_utils.ts b/packages/0x.js/test/utils/token_utils.ts index d3fc22ff4..fe4886ba4 100644 --- a/packages/0x.js/test/utils/token_utils.ts +++ b/packages/0x.js/test/utils/token_utils.ts @@ -1,6 +1,7 @@ +import { Token } from '@0xproject/types'; import * as _ from 'lodash'; -import { InternalZeroExError, Token } from '../../src/types'; +import { InternalZeroExError } from '../../src/types'; const PROTOCOL_TOKEN_SYMBOL = 'ZRX'; const WETH_TOKEN_SYMBOL = 'WETH'; diff --git a/packages/abi-gen/package.json b/packages/abi-gen/package.json index 0ee7e1979..82184a596 100644 --- a/packages/abi-gen/package.json +++ b/packages/abi-gen/package.json @@ -6,7 +6,7 @@ "types": "lib/index.d.ts", "scripts": { "build:watch": "tsc -w", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "clean": "shx rm -rf lib scripts", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "manual:postpublish": "yarn build; node ./scripts/postpublish.js" diff --git a/packages/assert/package.json b/packages/assert/package.json index e02e018ae..f86bbb33f 100644 --- a/packages/assert/package.json +++ b/packages/assert/package.json @@ -8,7 +8,7 @@ "build:watch": "tsc -w", "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib test_temp scripts", - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "lint": "tslint --project .", "run_mocha": "mocha lib/test/**/*_test.js --exit", "prepublishOnly": "run-p build", "test": "run-s clean build run_mocha", diff --git a/packages/connect/package.json b/packages/connect/package.json index efc61178f..2930de98e 100644 --- a/packages/connect/package.json +++ b/packages/connect/package.json @@ -16,7 +16,7 @@ "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib test_temp scripts", "copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures", - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "lint": "tslint --project .", "run_mocha": "mocha lib/test/**/*_test.js --exit", "test": "run-s clean build copy_test_fixtures run_mocha", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", diff --git a/packages/contract-wrappers/.npmignore b/packages/contract-wrappers/.npmignore new file mode 100644 index 000000000..6a3eb57bd --- /dev/null +++ b/packages/contract-wrappers/.npmignore @@ -0,0 +1,11 @@ +.* +tsconfig.json +webpack.config.js +yarn-error.log +test/ +/src/ +/_bundles/ +/contract_templates/ +/generated_docs/ +/scripts/ +/lib/src/monorepo_scripts/ diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json new file mode 100644 index 000000000..18ca4143e --- /dev/null +++ b/packages/contract-wrappers/CHANGELOG.json @@ -0,0 +1,11 @@ +[ + { + "version": "0.0.1", + "changes": [ + { + "note": "Moved contractWrappers out of 0x.js", + "pr": 579 + } + ] + } +] diff --git a/packages/contract-wrappers/CHANGELOG.md b/packages/contract-wrappers/CHANGELOG.md new file mode 100644 index 000000000..5565d6210 --- /dev/null +++ b/packages/contract-wrappers/CHANGELOG.md @@ -0,0 +1,6 @@ +<!-- +This file is auto-generated using the monorepo-scripts package. Don't edit directly. +Edit the package's CHANGELOG.json file only. +--> + +CHANGELOG diff --git a/packages/contract-wrappers/README.md b/packages/contract-wrappers/README.md new file mode 100644 index 000000000..0fca4c762 --- /dev/null +++ b/packages/contract-wrappers/README.md @@ -0,0 +1,91 @@ +## @0xproject/contract-wrappers + +Smart TS wrappers for 0x smart contracts. The wrappers have simplified interfaces, perform client-side validation on transactions and throw helpful error messages. + +### Read the [Documentation](https://0xproject.com/docs/0x.js). + +## Installation + +**Install** + +```bash +npm install @0xproject/contract-wrappers --save +``` + +**Import** + +```javascript +import { ContractWrappers } from '@0xproject/contract-wrappers'; +``` + +If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: + +```json +"compilerOptions": { + "typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"], +} +``` + +## Contributing + +We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. + +Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. + +### Install dependencies + +If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: + +```bash +yarn config set workspaces-experimental true +``` + +Then install dependencies + +```bash +yarn install +``` + +### Build + +If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory: + +```bash +yarn lerna:rebuild +``` + +Or continuously rebuild on change: + +```bash +yarn dev +``` + +You can also build this specific package by running the following from within its directory: + +```bash +yarn build +``` + +or continuously rebuild on change: + +```bash +yarn build:watch +``` + +### Clean + +```bash +yarn clean +``` + +### Lint + +```bash +yarn lint +``` + +### Run Tests + +```bash +yarn test +``` diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json new file mode 100644 index 000000000..917cabbb6 --- /dev/null +++ b/packages/contract-wrappers/package.json @@ -0,0 +1,96 @@ +{ + "name": "@0xproject/contract-wrappers", + "version": "0.0.1", + "description": "Smart TS wrappers for 0x smart contracts", + "keywords": [ + "0xproject", + "ethereum", + "tokens", + "exchange" + ], + "main": "lib/src/index.js", + "types": "lib/src/index.d.ts", + "scripts": { + "build:watch": "tsc -w", + "prebuild": "run-s clean generate_contract_wrappers", + "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'", + "lint": "tslint --project .", + "test:circleci": "run-s test:coverage", + "test": "run-s clean build run_mocha", + "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", + "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", + "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/src/artifacts/$i.json test/artifacts; done;", + "clean": "shx rm -rf _bundles lib test_temp scripts", + "build": "tsc && yarn update_artifacts && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", + "run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit", + "manual:postpublish": "yarn build; node ./scripts/postpublish.js" + }, + "config": { + "compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry", + "contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels", + "postpublish": { + "assets": [ + "packages/contract-wrappers/_bundles/index.js", + "packages/contract-wrappers/_bundles/index.min.js" + ] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/0xProject/0x-monorepo" + }, + "license": "Apache-2.0", + "engines": { + "node": ">=6.0.0" + }, + "devDependencies": { + "@0xproject/deployer": "^0.4.3", + "@0xproject/dev-utils": "^0.4.1", + "@0xproject/migrations": "^0.0.5", + "@0xproject/monorepo-scripts": "^0.1.19", + "@0xproject/subproviders": "^0.10.1", + "@0xproject/tslint-config": "^0.4.17", + "@types/lodash": "4.14.104", + "@types/mocha": "^2.2.42", + "@types/node": "^8.0.53", + "@types/sinon": "^2.2.2", + "@types/uuid": "^3.4.2", + "awesome-typescript-loader": "^3.1.3", + "chai": "^4.0.1", + "chai-as-promised": "^7.1.0", + "chai-bignumber": "^2.0.1", + "copyfiles": "^1.2.0", + "dirty-chai": "^2.0.1", + "mocha": "^4.0.1", + "npm-run-all": "^4.1.2", + "nyc": "^11.0.1", + "opn-cli": "^3.1.0", + "prettier": "^1.11.1", + "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.4" + }, + "dependencies": { + "@0xproject/assert": "^0.2.9", + "@0xproject/base-contract": "^0.3.1", + "@0xproject/fill-scenarios": "^0.0.1", + "@0xproject/json-schemas": "^0.7.23", + "@0xproject/order-utils": "^0.0.4", + "@0xproject/types": "^0.6.3", + "@0xproject/typescript-typings": "^0.3.1", + "@0xproject/utils": "^0.6.1", + "@0xproject/web3-wrapper": "^0.6.3", + "ethereumjs-blockstream": "^2.0.6", + "ethereumjs-util": "^5.1.1", + "ethers": "^3.0.15", + "js-sha3": "^0.7.0", + "lodash": "^4.17.4", + "uuid": "^3.1.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/contract-wrappers/src/artifacts.ts b/packages/contract-wrappers/src/artifacts.ts new file mode 100644 index 000000000..13587984c --- /dev/null +++ b/packages/contract-wrappers/src/artifacts.ts @@ -0,0 +1,18 @@ +import { Artifact } from '@0xproject/types'; + +import * as DummyToken from './compact_artifacts/DummyToken.json'; +import * as EtherToken from './compact_artifacts/EtherToken.json'; +import * as Exchange from './compact_artifacts/Exchange.json'; +import * as Token from './compact_artifacts/Token.json'; +import * as TokenRegistry from './compact_artifacts/TokenRegistry.json'; +import * as TokenTransferProxy from './compact_artifacts/TokenTransferProxy.json'; +import * as ZRX from './compact_artifacts/ZRX.json'; +export const artifacts = { + ZRX: (ZRX as any) as Artifact, + DummyToken: (DummyToken as any) as Artifact, + Token: (Token as any) as Artifact, + Exchange: (Exchange as any) as Artifact, + EtherToken: (EtherToken as any) as Artifact, + TokenRegistry: (TokenRegistry as any) as Artifact, + TokenTransferProxy: (TokenTransferProxy as any) as Artifact, +}; diff --git a/packages/contract-wrappers/src/compact_artifacts/DummyToken.json b/packages/contract-wrappers/src/compact_artifacts/DummyToken.json new file mode 100644 index 000000000..f64a8cd3d --- /dev/null +++ b/packages/contract-wrappers/src/compact_artifacts/DummyToken.json @@ -0,0 +1,22 @@ +{ + "contract_name": "DummyToken", + "abi": [ + { + "constant": false, + "inputs": [ + { + "name": "_target", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "setBalance", + "outputs": [], + "payable": false, + "type": "function" + } + ] +} diff --git a/packages/contract-wrappers/src/compact_artifacts/EtherToken.json b/packages/contract-wrappers/src/compact_artifacts/EtherToken.json new file mode 100644 index 000000000..26cca57cd --- /dev/null +++ b/packages/contract-wrappers/src/compact_artifacts/EtherToken.json @@ -0,0 +1,287 @@ +{ + "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" + } + } +} diff --git a/packages/contract-wrappers/src/compact_artifacts/Exchange.json b/packages/contract-wrappers/src/compact_artifacts/Exchange.json new file mode 100644 index 000000000..af8db7360 --- /dev/null +++ b/packages/contract-wrappers/src/compact_artifacts/Exchange.json @@ -0,0 +1,610 @@ +{ + "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" + } + } +} diff --git a/packages/contract-wrappers/src/compact_artifacts/Token.json b/packages/contract-wrappers/src/compact_artifacts/Token.json new file mode 100644 index 000000000..3b5a86ae0 --- /dev/null +++ b/packages/contract-wrappers/src/compact_artifacts/Token.json @@ -0,0 +1,172 @@ +{ + "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" + } + ] +} diff --git a/packages/contract-wrappers/src/compact_artifacts/TokenRegistry.json b/packages/contract-wrappers/src/compact_artifacts/TokenRegistry.json new file mode 100644 index 000000000..0f583628c --- /dev/null +++ b/packages/contract-wrappers/src/compact_artifacts/TokenRegistry.json @@ -0,0 +1,547 @@ +{ + "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" + } + } +} diff --git a/packages/contract-wrappers/src/compact_artifacts/TokenTransferProxy.json b/packages/contract-wrappers/src/compact_artifacts/TokenTransferProxy.json new file mode 100644 index 000000000..8cf551ddb --- /dev/null +++ b/packages/contract-wrappers/src/compact_artifacts/TokenTransferProxy.json @@ -0,0 +1,187 @@ +{ + "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" + } + } +} diff --git a/packages/contract-wrappers/src/compact_artifacts/ZRX.json b/packages/contract-wrappers/src/compact_artifacts/ZRX.json new file mode 100644 index 000000000..e40b8f268 --- /dev/null +++ b/packages/contract-wrappers/src/compact_artifacts/ZRX.json @@ -0,0 +1,20 @@ +{ + "contract_name": "ZRX", + "networks": { + "1": { + "address": "0xe41d2489571d322189246dafa5ebde1f4699f498" + }, + "3": { + "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d" + }, + "4": { + "address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8" + }, + "42": { + "address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570" + }, + "50": { + "address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401" + } + } +} diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts new file mode 100644 index 000000000..381c4a63f --- /dev/null +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -0,0 +1,136 @@ +import { schemas, SchemaValidator } from '@0xproject/json-schemas'; +import { + generatePseudoRandomSalt, + getOrderHashHex, + isValidOrderHash, + isValidSignature, + signOrderHashAsync, +} from '@0xproject/order-utils'; +import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types'; +import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as ethUtil from 'ethereumjs-util'; +import * as _ from 'lodash'; + +import { artifacts } from './artifacts'; +import { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; +import { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; +import { TokenRegistryWrapper } from './contract_wrappers/token_registry_wrapper'; +import { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper'; +import { TokenWrapper } from './contract_wrappers/token_wrapper'; +import { ContractWrappersConfigSchema } from './schemas/contract_wrappers_config_schema'; +import { contractWrappersPrivateNetworkConfigSchema } from './schemas/contract_wrappers_private_network_config_schema'; +import { contractWrappersPublicNetworkConfigSchema } from './schemas/contract_wrappers_public_network_config_schema'; +import { ContractWrappersConfig } from './types'; +import { assert } from './utils/assert'; +import { constants } from './utils/constants'; +import { decorators } from './utils/decorators'; +import { utils } from './utils/utils'; + +/** + * The ContractWrappers class contains smart contract wrappers helpful when building on 0x protocol. + */ +export class ContractWrappers { + /** + * 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. + */ + public tokenRegistry: TokenRegistryWrapper; + /** + * An instance of the TokenWrapper class containing methods for interacting with any ERC20 token smart contract. + */ + public token: TokenWrapper; + /** + * 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. + */ + public proxy: TokenTransferProxyWrapper; + private _web3Wrapper: Web3Wrapper; + /** + * Instantiates a new ContractWrappers instance. + * @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 ContractWrappers class. + */ + constructor(provider: Provider, config: ContractWrappersConfig) { + assert.isWeb3Provider('provider', provider); + assert.doesConformToSchema('config', config, ContractWrappersConfigSchema, [ + contractWrappersPrivateNetworkConfigSchema, + contractWrappersPublicNetworkConfigSchema, + ]); + const artifactJSONs = _.values(artifacts); + const abiArrays = _.map(artifactJSONs, artifact => artifact.abi); + const defaults = { + gasPrice: config.gasPrice, + }; + this._web3Wrapper = new Web3Wrapper(provider, defaults); + _.forEach(abiArrays, abi => { + this._web3Wrapper.abiDecoder.addABI(abi); + }); + this.proxy = new TokenTransferProxyWrapper( + this._web3Wrapper, + config.networkId, + config.tokenTransferProxyContractAddress, + ); + this.token = new TokenWrapper(this._web3Wrapper, config.networkId, this.proxy); + this.exchange = new ExchangeWrapper( + this._web3Wrapper, + config.networkId, + this.token, + config.exchangeContractAddress, + config.zrxContractAddress, + ); + this.tokenRegistry = new TokenRegistryWrapper( + this._web3Wrapper, + config.networkId, + config.tokenRegistryContractAddress, + ); + this.etherToken = new EtherTokenWrapper(this._web3Wrapper, config.networkId, this.token); + } + /** + * 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._web3Wrapper.setProvider(provider); + (this.exchange as any)._invalidateContractInstances(); + (this.exchange as any)._setNetworkId(networkId); + (this.tokenRegistry as any)._invalidateContractInstance(); + (this.tokenRegistry as any)._setNetworkId(networkId); + (this.token as any)._invalidateContractInstances(); + (this.token as any)._setNetworkId(networkId); + (this.proxy as any)._invalidateContractInstance(); + (this.proxy as any)._setNetworkId(networkId); + (this.etherToken as any)._invalidateContractInstance(); + (this.etherToken as any)._setNetworkId(networkId); + } + /** + * Get the provider instance currently used by 0x.js + * @return Web3 provider instance + */ + public getProvider(): Provider { + return this._web3Wrapper.getProvider(); + } + /* + * HACK: `TokenWrapper` needs a token transfer proxy address. `TokenTransferProxy` address is fetched from + * an `ExchangeWrapper`. `ExchangeWrapper` needs `TokenWrapper` to validate orders, creating a dependency cycle. + * In order to break this - we create this function here and pass it as a parameter to the `TokenWrapper` + * and `ProxyWrapper`. + */ + private async _getTokenTransferProxyAddressAsync(): Promise<string> { + const tokenTransferProxyAddress = await (this.exchange as any)._getTokenTransferProxyAddressAsync(); + return tokenTransferProxyAddress; + } +} diff --git a/packages/0x.js/src/contract_wrappers/contract_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts index 02be2dab3..f255ced62 100644 --- a/packages/0x.js/src/contract_wrappers/contract_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/contract_wrapper.ts @@ -1,32 +1,38 @@ -import { BlockParamLiteral, ContractAbi, FilterObject, LogEntry, LogWithDecodedArgs, RawLog } from '@0xproject/types'; +import { + Artifact, + BlockParamLiteral, + ContractAbi, + FilterObject, + LogEntry, + LogWithDecodedArgs, + RawLog, +} from '@0xproject/types'; import { AbiDecoder, intervalUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream'; import * as _ from 'lodash'; -import * as Web3 from 'web3'; import { - Artifact, BlockRange, ContractEventArgs, ContractEvents, + ContractWrappersError, EventCallback, IndexedFilterValues, - InternalZeroExError, - ZeroExError, + InternalContractWrappersError, } from '../types'; import { constants } from '../utils/constants'; import { filterUtils } from '../utils/filter_utils'; const CONTRACT_NAME_TO_NOT_FOUND_ERROR: { - [contractName: string]: ZeroExError; + [contractName: string]: ContractWrappersError; } = { - ZRX: ZeroExError.ZRXContractDoesNotExist, - EtherToken: ZeroExError.EtherTokenContractDoesNotExist, - Token: ZeroExError.TokenContractDoesNotExist, - TokenRegistry: ZeroExError.TokenRegistryContractDoesNotExist, - TokenTransferProxy: ZeroExError.TokenTransferProxyContractDoesNotExist, - Exchange: ZeroExError.ExchangeContractDoesNotExist, + ZRX: ContractWrappersError.ZRXContractDoesNotExist, + EtherToken: ContractWrappersError.EtherTokenContractDoesNotExist, + Token: ContractWrappersError.TokenContractDoesNotExist, + TokenRegistry: ContractWrappersError.TokenRegistryContractDoesNotExist, + TokenTransferProxy: ContractWrappersError.TokenTransferProxyContractDoesNotExist, + Exchange: ContractWrappersError.ExchangeContractDoesNotExist, }; export class ContractWrapper { @@ -57,7 +63,7 @@ export class ContractWrapper { } protected _unsubscribe(filterToken: string, err?: Error): void { if (_.isUndefined(this._filters[filterToken])) { - throw new Error(ZeroExError.SubscriptionNotFound); + throw new Error(ContractWrappersError.SubscriptionNotFound); } if (!_.isUndefined(err)) { const callback = this._filterCallbacks[filterToken]; @@ -101,7 +107,7 @@ export class ContractWrapper { log: LogEntry, ): LogWithDecodedArgs<ArgsType> | RawLog { if (_.isUndefined(this._web3Wrapper.abiDecoder)) { - throw new Error(InternalZeroExError.NoAbiDecoder); + throw new Error(InternalContractWrappersError.NoAbiDecoder); } const logWithDecodedArgs = this._web3Wrapper.abiDecoder.tryToDecodeLogOrNoop(log); return logWithDecodedArgs; @@ -113,7 +119,7 @@ export class ContractWrapper { let contractAddress: string; if (_.isUndefined(addressIfExists)) { if (_.isUndefined(artifact.networks[this._networkId])) { - throw new Error(ZeroExError.ContractNotDeployedOnNetwork); + throw new Error(ContractWrappersError.ContractNotDeployedOnNetwork); } contractAddress = artifact.networks[this._networkId].address.toLowerCase(); } else { @@ -130,7 +136,7 @@ export class ContractWrapper { if (_.isUndefined(addressIfExists)) { const contractAddress = artifact.networks[this._networkId].address; if (_.isUndefined(contractAddress)) { - throw new Error(ZeroExError.ExchangeContractDoesNotExist); + throw new Error(ContractWrappersError.ExchangeContractDoesNotExist); } return contractAddress; } else { @@ -151,7 +157,7 @@ export class ContractWrapper { } private _startBlockAndLogStream(): void { if (!_.isUndefined(this._blockAndLogStreamerIfExists)) { - throw new Error(ZeroExError.SubscriptionAlreadyPresent); + throw new Error(ContractWrappersError.SubscriptionAlreadyPresent); } this._blockAndLogStreamerIfExists = new BlockAndLogStreamer( this._web3Wrapper.getBlockAsync.bind(this._web3Wrapper), @@ -184,7 +190,7 @@ export class ContractWrapper { } private _stopBlockAndLogStream(): void { if (_.isUndefined(this._blockAndLogStreamerIfExists)) { - throw new Error(ZeroExError.SubscriptionNotFound); + throw new Error(ContractWrappersError.SubscriptionNotFound); } this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string); this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string); diff --git a/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts index fd39de34b..1bd65270b 100644 --- a/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/ether_token_wrapper.ts @@ -5,7 +5,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { artifacts } from '../artifacts'; -import { BlockRange, EventCallback, IndexedFilterValues, TransactionOpts, ZeroExError } from '../types'; +import { BlockRange, ContractWrappersError, EventCallback, IndexedFilterValues, TransactionOpts } from '../types'; import { assert } from '../utils/assert'; import { ContractWrapper } from './contract_wrapper'; @@ -48,7 +48,7 @@ export class EtherTokenWrapper extends ContractWrapper { const normalizedDepositorAddress = depositor.toLowerCase(); const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(normalizedDepositorAddress); - assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit); + assert.assert(ethBalanceInWei.gte(amountInWei), ContractWrappersError.InsufficientEthBalanceForDeposit); const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress); const txHash = await wethContract.deposit.sendTransactionAsync({ @@ -84,7 +84,10 @@ export class EtherTokenWrapper extends ContractWrapper { normalizedEtherTokenAddress, normalizedWithdrawerAddress, ); - assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal); + assert.assert( + WETHBalanceInBaseUnits.gte(amountInWei), + ContractWrappersError.InsufficientWEthBalanceForWithdrawal, + ); const wethContract = await this._getEtherTokenContractAsync(normalizedEtherTokenAddress); const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, { @@ -119,7 +122,7 @@ export class EtherTokenWrapper extends ContractWrapper { eventName, blockRange, indexFilterValues, - artifacts.EtherTokenArtifact.abi, + artifacts.EtherToken.abi, ); return logs; } @@ -147,7 +150,7 @@ export class EtherTokenWrapper extends ContractWrapper { normalizedEtherTokenAddress, eventName, indexFilterValues, - artifacts.EtherTokenArtifact.abi, + artifacts.EtherToken.abi, callback, ); return subscriptionToken; @@ -172,7 +175,7 @@ export class EtherTokenWrapper extends ContractWrapper { * @returns The Ethereum address of the EtherToken contract or undefined. */ public getContractAddressIfExists(): string | undefined { - const networkSpecificArtifact = artifacts.EtherTokenArtifact.networks[this._networkId]; + const networkSpecificArtifact = artifacts.EtherToken.networks[this._networkId]; const contractAddressIfExists = _.isUndefined(networkSpecificArtifact) ? undefined : networkSpecificArtifact.address; @@ -188,7 +191,7 @@ export class EtherTokenWrapper extends ContractWrapper { return etherTokenContract; } const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.EtherTokenArtifact, + artifacts.EtherToken, etherTokenAddress, ); const contractInstance = new EtherTokenContract( diff --git a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts index 6ddaaaf4f..f2b64fc37 100644 --- a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/exchange_wrapper.ts @@ -1,12 +1,16 @@ import { schemas } from '@0xproject/json-schemas'; -import { getOrderHashHex } from '@0xproject/order-utils'; +import { formatters, getOrderHashHex, OrderStateUtils } from '@0xproject/order-utils'; import { BlockParamLiteral, DecodedLogArgs, ECSignature, + ExchangeContractErrs, LogEntry, LogWithDecodedArgs, Order, + OrderAddresses, + OrderState, + OrderValues, SignedOrder, } from '@0xproject/types'; import { AbiDecoder, BigNumber } from '@0xproject/utils'; @@ -20,21 +24,16 @@ import { BlockRange, EventCallback, ExchangeContractErrCodes, - ExchangeContractErrs, IndexedFilterValues, MethodOpts, - OrderAddresses, OrderCancellationRequest, OrderFillRequest, - OrderState, OrderTransactionOpts, - OrderValues, ValidateOrderFillableOpts, } from '../types'; import { assert } from '../utils/assert'; import { decorators } from '../utils/decorators'; import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator'; -import { OrderStateUtils } from '../utils/order_state_utils'; import { OrderValidationUtils } from '../utils/order_validation_utils'; import { utils } from '../utils/utils'; @@ -70,24 +69,6 @@ export class ExchangeWrapper extends ContractWrapper { }; private _contractAddressIfExists?: string; private _zrxContractAddressIfExists?: string; - private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] { - const orderAddresses: OrderAddresses = [ - order.maker, - order.taker, - order.makerTokenAddress, - order.takerTokenAddress, - order.feeRecipient, - ]; - const orderValues: OrderValues = [ - order.makerTokenAmount, - order.takerTokenAmount, - order.makerFee, - order.takerFee, - order.expirationUnixTimestampSec, - order.salt, - ]; - return [orderAddresses, orderValues]; - } constructor( web3Wrapper: Web3Wrapper, networkId: number, @@ -209,7 +190,7 @@ export class ExchangeWrapper extends ContractWrapper { ); } - const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); + const [orderAddresses, orderValues] = formatters.getOrderAddressesAndValues(signedOrder); const txHash: string = await exchangeInstance.fillOrder.sendTransactionAsync( orderAddresses, @@ -296,7 +277,7 @@ export class ExchangeWrapper extends ContractWrapper { const orderAddressesValuesAndSignatureArray = _.map(signedOrders, signedOrder => { return [ - ...ExchangeWrapper._getOrderAddressesAndValues(signedOrder), + ...formatters.getOrderAddressesAndValues(signedOrder), signedOrder.ecSignature.v, signedOrder.ecSignature.r, signedOrder.ecSignature.s, @@ -384,7 +365,7 @@ export class ExchangeWrapper extends ContractWrapper { const orderAddressesValuesAmountsAndSignatureArray = _.map(orderFillRequests, orderFillRequest => { return [ - ...ExchangeWrapper._getOrderAddressesAndValues(orderFillRequest.signedOrder), + ...formatters.getOrderAddressesAndValues(orderFillRequest.signedOrder), orderFillRequest.takerTokenFillAmount, orderFillRequest.signedOrder.ecSignature.v, orderFillRequest.signedOrder.ecSignature.r, @@ -453,7 +434,7 @@ export class ExchangeWrapper extends ContractWrapper { ); } - const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); + const [orderAddresses, orderValues] = formatters.getOrderAddressesAndValues(signedOrder); const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync( orderAddresses, orderValues, @@ -519,7 +500,7 @@ export class ExchangeWrapper extends ContractWrapper { const orderAddressesValuesAndTakerTokenFillAmounts = _.map(orderFillRequests, request => { return [ - ...ExchangeWrapper._getOrderAddressesAndValues(request.signedOrder), + ...formatters.getOrderAddressesAndValues(request.signedOrder), request.takerTokenFillAmount, request.signedOrder.ecSignature.v, request.signedOrder.ecSignature.r, @@ -580,7 +561,7 @@ export class ExchangeWrapper extends ContractWrapper { ); } - const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); + const [orderAddresses, orderValues] = formatters.getOrderAddressesAndValues(order); const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync( orderAddresses, orderValues, @@ -645,7 +626,7 @@ export class ExchangeWrapper extends ContractWrapper { const exchangeInstance = await this._getExchangeContractAsync(); const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => { return [ - ...ExchangeWrapper._getOrderAddressesAndValues(cancellationRequest.order), + ...formatters.getOrderAddressesAndValues(cancellationRequest.order), cancellationRequest.takerTokenCancelAmount, ]; }); @@ -686,7 +667,7 @@ export class ExchangeWrapper extends ContractWrapper { exchangeContractAddress, eventName, indexFilterValues, - artifacts.ExchangeArtifact.abi, + artifacts.Exchange.abi, callback, ); return subscriptionToken; @@ -726,7 +707,7 @@ export class ExchangeWrapper extends ContractWrapper { eventName, blockRange, indexFilterValues, - artifacts.ExchangeArtifact.abi, + artifacts.Exchange.abi, ); return logs; } @@ -736,7 +717,7 @@ export class ExchangeWrapper extends ContractWrapper { * @returns The Ethereum address of the Exchange contract being used. */ public getContractAddress(): string { - const contractAddress = this._getContractAddress(artifacts.ExchangeArtifact, this._contractAddressIfExists); + const contractAddress = this._getContractAddress(artifacts.Exchange, this._contractAddressIfExists); return contractAddress; } /** @@ -904,7 +885,7 @@ export class ExchangeWrapper extends ContractWrapper { * @return Address of ZRX token */ public getZRXTokenAddress(): string { - const contractAddress = this._getContractAddress(artifacts.ZRXArtifact, this._zrxContractAddressIfExists); + const contractAddress = this._getContractAddress(artifacts.ZRX, this._zrxContractAddressIfExists); return contractAddress; } private _invalidateContractInstances(): void { @@ -934,7 +915,7 @@ export class ExchangeWrapper extends ContractWrapper { } private async _getOrderHashHexUsingContractCallAsync(order: Order | SignedOrder): Promise<string> { const exchangeInstance = await this._getExchangeContractAsync(); - const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); + const [orderAddresses, orderValues] = formatters.getOrderAddressesAndValues(order); const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues); return orderHashHex; } @@ -943,7 +924,7 @@ export class ExchangeWrapper extends ContractWrapper { return this._exchangeContractIfExists; } const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.ExchangeArtifact, + artifacts.Exchange, this._contractAddressIfExists, ); const contractInstance = new ExchangeContract( diff --git a/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/token_registry_wrapper.ts index c4a193264..5ae488172 100644 --- a/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/token_registry_wrapper.ts @@ -1,8 +1,9 @@ +import { Token } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { artifacts } from '../artifacts'; -import { Token, TokenMetadata } from '../types'; +import { TokenMetadata } from '../types'; import { assert } from '../utils/assert'; import { constants } from '../utils/constants'; @@ -105,7 +106,7 @@ export class TokenRegistryWrapper extends ContractWrapper { */ public getContractAddress(): string { const contractAddress = this._getContractAddress( - artifacts.TokenRegistryArtifact, + artifacts.TokenRegistry, this._contractAddressIfExists, ); return contractAddress; @@ -118,7 +119,7 @@ export class TokenRegistryWrapper extends ContractWrapper { return this._tokenRegistryContractIfExists; } const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.TokenRegistryArtifact, + artifacts.TokenRegistry, this._contractAddressIfExists, ); const contractInstance = new TokenRegistryContract( diff --git a/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/token_transfer_proxy_wrapper.ts index be558b5be..ebd40e4d2 100644 --- a/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/token_transfer_proxy_wrapper.ts @@ -47,7 +47,7 @@ export class TokenTransferProxyWrapper extends ContractWrapper { */ public getContractAddress(): string { const contractAddress = this._getContractAddress( - artifacts.TokenTransferProxyArtifact, + artifacts.TokenTransferProxy, this._contractAddressIfExists, ); return contractAddress; @@ -60,7 +60,7 @@ export class TokenTransferProxyWrapper extends ContractWrapper { return this._tokenTransferProxyContractIfExists; } const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.TokenTransferProxyArtifact, + artifacts.TokenTransferProxy, this._contractAddressIfExists, ); const contractInstance = new TokenTransferProxyContract( diff --git a/packages/0x.js/src/contract_wrappers/token_wrapper.ts b/packages/contract-wrappers/src/contract_wrappers/token_wrapper.ts index 194cfb5aa..844318c79 100644 --- a/packages/0x.js/src/contract_wrappers/token_wrapper.ts +++ b/packages/contract-wrappers/src/contract_wrappers/token_wrapper.ts @@ -5,7 +5,14 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { artifacts } from '../artifacts'; -import { BlockRange, EventCallback, IndexedFilterValues, MethodOpts, TransactionOpts, ZeroExError } from '../types'; +import { + BlockRange, + ContractWrappersError, + EventCallback, + IndexedFilterValues, + MethodOpts, + TransactionOpts, +} from '../types'; import { assert } from '../utils/assert'; import { constants } from '../utils/constants'; @@ -266,7 +273,7 @@ export class TokenWrapper extends ContractWrapper { const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress); if (fromAddressBalance.lessThan(amountInBaseUnits)) { - throw new Error(ZeroExError.InsufficientBalanceForTransfer); + throw new Error(ContractWrappersError.InsufficientBalanceForTransfer); } const txHash = await tokenContract.transfer.sendTransactionAsync(normalizedToAddress, amountInBaseUnits, { @@ -316,12 +323,12 @@ export class TokenWrapper extends ContractWrapper { normalizedSenderAddress, ); if (fromAddressAllowance.lessThan(amountInBaseUnits)) { - throw new Error(ZeroExError.InsufficientAllowanceForTransfer); + throw new Error(ContractWrappersError.InsufficientAllowanceForTransfer); } const fromAddressBalance = await this.getBalanceAsync(normalizedTokenAddress, normalizedFromAddress); if (fromAddressBalance.lessThan(amountInBaseUnits)) { - throw new Error(ZeroExError.InsufficientBalanceForTransfer); + throw new Error(ContractWrappersError.InsufficientBalanceForTransfer); } const txHash = await tokenContract.transferFrom.sendTransactionAsync( @@ -360,7 +367,7 @@ export class TokenWrapper extends ContractWrapper { normalizedTokenAddress, eventName, indexFilterValues, - artifacts.TokenArtifact.abi, + artifacts.Token.abi, callback, ); return subscriptionToken; @@ -403,7 +410,7 @@ export class TokenWrapper extends ContractWrapper { eventName, blockRange, indexFilterValues, - artifacts.TokenArtifact.abi, + artifacts.Token.abi, ); return logs; } @@ -418,7 +425,7 @@ export class TokenWrapper extends ContractWrapper { return tokenContract; } const [abi, address] = await this._getContractAbiAndAddressFromArtifactsAsync( - artifacts.TokenArtifact, + artifacts.Token, normalizedTokenAddress, ); const contractInstance = new TokenContract( diff --git a/packages/0x.js/src/fetchers/simple_balance_and_proxy_allowance_fetcher.ts b/packages/contract-wrappers/src/fetchers/simple_balance_and_proxy_allowance_fetcher.ts index 21774d794..5017d879a 100644 --- a/packages/0x.js/src/fetchers/simple_balance_and_proxy_allowance_fetcher.ts +++ b/packages/contract-wrappers/src/fetchers/simple_balance_and_proxy_allowance_fetcher.ts @@ -1,10 +1,10 @@ +import { AbstractBalanceAndProxyAllowanceFetcher } from '@0xproject/order-utils'; import { BlockParamLiteral } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; -import { BalanceAndProxyAllowanceFetcher } from '../abstract/balance_and_proxy_allowance_fetcher'; import { TokenWrapper } from '../contract_wrappers/token_wrapper'; -export class SimpleBalanceAndProxyAllowanceFetcher implements BalanceAndProxyAllowanceFetcher { +export class SimpleBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher { private _tokenWrapper: TokenWrapper; private _defaultBlock: BlockParamLiteral; constructor(token: TokenWrapper, defaultBlock: BlockParamLiteral) { diff --git a/packages/0x.js/src/fetchers/simple_order_filled_cancelled_fetcher.ts b/packages/contract-wrappers/src/fetchers/simple_order_filled_cancelled_fetcher.ts index b7548d54d..52d0a100c 100644 --- a/packages/0x.js/src/fetchers/simple_order_filled_cancelled_fetcher.ts +++ b/packages/contract-wrappers/src/fetchers/simple_order_filled_cancelled_fetcher.ts @@ -1,10 +1,10 @@ +import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils'; import { BlockParamLiteral } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; -import { OrderFilledCancelledFetcher } from '../abstract/order_filled_cancelled_fetcher'; import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; -export class SimpleOrderFilledCancelledFetcher implements OrderFilledCancelledFetcher { +export class SimpleOrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher { private _exchangeWrapper: ExchangeWrapper; private _defaultBlock: BlockParamLiteral; constructor(exchange: ExchangeWrapper, defaultBlock: BlockParamLiteral) { @@ -25,4 +25,12 @@ export class SimpleOrderFilledCancelledFetcher implements OrderFilledCancelledFe const cancelledTakerAmount = this._exchangeWrapper.getCancelledTakerAmountAsync(orderHash, methodOpts); return cancelledTakerAmount; } + public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber> { + const unavailableTakerAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); + return unavailableTakerAmount; + } + public getZRXTokenAddress(): string { + const zrxToken = this._exchangeWrapper.getZRXTokenAddress(); + return zrxToken; + } } diff --git a/packages/contract-wrappers/src/globals.d.ts b/packages/contract-wrappers/src/globals.d.ts new file mode 100644 index 000000000..94e63a32d --- /dev/null +++ b/packages/contract-wrappers/src/globals.d.ts @@ -0,0 +1,6 @@ +declare module '*.json' { + const json: any; + /* tslint:disable */ + export default json; + /* tslint:enable */ +} diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts new file mode 100644 index 000000000..45af8a707 --- /dev/null +++ b/packages/contract-wrappers/src/index.ts @@ -0,0 +1,68 @@ +export { ContractWrappers } from './contract_wrappers'; +export { ExchangeWrapper } from './contract_wrappers/exchange_wrapper'; +export { TokenWrapper } from './contract_wrappers/token_wrapper'; +export { TokenRegistryWrapper } from './contract_wrappers/token_registry_wrapper'; +export { EtherTokenWrapper } from './contract_wrappers/ether_token_wrapper'; +export { TokenTransferProxyWrapper } from './contract_wrappers/token_transfer_proxy_wrapper'; + +export { + ContractWrappersError, + EventCallback, + ContractEvent, + Token, + IndexedFilterValues, + BlockRange, + OrderCancellationRequest, + OrderFillRequest, + ContractEventArgs, + ContractWrappersConfig, + MethodOpts, + OrderTransactionOpts, + TransactionOpts, + LogEvent, + DecodedLogEvent, + OnOrderStateChangeCallback, +} from './types'; + +export { + BlockParamLiteral, + FilterObject, + BlockParam, + ContractEventArg, + ExchangeContractErrs, + LogWithDecodedArgs, + Order, + Provider, + SignedOrder, + ECSignature, + OrderStateValid, + OrderStateInvalid, + OrderState, + TransactionReceipt, + TransactionReceiptWithDecodedLogs, +} from '@0xproject/types'; + +export { + EtherTokenContractEventArgs, + WithdrawalContractEventArgs, + DepositContractEventArgs, + EtherTokenEvents, +} from './contract_wrappers/generated/ether_token'; + +export { + TransferContractEventArgs, + ApprovalContractEventArgs, + TokenContractEventArgs, + TokenEvents, +} from './contract_wrappers/generated/token'; + +export { + LogErrorContractEventArgs, + LogCancelContractEventArgs, + LogFillContractEventArgs, + ExchangeContractEventArgs, + ExchangeEvents, +} from './contract_wrappers/generated/exchange'; + +export { BalanceAndProxyAllowanceLazyStore } from './stores/balance_proxy_allowance_lazy_store'; +export { OrderFilledCancelledLazyStore } from './stores/order_filled_cancelled_lazy_store'; diff --git a/packages/contract-wrappers/src/monorepo_scripts/postpublish.ts b/packages/contract-wrappers/src/monorepo_scripts/postpublish.ts new file mode 100644 index 000000000..dcb99d0f7 --- /dev/null +++ b/packages/contract-wrappers/src/monorepo_scripts/postpublish.ts @@ -0,0 +1,8 @@ +import { postpublishUtils } from '@0xproject/monorepo-scripts'; + +import * as packageJSON from '../package.json'; +import * as tsConfigJSON from '../tsconfig.json'; + +const cwd = `${__dirname}/..`; +// tslint:disable-next-line:no-floating-promises +postpublishUtils.runAsync(packageJSON, tsConfigJSON, cwd); diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_config_schema.ts new file mode 100644 index 000000000..ac248b2d4 --- /dev/null +++ b/packages/contract-wrappers/src/schemas/contract_wrappers_config_schema.ts @@ -0,0 +1,5 @@ +export const ContractWrappersConfigSchema = { + id: '/ContractWrappersConfig', + oneOf: [{ $ref: '/ZeroExContractPrivateNetworkConfig' }, { $ref: '/ZeroExContractPublicNetworkConfig' }], + type: 'object', +}; diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts new file mode 100644 index 000000000..759078feb --- /dev/null +++ b/packages/contract-wrappers/src/schemas/contract_wrappers_private_network_config_schema.ts @@ -0,0 +1,35 @@ +export const contractWrappersPrivateNetworkConfigSchema = { + id: '/ZeroExContractPrivateNetworkConfig', + properties: { + networkId: { + type: 'number', + minimum: 1, + }, + gasPrice: { $ref: '/Number' }, + zrxContractAddress: { $ref: '/Address' }, + exchangeContractAddress: { $ref: '/Address' }, + tokenRegistryContractAddress: { $ref: '/Address' }, + tokenTransferProxyContractAddress: { $ref: '/Address' }, + orderWatcherConfig: { + type: 'object', + properties: { + pollingIntervalMs: { + type: 'number', + minimum: 0, + }, + numConfirmations: { + type: 'number', + minimum: 0, + }, + }, + }, + }, + type: 'object', + required: [ + 'networkId', + 'zrxContractAddress', + 'exchangeContractAddress', + 'tokenRegistryContractAddress', + 'tokenTransferProxyContractAddress', + ], +}; diff --git a/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts new file mode 100644 index 000000000..bf1000afa --- /dev/null +++ b/packages/contract-wrappers/src/schemas/contract_wrappers_public_network_config_schema.ts @@ -0,0 +1,29 @@ +export const contractWrappersPublicNetworkConfigSchema = { + id: '/ZeroExContractPublicNetworkConfig', + properties: { + networkId: { + type: 'number', + enum: [1, 3, 4, 42, 50], + }, + gasPrice: { $ref: '/Number' }, + zrxContractAddress: { $ref: '/Address' }, + exchangeContractAddress: { $ref: '/Address' }, + tokenRegistryContractAddress: { $ref: '/Address' }, + tokenTransferProxyContractAddress: { $ref: '/Address' }, + orderWatcherConfig: { + type: 'object', + properties: { + pollingIntervalMs: { + type: 'number', + minimum: 0, + }, + numConfirmations: { + type: 'number', + minimum: 0, + }, + }, + }, + }, + type: 'object', + required: ['networkId'], +}; diff --git a/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts b/packages/contract-wrappers/src/stores/balance_proxy_allowance_lazy_store.ts index 3ff116db4..614195157 100644 --- a/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts +++ b/packages/contract-wrappers/src/stores/balance_proxy_allowance_lazy_store.ts @@ -1,14 +1,14 @@ +import { AbstractBalanceAndProxyAllowanceFetcher } from '@0xproject/order-utils'; import { BlockParamLiteral } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; -import { BalanceAndProxyAllowanceFetcher } from '../abstract/balance_and_proxy_allowance_fetcher'; import { TokenWrapper } from '../contract_wrappers/token_wrapper'; /** * Copy on read store for balances/proxyAllowances of tokens/accounts */ -export class BalanceAndProxyAllowanceLazyStore implements BalanceAndProxyAllowanceFetcher { +export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProxyAllowanceFetcher { private _tokenWrapper: TokenWrapper; private _defaultBlock: BlockParamLiteral; private _balance: { diff --git a/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts b/packages/contract-wrappers/src/stores/order_filled_cancelled_lazy_store.ts index 61d2db8c2..3d96a95f3 100644 --- a/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts +++ b/packages/contract-wrappers/src/stores/order_filled_cancelled_lazy_store.ts @@ -1,14 +1,14 @@ +import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils'; import { BlockParamLiteral } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; -import { OrderFilledCancelledFetcher } from '../abstract/order_filled_cancelled_fetcher'; import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; /** * Copy on read store for filled/cancelled taker amounts */ -export class OrderFilledCancelledLazyStore implements OrderFilledCancelledFetcher { +export class OrderFilledCancelledLazyStore implements AbstractOrderFilledCancelledFetcher { private _exchangeWrapper: ExchangeWrapper; private _defaultBlock: BlockParamLiteral; private _filledTakerAmount: { @@ -64,4 +64,12 @@ export class OrderFilledCancelledLazyStore implements OrderFilledCancelledFetche this._filledTakerAmount = {}; this._cancelledTakerAmount = {}; } + public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber> { + const unavailableTakerAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); + return unavailableTakerAmount; + } + public getZRXTokenAddress(): string { + const zrxToken = this._exchangeWrapper.getZRXTokenAddress(); + return zrxToken; + } } diff --git a/packages/contract-wrappers/src/types.ts b/packages/contract-wrappers/src/types.ts new file mode 100644 index 000000000..9a463d635 --- /dev/null +++ b/packages/contract-wrappers/src/types.ts @@ -0,0 +1,186 @@ +import { BigNumber } from '@0xproject/utils'; + +import { + BlockParam, + BlockParamLiteral, + ContractAbi, + ContractEventArg, + ExchangeContractErrs, + FilterObject, + LogEntryEvent, + LogWithDecodedArgs, + Order, + OrderState, + SignedOrder, +} from '@0xproject/types'; + +import { EtherTokenContractEventArgs, EtherTokenEvents } from './contract_wrappers/generated/ether_token'; +import { ExchangeContractEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange'; +import { TokenContractEventArgs, TokenEvents } from './contract_wrappers/generated/token'; + +export enum ContractWrappersError { + ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST', + ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST', + EtherTokenContractDoesNotExist = 'ETHER_TOKEN_CONTRACT_DOES_NOT_EXIST', + TokenTransferProxyContractDoesNotExist = 'TOKEN_TRANSFER_PROXY_CONTRACT_DOES_NOT_EXIST', + TokenRegistryContractDoesNotExist = 'TOKEN_REGISTRY_CONTRACT_DOES_NOT_EXIST', + TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST', + ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK', + InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER', + InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER', + InsufficientEthBalanceForDeposit = 'INSUFFICIENT_ETH_BALANCE_FOR_DEPOSIT', + InsufficientWEthBalanceForWithdrawal = 'INSUFFICIENT_WETH_BALANCE_FOR_WITHDRAWAL', + InvalidJump = 'INVALID_JUMP', + OutOfGas = 'OUT_OF_GAS', + SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND', + SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT', +} + +export enum InternalContractWrappersError { + NoAbiDecoder = 'NO_ABI_DECODER', + ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY', + WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY', +} + +export type LogEvent = LogEntryEvent; +export interface DecodedLogEvent<ArgsType> { + isRemoved: boolean; + log: LogWithDecodedArgs<ArgsType>; +} + +export type EventCallback<ArgsType> = (err: null | Error, log?: DecodedLogEvent<ArgsType>) => void; + +export enum ExchangeContractErrCodes { + ERROR_FILL_EXPIRED, // Order has already expired + ERROR_FILL_NO_VALUE, // Order has already been fully filled or cancelled + ERROR_FILL_TRUNCATION, // Rounding error too large + ERROR_FILL_BALANCE_ALLOWANCE, // Insufficient balance or allowance for token transfer + ERROR_CANCEL_EXPIRED, // Order has already expired + ERROR_CANCEL_NO_VALUE, // Order has already been fully filled or cancelled +} + +export interface ContractEvent { + logIndex: number; + transactionIndex: number; + transactionHash: string; + blockHash: string; + blockNumber: number; + address: string; + type: string; + event: string; + args: ContractEventArgs; +} + +export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs; + +// [address, name, symbol, decimals, ipfsHash, swarmHash] +export type TokenMetadata = [string, string, string, number, string, string]; + +export interface Token { + name: string; + address: string; + symbol: string; + decimals: number; +} + +export interface TxOpts { + from: string; + gas?: number; + value?: BigNumber; + gasPrice?: BigNumber; +} + +export interface TokenAddressBySymbol { + [symbol: string]: string; +} + +export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents; + +export interface IndexedFilterValues { + [index: string]: ContractEventArg; +} + +export interface BlockRange { + fromBlock: BlockParam; + toBlock: BlockParam; +} + +export interface OrderCancellationRequest { + order: Order | SignedOrder; + takerTokenCancelAmount: BigNumber; +} + +export interface OrderFillRequest { + signedOrder: SignedOrder; + takerTokenFillAmount: BigNumber; +} + +export type AsyncMethod = (...args: any[]) => Promise<any>; +export type SyncMethod = (...args: any[]) => any; + +/** + * networkId: The id of the underlying ethereum network your provider is connected to. (1-mainnet, 3-ropsten, 4-rinkeby, 42-kovan, 50-testrpc) + * gasPrice: Gas price to use with every transaction + * exchangeContractAddress: The address of an exchange contract to use + * zrxContractAddress: The address of the ZRX contract to use + * tokenRegistryContractAddress: The address of a token registry contract to use + * tokenTransferProxyContractAddress: The address of the token transfer proxy contract to use + * orderWatcherConfig: All the configs related to the orderWatcher + */ +export interface ContractWrappersConfig { + networkId: number; + gasPrice?: BigNumber; + exchangeContractAddress?: string; + zrxContractAddress?: string; + tokenRegistryContractAddress?: string; + tokenTransferProxyContractAddress?: string; +} + +/** + * expectedFillTakerTokenAmount: If specified, the validation method will ensure that the + * supplied order maker has a sufficient allowance/balance to fill this amount of the order's + * takerTokenAmount. If not specified, the validation method ensures that the maker has a sufficient + * allowance/balance to fill the entire remaining order amount. + */ +export interface ValidateOrderFillableOpts { + expectedFillTakerTokenAmount?: BigNumber; +} + +/** + * defaultBlock: The block up to which to query the blockchain state. Setting this to a historical block number + * let's the user query the blockchain's state at an arbitrary point in time. In order for this to work, the + * backing Ethereum node must keep the entire historical state of the chain (e.g setting `--pruning=archive` + * flag when running Parity). + */ +export interface MethodOpts { + defaultBlock?: BlockParam; +} + +/** + * gasPrice: Gas price in Wei to use for a transaction + * gasLimit: The amount of gas to send with a transaction + */ +export interface TransactionOpts { + gasPrice?: BigNumber; + gasLimit?: number; +} + +/** + * shouldValidate: Flag indicating whether the library should make attempts to validate a transaction before + * broadcasting it. For example, order has a valid signature, maker has sufficient funds, etc. Default=true. + */ +export interface OrderTransactionOpts extends TransactionOpts { + shouldValidate?: boolean; +} + +export enum TradeSide { + Maker = 'maker', + Taker = 'taker', +} + +export enum TransferType { + Trade = 'trade', + Fee = 'fee', +} + +export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void; diff --git a/packages/0x.js/src/utils/assert.ts b/packages/contract-wrappers/src/utils/assert.ts index 2588a4d09..2588a4d09 100644 --- a/packages/0x.js/src/utils/assert.ts +++ b/packages/contract-wrappers/src/utils/assert.ts diff --git a/packages/contract-wrappers/src/utils/constants.ts b/packages/contract-wrappers/src/utils/constants.ts new file mode 100644 index 000000000..07da6745d --- /dev/null +++ b/packages/contract-wrappers/src/utils/constants.ts @@ -0,0 +1,11 @@ +import { BigNumber } from '@0xproject/utils'; + +export const constants = { + NULL_ADDRESS: '0x0000000000000000000000000000000000000000', + TESTRPC_NETWORK_ID: 50, + INVALID_JUMP_PATTERN: 'invalid JUMP at', + OUT_OF_GAS_PATTERN: 'out of gas', + INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string', + UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), + DEFAULT_BLOCK_POLLING_INTERVAL: 1000, +}; diff --git a/packages/0x.js/src/utils/decorators.ts b/packages/contract-wrappers/src/utils/decorators.ts index f774d734e..64123143c 100644 --- a/packages/0x.js/src/utils/decorators.ts +++ b/packages/contract-wrappers/src/utils/decorators.ts @@ -1,6 +1,6 @@ import * as _ from 'lodash'; -import { AsyncMethod, SyncMethod, ZeroExError } from '../types'; +import { AsyncMethod, ContractWrappersError, SyncMethod } from '../types'; import { constants } from './constants'; @@ -8,10 +8,10 @@ type ErrorTransformer = (err: Error) => Error; const contractCallErrorTransformer = (error: Error) => { if (_.includes(error.message, constants.INVALID_JUMP_PATTERN)) { - return new Error(ZeroExError.InvalidJump); + return new Error(ContractWrappersError.InvalidJump); } if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) { - return new Error(ZeroExError.OutOfGas); + return new Error(ContractWrappersError.OutOfGas); } return error; }; diff --git a/packages/0x.js/src/utils/exchange_transfer_simulator.ts b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts index f8301f5c2..b575285a1 100644 --- a/packages/0x.js/src/utils/exchange_transfer_simulator.ts +++ b/packages/contract-wrappers/src/utils/exchange_transfer_simulator.ts @@ -1,10 +1,10 @@ -import { BlockParamLiteral } from '@0xproject/types'; +import { BlockParamLiteral, ExchangeContractErrs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import { TokenWrapper } from '../contract_wrappers/token_wrapper'; import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store'; -import { ExchangeContractErrs, TradeSide, TransferType } from '../types'; +import { TradeSide, TransferType } from '../types'; import { constants } from '../utils/constants'; enum FailureReason { diff --git a/packages/0x.js/src/utils/filter_utils.ts b/packages/contract-wrappers/src/utils/filter_utils.ts index c5df7321e..c5df7321e 100644 --- a/packages/0x.js/src/utils/filter_utils.ts +++ b/packages/contract-wrappers/src/utils/filter_utils.ts diff --git a/packages/0x.js/src/utils/order_validation_utils.ts b/packages/contract-wrappers/src/utils/order_validation_utils.ts index a13c3dc04..36dfbd800 100644 --- a/packages/0x.js/src/utils/order_validation_utils.ts +++ b/packages/contract-wrappers/src/utils/order_validation_utils.ts @@ -1,11 +1,10 @@ -import { getOrderHashHex, OrderError } from '@0xproject/order-utils'; -import { Order, SignedOrder } from '@0xproject/types'; +import { getOrderHashHex, isValidSignature, OrderError } from '@0xproject/order-utils'; +import { ExchangeContractErrs, Order, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; -import { ZeroEx } from '../0x'; import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; -import { ExchangeContractErrs, TradeSide, TransferType, ZeroExError } from '../types'; +import { ContractWrappersError, TradeSide, TransferType } from '../types'; import { constants } from '../utils/constants'; import { utils } from '../utils/utils'; @@ -144,7 +143,7 @@ export class OrderValidationUtils { throw new Error(ExchangeContractErrs.OrderFillAmountZero); } const orderHash = getOrderHashHex(signedOrder); - if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) { + if (!isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) { throw new Error(OrderError.InvalidSignature); } const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); diff --git a/packages/0x.js/src/utils/utils.ts b/packages/contract-wrappers/src/utils/utils.ts index af1125632..af1125632 100644 --- a/packages/0x.js/src/utils/utils.ts +++ b/packages/contract-wrappers/src/utils/utils.ts diff --git a/packages/contract-wrappers/test/artifacts_test.ts b/packages/contract-wrappers/test/artifacts_test.ts new file mode 100644 index 000000000..5d7261e09 --- /dev/null +++ b/packages/contract-wrappers/test/artifacts_test.ts @@ -0,0 +1,49 @@ +import { web3Factory } from '@0xproject/dev-utils'; +import * as fs from 'fs'; + +import { ContractWrappers } from '../src'; + +import { chaiSetup } from './utils/chai_setup'; +import { constants } from './utils/constants'; + +chaiSetup.configure(); + +// Those tests are slower cause they're talking to a remote node +const TIMEOUT = 10000; + +describe('Artifacts', () => { + describe('contracts are deployed on kovan', () => { + const kovanRpcUrl = constants.KOVAN_RPC_URL; + const provider = web3Factory.create({ rpcUrl: kovanRpcUrl }).currentProvider; + const config = { + networkId: constants.KOVAN_NETWORK_ID, + }; + const contractWrappers = new ContractWrappers(provider, config); + it('token registry contract is deployed', async () => { + await (contractWrappers.tokenRegistry as any)._getTokenRegistryContractAsync(); + }).timeout(TIMEOUT); + it('proxy contract is deployed', async () => { + await (contractWrappers.proxy as any)._getTokenTransferProxyContractAsync(); + }).timeout(TIMEOUT); + it('exchange contract is deployed', async () => { + await (contractWrappers.exchange as any)._getExchangeContractAsync(); + }).timeout(TIMEOUT); + }); + describe('contracts are deployed on ropsten', () => { + const ropstenRpcUrl = constants.ROPSTEN_RPC_URL; + const provider = web3Factory.create({ rpcUrl: ropstenRpcUrl }).currentProvider; + const config = { + networkId: constants.ROPSTEN_NETWORK_ID, + }; + const contractWrappers = new ContractWrappers(provider, config); + it('token registry contract is deployed', async () => { + await (contractWrappers.tokenRegistry as any)._getTokenRegistryContractAsync(); + }).timeout(TIMEOUT); + it('proxy contract is deployed', async () => { + await (contractWrappers.proxy as any)._getTokenTransferProxyContractAsync(); + }).timeout(TIMEOUT); + it('exchange contract is deployed', async () => { + await (contractWrappers.exchange as any)._getExchangeContractAsync(); + }).timeout(TIMEOUT); + }); +}); diff --git a/packages/0x.js/test/ether_token_wrapper_test.ts b/packages/contract-wrappers/test/ether_token_wrapper_test.ts index 99c42fe0b..e9a9705b1 100644 --- a/packages/0x.js/test/ether_token_wrapper_test.ts +++ b/packages/contract-wrappers/test/ether_token_wrapper_test.ts @@ -1,4 +1,5 @@ -import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { BlockchainLifecycle, callbackErrorReporter, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { DoneCallback } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; @@ -8,20 +9,18 @@ import { ApprovalContractEventArgs, BlockParamLiteral, BlockRange, + ContractWrappers, + ContractWrappersError, DecodedLogEvent, DepositContractEventArgs, EtherTokenEvents, Token, TransferContractEventArgs, WithdrawalContractEventArgs, - ZeroEx, - ZeroExError, } from '../src'; -import { DoneCallback } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -36,7 +35,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const MAX_REASONABLE_GAS_COST_IN_WEI = 62517; describe('EtherTokenWrapper', () => { - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; let tokens: Token[]; let userAddresses: string[]; let addressWithETH: string; @@ -54,11 +53,11 @@ describe('EtherTokenWrapper', () => { const depositAmount = new BigNumber(42); const withdrawalAmount = new BigNumber(42); before(async () => { - zeroEx = new ZeroEx(provider, zeroExConfig); - tokens = await zeroEx.tokenRegistry.getTokensAsync(); - userAddresses = await zeroEx.getAvailableAddressesAsync(); + contractWrappers = new ContractWrappers(provider, zeroExConfig); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); addressWithETH = userAddresses[0]; - wethContractAddress = zeroEx.etherToken.getContractAddressIfExists() as string; + wethContractAddress = contractWrappers.etherToken.getContractAddressIfExists() as string; depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5)); decimalPlaces = 7; addressWithoutFunds = userAddresses[1]; @@ -71,14 +70,14 @@ describe('EtherTokenWrapper', () => { }); describe('#getContractAddressIfExists', async () => { it('should return contract address if connected to a known network', () => { - const contractAddressIfExists = zeroEx.etherToken.getContractAddressIfExists(); + const contractAddressIfExists = contractWrappers.etherToken.getContractAddressIfExists(); expect(contractAddressIfExists).to.not.be.undefined(); }); it('should throw if connected to a private network and contract addresses are not specified', () => { const UNKNOWN_NETWORK_NETWORK_ID = 10; expect( () => - new ZeroEx(provider, { + new ContractWrappers(provider, { networkId: UNKNOWN_NETWORK_NETWORK_ID, } as any), ).to.throw(); @@ -86,16 +85,23 @@ describe('EtherTokenWrapper', () => { }); describe('#depositAsync', () => { it('should successfully deposit ETH and issue Wrapped ETH tokens', async () => { - const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); + const preWETHBalance = await contractWrappers.token.getBalanceAsync(wethContractAddress, addressWithETH); expect(preETHBalance).to.be.bignumber.gt(0); expect(preWETHBalance).to.be.bignumber.equal(0); - const txHash = await zeroEx.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH); - await zeroEx.awaitTransactionMinedAsync(txHash); + const txHash = await contractWrappers.etherToken.depositAsync( + wethContractAddress, + depositWeiAmount, + addressWithETH, + ); + await web3Wrapper.awaitTransactionMinedAsync(txHash); - const postETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + const postETHBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); + const postWETHBalanceInBaseUnits = await contractWrappers.token.getBalanceAsync( + wethContractAddress, + addressWithETH, + ); expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(depositWeiAmount); const remainingETHInWei = preETHBalance.minus(depositWeiAmount); @@ -103,34 +109,41 @@ describe('EtherTokenWrapper', () => { expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); }); it('should throw if user has insufficient ETH balance for deposit', async () => { - const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); + const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); const extraETHBalance = Web3Wrapper.toWei(new BigNumber(5)); const overETHBalanceinWei = preETHBalance.add(extraETHBalance); return expect( - zeroEx.etherToken.depositAsync(wethContractAddress, overETHBalanceinWei, addressWithETH), - ).to.be.rejectedWith(ZeroExError.InsufficientEthBalanceForDeposit); + contractWrappers.etherToken.depositAsync(wethContractAddress, overETHBalanceinWei, addressWithETH), + ).to.be.rejectedWith(ContractWrappersError.InsufficientEthBalanceForDeposit); }); }); describe('#withdrawAsync', () => { it('should successfully withdraw ETH in return for Wrapped ETH tokens', async () => { - const ETHBalanceInWei = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); + const ETHBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); - await zeroEx.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH); + await contractWrappers.etherToken.depositAsync(wethContractAddress, depositWeiAmount, addressWithETH); const expectedPreETHBalance = ETHBalanceInWei.minus(depositWeiAmount); - const preETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + const preETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); + const preWETHBalance = await contractWrappers.token.getBalanceAsync(wethContractAddress, addressWithETH); let gasCost = expectedPreETHBalance.minus(preETHBalance); expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); expect(preWETHBalance).to.be.bignumber.equal(depositWeiAmount); - const txHash = await zeroEx.etherToken.withdrawAsync(wethContractAddress, depositWeiAmount, addressWithETH); - await zeroEx.awaitTransactionMinedAsync(txHash); + const txHash = await contractWrappers.etherToken.withdrawAsync( + wethContractAddress, + depositWeiAmount, + addressWithETH, + ); + await web3Wrapper.awaitTransactionMinedAsync(txHash); - const postETHBalance = await (zeroEx as any)._web3Wrapper.getBalanceInWeiAsync(addressWithETH); - const postWETHBalanceInBaseUnits = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + const postETHBalance = await web3Wrapper.getBalanceInWeiAsync(addressWithETH); + const postWETHBalanceInBaseUnits = await contractWrappers.token.getBalanceAsync( + wethContractAddress, + addressWithETH, + ); expect(postWETHBalanceInBaseUnits).to.be.bignumber.equal(0); const expectedETHBalance = preETHBalance.add(depositWeiAmount).round(decimalPlaces); @@ -138,14 +151,14 @@ describe('EtherTokenWrapper', () => { expect(gasCost).to.be.bignumber.lte(MAX_REASONABLE_GAS_COST_IN_WEI); }); it('should throw if user has insufficient WETH balance for withdrawal', async () => { - const preWETHBalance = await zeroEx.token.getBalanceAsync(wethContractAddress, addressWithETH); + const preWETHBalance = await contractWrappers.token.getBalanceAsync(wethContractAddress, addressWithETH); expect(preWETHBalance).to.be.bignumber.equal(0); const overWETHBalance = preWETHBalance.add(999999999); return expect( - zeroEx.etherToken.withdrawAsync(wethContractAddress, overWETHBalance, addressWithETH), - ).to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal); + contractWrappers.etherToken.withdrawAsync(wethContractAddress, overWETHBalance, addressWithETH), + ).to.be.rejectedWith(ContractWrappersError.InsufficientWEthBalanceForWithdrawal); }); }); describe('#subscribe', () => { @@ -157,7 +170,7 @@ describe('EtherTokenWrapper', () => { etherTokenAddress = etherToken.address; }); afterEach(() => { - zeroEx.etherToken.unsubscribeAll(); + contractWrappers.etherToken.unsubscribeAll(); }); // Hack: Mocha does not allow a test to be both async and have a `done` callback // Since we need to await the receipt of the event in the `subscribe` callback, @@ -166,7 +179,7 @@ describe('EtherTokenWrapper', () => { // Source: https://github.com/mochajs/mocha/issues/2407 it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { (async () => { - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<TransferContractEventArgs>) => { expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); @@ -179,9 +192,14 @@ describe('EtherTokenWrapper', () => { expect(args._value).to.be.bignumber.equal(transferAmount); }, ); - await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); - zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callback); - await zeroEx.token.transferAsync( + await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); + contractWrappers.etherToken.subscribe( + etherTokenAddress, + EtherTokenEvents.Transfer, + indexFilterValues, + callback, + ); + await contractWrappers.token.transferAsync( etherTokenAddress, addressWithETH, addressWithoutFunds, @@ -191,7 +209,7 @@ describe('EtherTokenWrapper', () => { }); it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => { (async () => { - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => { expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); @@ -201,8 +219,13 @@ describe('EtherTokenWrapper', () => { expect(args._value).to.be.bignumber.equal(allowanceAmount); }, ); - zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Approval, indexFilterValues, callback); - await zeroEx.token.setAllowanceAsync( + contractWrappers.etherToken.subscribe( + etherTokenAddress, + EtherTokenEvents.Approval, + indexFilterValues, + callback, + ); + await contractWrappers.token.setAllowanceAsync( etherTokenAddress, addressWithETH, addressWithoutFunds, @@ -212,7 +235,7 @@ describe('EtherTokenWrapper', () => { }); it('Should receive the Deposit event when ether is being deposited', (done: DoneCallback) => { (async () => { - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<DepositContractEventArgs>) => { expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); @@ -221,13 +244,18 @@ describe('EtherTokenWrapper', () => { expect(args._value).to.be.bignumber.equal(depositAmount); }, ); - zeroEx.etherToken.subscribe(etherTokenAddress, EtherTokenEvents.Deposit, indexFilterValues, callback); - await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); + contractWrappers.etherToken.subscribe( + etherTokenAddress, + EtherTokenEvents.Deposit, + indexFilterValues, + callback, + ); + await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); })().catch(done); }); it('Should receive the Withdrawal event when ether is being withdrawn', (done: DoneCallback) => { (async () => { - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<WithdrawalContractEventArgs>) => { expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); @@ -236,39 +264,39 @@ describe('EtherTokenWrapper', () => { expect(args._value).to.be.bignumber.equal(depositAmount); }, ); - await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); - zeroEx.etherToken.subscribe( + await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); + contractWrappers.etherToken.subscribe( etherTokenAddress, EtherTokenEvents.Withdrawal, indexFilterValues, callback, ); - await zeroEx.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH); + await contractWrappers.etherToken.withdrawAsync(etherTokenAddress, withdrawalAmount, addressWithETH); })().catch(done); }); it('should cancel outstanding subscriptions when ZeroEx.setProvider is called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = reportNodeCallbackErrors(done)( + const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }, ); - zeroEx.etherToken.subscribe( + contractWrappers.etherToken.subscribe( etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled, ); - const callbackToBeCalled = reportNodeCallbackErrors(done)(); - zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID); - await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); - zeroEx.etherToken.subscribe( + const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); + contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); + contractWrappers.etherToken.subscribe( etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackToBeCalled, ); - await zeroEx.token.transferAsync( + await contractWrappers.token.transferAsync( etherTokenAddress, addressWithETH, addressWithoutFunds, @@ -278,20 +306,20 @@ describe('EtherTokenWrapper', () => { }); it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = reportNodeCallbackErrors(done)( + const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }, ); - await zeroEx.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); - const subscriptionToken = zeroEx.etherToken.subscribe( + await contractWrappers.etherToken.depositAsync(etherTokenAddress, transferAmount, addressWithETH); + const subscriptionToken = contractWrappers.etherToken.subscribe( etherTokenAddress, EtherTokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled, ); - zeroEx.etherToken.unsubscribe(subscriptionToken); - await zeroEx.token.transferAsync( + contractWrappers.etherToken.unsubscribe(subscriptionToken); + await contractWrappers.token.transferAsync( etherTokenAddress, addressWithETH, addressWithoutFunds, @@ -314,14 +342,14 @@ describe('EtherTokenWrapper', () => { const tokenUtils = new TokenUtils(tokens); const etherToken = tokenUtils.getWethTokenOrThrow(); etherTokenAddress = etherToken.address; - tokenTransferProxyAddress = zeroEx.proxy.getContractAddress(); + tokenTransferProxyAddress = contractWrappers.proxy.getContractAddress(); }); it('should get logs with decoded args emitted by Approval', async () => { - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const eventName = EtherTokenEvents.Approval; const indexFilterValues = {}; - const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>( + const logs = await contractWrappers.etherToken.getLogsAsync<ApprovalContractEventArgs>( etherTokenAddress, eventName, blockRange, @@ -332,13 +360,13 @@ describe('EtherTokenWrapper', () => { expect(logs[0].event).to.be.equal(eventName); expect(args._owner).to.be.equal(addressWithETH); expect(args._spender).to.be.equal(tokenTransferProxyAddress); - expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + expect(args._value).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); it('should get logs with decoded args emitted by Deposit', async () => { - await zeroEx.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); + await contractWrappers.etherToken.depositAsync(etherTokenAddress, depositAmount, addressWithETH); const eventName = EtherTokenEvents.Deposit; const indexFilterValues = {}; - const logs = await zeroEx.etherToken.getLogsAsync<DepositContractEventArgs>( + const logs = await contractWrappers.etherToken.getLogsAsync<DepositContractEventArgs>( etherTokenAddress, eventName, blockRange, @@ -351,11 +379,11 @@ describe('EtherTokenWrapper', () => { expect(args._value).to.be.bignumber.equal(depositAmount); }); it('should only get the logs with the correct event name', async () => { - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const differentEventName = EtherTokenEvents.Transfer; const indexFilterValues = {}; - const logs = await zeroEx.etherToken.getLogsAsync( + const logs = await contractWrappers.etherToken.getLogsAsync( etherTokenAddress, differentEventName, blockRange, @@ -364,15 +392,18 @@ describe('EtherTokenWrapper', () => { expect(logs).to.have.length(0); }); it('should only get the logs with the correct indexed fields', async () => { - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); - await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithoutFunds); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(etherTokenAddress, addressWithETH); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync( + etherTokenAddress, + addressWithoutFunds, + ); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const eventName = EtherTokenEvents.Approval; const indexFilterValues = { _owner: addressWithETH, }; - const logs = await zeroEx.etherToken.getLogsAsync<ApprovalContractEventArgs>( + const logs = await contractWrappers.etherToken.getLogsAsync<ApprovalContractEventArgs>( etherTokenAddress, eventName, blockRange, diff --git a/packages/0x.js/test/exchange_transfer_simulator_test.ts b/packages/contract-wrappers/test/exchange_transfer_simulator_test.ts index cb976a0ae..0011f0626 100644 --- a/packages/0x.js/test/exchange_transfer_simulator_test.ts +++ b/packages/contract-wrappers/test/exchange_transfer_simulator_test.ts @@ -1,9 +1,9 @@ import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; -import { BlockParamLiteral } from '@0xproject/types'; +import { BlockParamLiteral, Token } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; -import { ExchangeContractErrs, Token, ZeroEx } from '../src'; +import { ContractWrappers, ExchangeContractErrs } from '../src'; import { TradeSide, TransferType } from '../src/types'; import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator'; @@ -19,7 +19,7 @@ describe('ExchangeTransferSimulator', () => { const config = { networkId: constants.TESTRPC_NETWORK_ID, }; - const zeroEx = new ZeroEx(provider, config); + const contractWrappers = new ContractWrappers(provider, config); const transferAmount = new BigNumber(5); let userAddresses: string[]; let tokens: Token[]; @@ -30,9 +30,9 @@ describe('ExchangeTransferSimulator', () => { let exchangeTransferSimulator: ExchangeTransferSimulator; let txHash: string; before(async () => { - userAddresses = await zeroEx.getAvailableAddressesAsync(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); [coinbase, sender, recipient] = userAddresses; - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); exampleTokenAddress = tokens[0].address; }); beforeEach(async () => { @@ -43,7 +43,7 @@ describe('ExchangeTransferSimulator', () => { }); describe('#transferFromAsync', () => { beforeEach(() => { - exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest); + exchangeTransferSimulator = new ExchangeTransferSimulator(contractWrappers.token, BlockParamLiteral.Latest); }); it("throws if the user doesn't have enough allowance", async () => { return expect( @@ -58,8 +58,8 @@ describe('ExchangeTransferSimulator', () => { ).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance); }); it("throws if the user doesn't have enough balance", async () => { - txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount); + await web3Wrapper.awaitTransactionMinedAsync(txHash); return expect( exchangeTransferSimulator.transferFromAsync( exampleTokenAddress, @@ -72,10 +72,10 @@ describe('ExchangeTransferSimulator', () => { ).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance); }); it('updates balances and proxyAllowance after transfer', async () => { - txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount); - await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setProxyAllowanceAsync(exampleTokenAddress, sender, transferAmount); + await web3Wrapper.awaitTransactionMinedAsync(txHash); await exchangeTransferSimulator.transferFromAsync( exampleTokenAddress, sender, @@ -93,10 +93,10 @@ describe('ExchangeTransferSimulator', () => { expect(senderProxyAllowance).to.be.bignumber.equal(0); }); it("doesn't update proxyAllowance after transfer if unlimited", async () => { - txHash = await zeroEx.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount); - await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.transferAsync(exampleTokenAddress, coinbase, sender, transferAmount); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(exampleTokenAddress, sender); + await web3Wrapper.awaitTransactionMinedAsync(txHash); await exchangeTransferSimulator.transferFromAsync( exampleTokenAddress, sender, @@ -111,7 +111,7 @@ describe('ExchangeTransferSimulator', () => { const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender); expect(senderBalance).to.be.bignumber.equal(0); expect(recipientBalance).to.be.bignumber.equal(transferAmount); - expect(senderProxyAllowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + expect(senderProxyAllowance).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); }); }); diff --git a/packages/0x.js/test/exchange_wrapper_test.ts b/packages/contract-wrappers/test/exchange_wrapper_test.ts index 65f4e8251..fc0a23485 100644 --- a/packages/0x.js/test/exchange_wrapper_test.ts +++ b/packages/contract-wrappers/test/exchange_wrapper_test.ts @@ -1,12 +1,16 @@ -import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; -import { BlockParamLiteral } from '@0xproject/types'; +import { BlockchainLifecycle, callbackErrorReporter, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { FillScenarios } from '@0xproject/fill-scenarios'; +import { getOrderHashHex } from '@0xproject/order-utils'; +import { BlockParamLiteral, DoneCallback, OrderState } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; import { BlockRange, + ContractWrappers, DecodedLogEvent, ExchangeContractErrs, ExchangeEvents, @@ -14,17 +18,12 @@ import { LogFillContractEventArgs, OrderCancellationRequest, OrderFillRequest, - OrderState, SignedOrder, Token, - ZeroEx, } from '../src'; -import { DoneCallback } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { FillScenarios } from './utils/fill_scenarios'; -import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -35,7 +34,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const NON_EXISTENT_ORDER_HASH = '0x79370342234e7acd6bbeac335bd3bb1d368383294b64b8160a00f4060e4d3777'; describe('ExchangeWrapper', () => { - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; let tokenUtils: TokenUtils; let tokens: Token[]; let userAddresses: string[]; @@ -46,13 +45,13 @@ describe('ExchangeWrapper', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(provider, config); - exchangeContractAddress = zeroEx.exchange.getContractAddress(); - userAddresses = await zeroEx.getAvailableAddressesAsync(); - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + contractWrappers = new ContractWrappers(provider, config); + exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); tokenUtils = new TokenUtils(tokens); zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address; - fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress); + fillScenarios = new FillScenarios(provider, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress); await fillScenarios.initTokenBalancesAsync(); }); beforeEach(async () => { @@ -71,7 +70,7 @@ describe('ExchangeWrapper', () => { const takerTokenFillAmount = new BigNumber(5); before(async () => { [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses; - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); const [makerToken, takerToken] = tokenUtils.getDummyTokens(); makerTokenAddress = makerToken.address; takerTokenAddress = takerToken.address; @@ -104,7 +103,7 @@ describe('ExchangeWrapper', () => { takerTokenFillAmount: partialFillTakerAmount, }, ]; - await zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress); + await contractWrappers.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress); }); describe('order transaction options', () => { let signedOrder: SignedOrder; @@ -127,19 +126,19 @@ describe('ExchangeWrapper', () => { }); it('should validate when orderTransactionOptions are not present', async () => { return expect( - zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress), + contractWrappers.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress), ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); }); it('should validate when orderTransactionOptions specify to validate', async () => { return expect( - zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, { + contractWrappers.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, { shouldValidate: true, }), ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); }); it('should not validate when orderTransactionOptions specify not to validate', async () => { return expect( - zeroEx.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, { + contractWrappers.exchange.batchFillOrKillAsync(orderFillRequests, takerAddress, { shouldValidate: false, }), ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); @@ -160,66 +159,70 @@ describe('ExchangeWrapper', () => { }); describe('successful fills', () => { it('should fill a valid order', async () => { - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal( - fillableAmount, - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal( - 0, - ); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal( - 0, - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal( - fillableAmount, - ); - await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal( - fillableAmount.minus(takerTokenFillAmount), - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal( - takerTokenFillAmount, - ); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal( + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, makerAddress), + ).to.be.bignumber.equal(fillableAmount); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, makerAddress), + ).to.be.bignumber.equal(0); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, takerAddress), + ).to.be.bignumber.equal(0); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, takerAddress), + ).to.be.bignumber.equal(fillableAmount); + await contractWrappers.exchange.fillOrKillOrderAsync( + signedOrder, takerTokenFillAmount, + takerAddress, ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal( - fillableAmount.minus(takerTokenFillAmount), - ); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, makerAddress), + ).to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount)); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, makerAddress), + ).to.be.bignumber.equal(takerTokenFillAmount); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, takerAddress), + ).to.be.bignumber.equal(takerTokenFillAmount); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, takerAddress), + ).to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount)); }); it('should partially fill a valid order', async () => { const partialFillAmount = new BigNumber(3); - await zeroEx.exchange.fillOrKillOrderAsync(signedOrder, partialFillAmount, takerAddress); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal( - fillableAmount.minus(partialFillAmount), - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal( - partialFillAmount, - ); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal( - partialFillAmount, - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal( - fillableAmount.minus(partialFillAmount), - ); + await contractWrappers.exchange.fillOrKillOrderAsync(signedOrder, partialFillAmount, takerAddress); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, makerAddress), + ).to.be.bignumber.equal(fillableAmount.minus(partialFillAmount)); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, makerAddress), + ).to.be.bignumber.equal(partialFillAmount); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, takerAddress), + ).to.be.bignumber.equal(partialFillAmount); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, takerAddress), + ).to.be.bignumber.equal(fillableAmount.minus(partialFillAmount)); }); }); describe('order transaction options', () => { const emptyFillableAmount = new BigNumber(0); it('should validate when orderTransactionOptions are not present', async () => { return expect( - zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress), + contractWrappers.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress), ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); }); it('should validate when orderTransactionOptions specify to validate', async () => { return expect( - zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, { + contractWrappers.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, { shouldValidate: true, }), ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); }); it('should not validate when orderTransactionOptions specify not to validate', async () => { return expect( - zeroEx.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, { + contractWrappers.exchange.fillOrKillOrderAsync(signedOrder, emptyFillableAmount, takerAddress, { shouldValidate: false, }), ).to.not.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); @@ -239,7 +242,7 @@ describe('ExchangeWrapper', () => { const shouldThrowOnInsufficientBalanceOrAllowance = true; before(async () => { [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses; - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); const [makerToken, takerToken] = tokenUtils.getDummyTokens(); makerTokenAddress = makerToken.address; takerTokenAddress = takerToken.address; @@ -254,37 +257,37 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal( - fillableAmount, - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal( - 0, - ); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal( - 0, - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal( - fillableAmount, - ); - const txHash = await zeroEx.exchange.fillOrderAsync( + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, makerAddress), + ).to.be.bignumber.equal(fillableAmount); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, makerAddress), + ).to.be.bignumber.equal(0); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, takerAddress), + ).to.be.bignumber.equal(0); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, takerAddress), + ).to.be.bignumber.equal(fillableAmount); + const txHash = await contractWrappers.exchange.fillOrderAsync( signedOrder, takerTokenFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal( - fillableAmount.minus(takerTokenFillAmount), - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal( - takerTokenFillAmount, - ); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal( - takerTokenFillAmount, - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal( - fillableAmount.minus(takerTokenFillAmount), - ); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, makerAddress), + ).to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount)); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, makerAddress), + ).to.be.bignumber.equal(takerTokenFillAmount); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, takerAddress), + ).to.be.bignumber.equal(takerTokenFillAmount); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, takerAddress), + ).to.be.bignumber.equal(fillableAmount.minus(takerTokenFillAmount)); }); it('should partially fill the valid order', async () => { const signedOrder = await fillScenarios.createFillableSignedOrderAsync( @@ -295,25 +298,25 @@ describe('ExchangeWrapper', () => { fillableAmount, ); const partialFillAmount = new BigNumber(3); - const txHash = await zeroEx.exchange.fillOrderAsync( + const txHash = await contractWrappers.exchange.fillOrderAsync( signedOrder, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, makerAddress)).to.be.bignumber.equal( - fillableAmount.minus(partialFillAmount), - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, makerAddress)).to.be.bignumber.equal( - partialFillAmount, - ); - expect(await zeroEx.token.getBalanceAsync(makerTokenAddress, takerAddress)).to.be.bignumber.equal( - partialFillAmount, - ); - expect(await zeroEx.token.getBalanceAsync(takerTokenAddress, takerAddress)).to.be.bignumber.equal( - fillableAmount.minus(partialFillAmount), - ); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, makerAddress), + ).to.be.bignumber.equal(fillableAmount.minus(partialFillAmount)); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, makerAddress), + ).to.be.bignumber.equal(partialFillAmount); + expect( + await contractWrappers.token.getBalanceAsync(makerTokenAddress, takerAddress), + ).to.be.bignumber.equal(partialFillAmount); + expect( + await contractWrappers.token.getBalanceAsync(takerTokenAddress, takerAddress), + ).to.be.bignumber.equal(fillableAmount.minus(partialFillAmount)); }); it('should fill the valid orders with fees', async () => { const makerFee = new BigNumber(1); @@ -328,16 +331,16 @@ describe('ExchangeWrapper', () => { fillableAmount, feeRecipient, ); - const txHash = await zeroEx.exchange.fillOrderAsync( + const txHash = await contractWrappers.exchange.fillOrderAsync( signedOrder, takerTokenFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); - expect(await zeroEx.token.getBalanceAsync(zrxTokenAddress, feeRecipient)).to.be.bignumber.equal( - makerFee.plus(takerFee), - ); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + expect( + await contractWrappers.token.getBalanceAsync(zrxTokenAddress, feeRecipient), + ).to.be.bignumber.equal(makerFee.plus(takerFee)); }); }); describe('order transaction options', () => { @@ -354,7 +357,7 @@ describe('ExchangeWrapper', () => { }); it('should validate when orderTransactionOptions are not present', async () => { return expect( - zeroEx.exchange.fillOrderAsync( + contractWrappers.exchange.fillOrderAsync( signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -364,7 +367,7 @@ describe('ExchangeWrapper', () => { }); it('should validate when orderTransactionOptions specify to validate', async () => { return expect( - zeroEx.exchange.fillOrderAsync( + contractWrappers.exchange.fillOrderAsync( signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -377,7 +380,7 @@ describe('ExchangeWrapper', () => { }); it('should not validate when orderTransactionOptions specify not to validate', async () => { return expect( - zeroEx.exchange.fillOrderAsync( + contractWrappers.exchange.fillOrderAsync( signedOrder, emptyFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -403,7 +406,7 @@ describe('ExchangeWrapper', () => { }); it('should not allow the exchange wrapper to fill if amount is negative', async () => { return expect( - zeroEx.exchange.fillOrderAsync( + contractWrappers.exchange.fillOrderAsync( signedOrder, negativeFillTakerAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -427,7 +430,7 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder); + signedOrderHashHex = getOrderHashHex(signedOrder); anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, @@ -435,7 +438,7 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder); + anotherOrderHashHex = getOrderHashHex(anotherSignedOrder); }); describe('successful batch fills', () => { beforeEach(() => { @@ -452,7 +455,7 @@ describe('ExchangeWrapper', () => { }); it('should throw if a batch is empty', async () => { return expect( - zeroEx.exchange.batchFillOrdersAsync( + contractWrappers.exchange.batchFillOrdersAsync( [], shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, @@ -460,14 +463,16 @@ describe('ExchangeWrapper', () => { ).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); }); it('should successfully fill multiple orders', async () => { - const txHash = await zeroEx.exchange.batchFillOrdersAsync( + const txHash = await contractWrappers.exchange.batchFillOrdersAsync( orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); - const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex); - const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + const filledAmount = await contractWrappers.exchange.getFilledTakerAmountAsync(signedOrderHashHex); + const anotherFilledAmount = await contractWrappers.exchange.getFilledTakerAmountAsync( + anotherOrderHashHex, + ); expect(filledAmount).to.be.bignumber.equal(takerTokenFillAmount); expect(anotherFilledAmount).to.be.bignumber.equal(takerTokenFillAmount); }); @@ -488,7 +493,7 @@ describe('ExchangeWrapper', () => { }); it('should validate when orderTransactionOptions are not present', async () => { return expect( - zeroEx.exchange.batchFillOrdersAsync( + contractWrappers.exchange.batchFillOrdersAsync( orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, @@ -497,7 +502,7 @@ describe('ExchangeWrapper', () => { }); it('should validate when orderTransactionOptions specify to validate', async () => { return expect( - zeroEx.exchange.batchFillOrdersAsync( + contractWrappers.exchange.batchFillOrdersAsync( orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, @@ -509,7 +514,7 @@ describe('ExchangeWrapper', () => { }); it('should not validate when orderTransactionOptions specify not to validate', async () => { return expect( - zeroEx.exchange.batchFillOrdersAsync( + contractWrappers.exchange.batchFillOrdersAsync( orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, @@ -536,7 +541,7 @@ describe('ExchangeWrapper', () => { }); it('should not allow the exchange wrapper to batch fill if any amount is negative', async () => { return expect( - zeroEx.exchange.batchFillOrdersAsync( + contractWrappers.exchange.batchFillOrdersAsync( orderFillBatch, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, @@ -560,7 +565,7 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - signedOrderHashHex = ZeroEx.getOrderHashHex(signedOrder); + signedOrderHashHex = getOrderHashHex(signedOrder); anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( makerTokenAddress, takerTokenAddress, @@ -568,13 +573,13 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder); + anotherOrderHashHex = getOrderHashHex(anotherSignedOrder); signedOrders = [signedOrder, anotherSignedOrder]; }); describe('successful batch fills', () => { it('should throw if a batch is empty', async () => { return expect( - zeroEx.exchange.fillOrdersUpToAsync( + contractWrappers.exchange.fillOrdersUpToAsync( [], fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -583,45 +588,54 @@ describe('ExchangeWrapper', () => { ).to.be.rejectedWith(ExchangeContractErrs.BatchOrdersMustHaveAtLeastOneItem); }); it('should successfully fill up to specified amount when all orders are fully funded', async () => { - const txHash = await zeroEx.exchange.fillOrdersUpToAsync( + const txHash = await contractWrappers.exchange.fillOrdersUpToAsync( signedOrders, fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); - const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex); - const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + const filledAmount = await contractWrappers.exchange.getFilledTakerAmountAsync(signedOrderHashHex); + const anotherFilledAmount = await contractWrappers.exchange.getFilledTakerAmountAsync( + anotherOrderHashHex, + ); expect(filledAmount).to.be.bignumber.equal(fillableAmount); const remainingFillAmount = fillableAmount.minus(1); expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount); }); it('should successfully fill up to specified amount and leave the rest of the orders untouched', async () => { - const txHash = await zeroEx.exchange.fillOrdersUpToAsync( + const txHash = await contractWrappers.exchange.fillOrdersUpToAsync( signedOrders, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); - const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex); - const zeroAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + const filledAmount = await contractWrappers.exchange.getFilledTakerAmountAsync(signedOrderHashHex); + const zeroAmount = await contractWrappers.exchange.getFilledTakerAmountAsync(anotherOrderHashHex); expect(filledAmount).to.be.bignumber.equal(fillableAmount); expect(zeroAmount).to.be.bignumber.equal(0); }); it('should successfully fill up to specified amount even if filling all orders would fail', async () => { const missingBalance = new BigNumber(1); // User will still have enough balance to fill up to 9, // but won't have 10 to fully fill all orders in a batch. - await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, missingBalance); - const txHash = await zeroEx.exchange.fillOrdersUpToAsync( + await contractWrappers.token.transferAsync( + makerTokenAddress, + makerAddress, + coinbase, + missingBalance, + ); + const txHash = await contractWrappers.exchange.fillOrdersUpToAsync( signedOrders, fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); - const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex); - const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + const filledAmount = await contractWrappers.exchange.getFilledTakerAmountAsync(signedOrderHashHex); + const anotherFilledAmount = await contractWrappers.exchange.getFilledTakerAmountAsync( + anotherOrderHashHex, + ); expect(filledAmount).to.be.bignumber.equal(fillableAmount); const remainingFillAmount = fillableAmount.minus(1); expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount); @@ -630,9 +644,14 @@ describe('ExchangeWrapper', () => { describe('failed batch fills', () => { it("should fail validation if user doesn't have enough balance without fill up to", async () => { const missingBalance = new BigNumber(2); // User will only have enough balance to fill up to 8 - await zeroEx.token.transferAsync(makerTokenAddress, makerAddress, coinbase, missingBalance); + await contractWrappers.token.transferAsync( + makerTokenAddress, + makerAddress, + coinbase, + missingBalance, + ); return expect( - zeroEx.exchange.fillOrdersUpToAsync( + contractWrappers.exchange.fillOrdersUpToAsync( signedOrders, fillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -645,7 +664,7 @@ describe('ExchangeWrapper', () => { const emptyFillUpToAmount = new BigNumber(0); it('should validate when orderTransactionOptions are not present', async () => { return expect( - zeroEx.exchange.fillOrdersUpToAsync( + contractWrappers.exchange.fillOrdersUpToAsync( signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -655,7 +674,7 @@ describe('ExchangeWrapper', () => { }); it('should validate when orderTransactionOptions specify to validate', async () => { return expect( - zeroEx.exchange.fillOrdersUpToAsync( + contractWrappers.exchange.fillOrdersUpToAsync( signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -668,7 +687,7 @@ describe('ExchangeWrapper', () => { }); it('should not validate when orderTransactionOptions specify not to validate', async () => { return expect( - zeroEx.exchange.fillOrdersUpToAsync( + contractWrappers.exchange.fillOrdersUpToAsync( signedOrders, emptyFillUpToAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -704,14 +723,14 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - orderHashHex = ZeroEx.getOrderHashHex(signedOrder); + orderHashHex = getOrderHashHex(signedOrder); }); describe('#cancelOrderAsync', () => { describe('successful cancels', () => { it('should cancel an order', async () => { - const txHash = await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount); - await zeroEx.awaitTransactionMinedAsync(txHash); - const cancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHashHex); + const txHash = await contractWrappers.exchange.cancelOrderAsync(signedOrder, cancelAmount); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + const cancelledAmount = await contractWrappers.exchange.getCancelledTakerAmountAsync(orderHashHex); expect(cancelledAmount).to.be.bignumber.equal(cancelAmount); }); }); @@ -719,19 +738,19 @@ describe('ExchangeWrapper', () => { const emptyCancelTakerTokenAmount = new BigNumber(0); it('should validate when orderTransactionOptions are not present', async () => { return expect( - zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount), + contractWrappers.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount), ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero); }); it('should validate when orderTransactionOptions specify to validate', async () => { return expect( - zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, { + contractWrappers.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, { shouldValidate: true, }), ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero); }); it('should not validate when orderTransactionOptions specify not to validate', async () => { return expect( - zeroEx.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, { + contractWrappers.exchange.cancelOrderAsync(signedOrder, emptyCancelTakerTokenAmount, { shouldValidate: false, }), ).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero); @@ -750,7 +769,7 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - anotherOrderHashHex = ZeroEx.getOrderHashHex(anotherSignedOrder); + anotherOrderHashHex = getOrderHashHex(anotherSignedOrder); cancelBatch = [ { order: signedOrder, @@ -772,7 +791,7 @@ describe('ExchangeWrapper', () => { fillableAmount, ); return expect( - zeroEx.exchange.batchCancelOrdersAsync([ + contractWrappers.exchange.batchCancelOrdersAsync([ cancelBatch[0], { order: signedOrderWithDifferentMaker, @@ -784,9 +803,9 @@ describe('ExchangeWrapper', () => { }); describe('successful batch cancels', () => { it('should cancel a batch of orders', async () => { - await zeroEx.exchange.batchCancelOrdersAsync(cancelBatch); - const cancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHashHex); - const anotherCancelledAmount = await zeroEx.exchange.getCancelledTakerAmountAsync( + await contractWrappers.exchange.batchCancelOrdersAsync(cancelBatch); + const cancelledAmount = await contractWrappers.exchange.getCancelledTakerAmountAsync(orderHashHex); + const anotherCancelledAmount = await contractWrappers.exchange.getCancelledTakerAmountAsync( anotherOrderHashHex, ); expect(cancelledAmount).to.be.bignumber.equal(cancelAmount); @@ -808,20 +827,20 @@ describe('ExchangeWrapper', () => { ]; }); it('should validate when orderTransactionOptions are not present', async () => { - return expect(zeroEx.exchange.batchCancelOrdersAsync(cancelBatch)).to.be.rejectedWith( + return expect(contractWrappers.exchange.batchCancelOrdersAsync(cancelBatch)).to.be.rejectedWith( ExchangeContractErrs.OrderCancelAmountZero, ); }); it('should validate when orderTransactionOptions specify to validate', async () => { return expect( - zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, { + contractWrappers.exchange.batchCancelOrdersAsync(cancelBatch, { shouldValidate: true, }), ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero); }); it('should not validate when orderTransactionOptions specify not to validate', async () => { return expect( - zeroEx.exchange.batchCancelOrdersAsync(cancelBatch, { + contractWrappers.exchange.batchCancelOrdersAsync(cancelBatch, { shouldValidate: false, }), ).to.not.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero); @@ -854,53 +873,63 @@ describe('ExchangeWrapper', () => { fillableAmount, partialFillAmount, ); - orderHash = ZeroEx.getOrderHashHex(signedOrder); + orderHash = getOrderHashHex(signedOrder); }); describe('#getUnavailableTakerAmountAsync', () => { it('should throw if passed an invalid orderHash', async () => { const invalidOrderHashHex = '0x123'; - return expect(zeroEx.exchange.getUnavailableTakerAmountAsync(invalidOrderHashHex)).to.be.rejected(); + return expect( + contractWrappers.exchange.getUnavailableTakerAmountAsync(invalidOrderHashHex), + ).to.be.rejected(); }); it('should return zero if passed a valid but non-existent orderHash', async () => { - const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(NON_EXISTENT_ORDER_HASH); + const unavailableValueT = await contractWrappers.exchange.getUnavailableTakerAmountAsync( + NON_EXISTENT_ORDER_HASH, + ); expect(unavailableValueT).to.be.bignumber.equal(0); }); it('should return the unavailableValueT for a valid and partially filled orderHash', async () => { - const unavailableValueT = await zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash); + const unavailableValueT = await contractWrappers.exchange.getUnavailableTakerAmountAsync(orderHash); expect(unavailableValueT).to.be.bignumber.equal(partialFillAmount); }); }); describe('#getFilledTakerAmountAsync', () => { it('should throw if passed an invalid orderHash', async () => { const invalidOrderHashHex = '0x123'; - return expect(zeroEx.exchange.getFilledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected(); + return expect( + contractWrappers.exchange.getFilledTakerAmountAsync(invalidOrderHashHex), + ).to.be.rejected(); }); it('should return zero if passed a valid but non-existent orderHash', async () => { - const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(NON_EXISTENT_ORDER_HASH); + const filledValueT = await contractWrappers.exchange.getFilledTakerAmountAsync(NON_EXISTENT_ORDER_HASH); expect(filledValueT).to.be.bignumber.equal(0); }); it('should return the filledValueT for a valid and partially filled orderHash', async () => { - const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(orderHash); + const filledValueT = await contractWrappers.exchange.getFilledTakerAmountAsync(orderHash); expect(filledValueT).to.be.bignumber.equal(partialFillAmount); }); }); describe('#getCancelledTakerAmountAsync', () => { it('should throw if passed an invalid orderHash', async () => { const invalidOrderHashHex = '0x123'; - return expect(zeroEx.exchange.getCancelledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected(); + return expect( + contractWrappers.exchange.getCancelledTakerAmountAsync(invalidOrderHashHex), + ).to.be.rejected(); }); it('should return zero if passed a valid but non-existent orderHash', async () => { - const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(NON_EXISTENT_ORDER_HASH); + const cancelledValueT = await contractWrappers.exchange.getCancelledTakerAmountAsync( + NON_EXISTENT_ORDER_HASH, + ); expect(cancelledValueT).to.be.bignumber.equal(0); }); it('should return the cancelledValueT for a valid and partially filled orderHash', async () => { - const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHash); + const cancelledValueT = await contractWrappers.exchange.getCancelledTakerAmountAsync(orderHash); expect(cancelledValueT).to.be.bignumber.equal(0); }); it('should return the cancelledValueT for a valid and cancelled orderHash', async () => { const cancelAmount = fillableAmount.minus(partialFillAmount); - await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount); - const cancelledValueT = await zeroEx.exchange.getCancelledTakerAmountAsync(orderHash); + await contractWrappers.exchange.cancelOrderAsync(signedOrder, cancelAmount); + const cancelledValueT = await contractWrappers.exchange.getCancelledTakerAmountAsync(orderHash); expect(cancelledValueT).to.be.bignumber.equal(cancelAmount); }); }); @@ -934,7 +963,7 @@ describe('ExchangeWrapper', () => { ); }); afterEach(async () => { - zeroEx.exchange.unsubscribeAll(); + contractWrappers.exchange.unsubscribeAll(); }); // Hack: Mocha does not allow a test to be both async and have a `done` callback // Since we need to await the receipt of the event in the `subscribe` callback, @@ -943,13 +972,13 @@ describe('ExchangeWrapper', () => { // Source: https://github.com/mochajs/mocha/issues/2407 it('Should receive the LogFill event when an order is filled', (done: DoneCallback) => { (async () => { - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => { expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogFill); }, ); - zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callback); - await zeroEx.exchange.fillOrderAsync( + contractWrappers.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callback); + await contractWrappers.exchange.fillOrderAsync( signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, @@ -959,33 +988,33 @@ describe('ExchangeWrapper', () => { }); it('Should receive the LogCancel event when an order is cancelled', (done: DoneCallback) => { (async () => { - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<LogCancelContractEventArgs>) => { expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogCancel); }, ); - zeroEx.exchange.subscribe(ExchangeEvents.LogCancel, indexFilterValues, callback); - await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits); + contractWrappers.exchange.subscribe(ExchangeEvents.LogCancel, indexFilterValues, callback); + await contractWrappers.exchange.cancelOrderAsync(signedOrder, cancelTakerAmountInBaseUnits); })().catch(done); }); - it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = reportNodeCallbackErrors(done)( + const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }, ); - zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled); + contractWrappers.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled); - zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => { expect(logEvent.log.event).to.be.equal(ExchangeEvents.LogFill); }, ); - zeroEx.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callback); - await zeroEx.exchange.fillOrderAsync( + contractWrappers.exchange.subscribe(ExchangeEvents.LogFill, indexFilterValues, callback); + await contractWrappers.exchange.fillOrderAsync( signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, @@ -995,18 +1024,18 @@ describe('ExchangeWrapper', () => { }); it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = reportNodeCallbackErrors(done)( + const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<LogFillContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }, ); - const subscriptionToken = zeroEx.exchange.subscribe( + const subscriptionToken = contractWrappers.exchange.subscribe( ExchangeEvents.LogFill, indexFilterValues, callbackNeverToBeCalled, ); - zeroEx.exchange.unsubscribe(subscriptionToken); - await zeroEx.exchange.fillOrderAsync( + contractWrappers.exchange.unsubscribe(subscriptionToken); + await contractWrappers.exchange.fillOrderAsync( signedOrder, takerTokenFillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, @@ -1036,8 +1065,8 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - const orderHashFromContract = await (zeroEx.exchange as any)._getOrderHashHexUsingContractCallAsync( + const orderHash = getOrderHashHex(signedOrder); + const orderHashFromContract = await (contractWrappers.exchange as any)._getOrderHashHexUsingContractCallAsync( signedOrder, ); expect(orderHash).to.equal(orderHashFromContract); @@ -1045,7 +1074,7 @@ describe('ExchangeWrapper', () => { }); describe('#getZRXTokenAddressAsync', () => { it('gets the same token as is in token registry', () => { - const zrxAddress = zeroEx.exchange.getZRXTokenAddress(); + const zrxAddress = contractWrappers.exchange.getZRXTokenAddress(); const zrxToken = tokenUtils.getProtocolTokenOrThrow(); expect(zrxAddress).to.equal(zrxToken.address); }); @@ -1076,16 +1105,16 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - txHash = await zeroEx.exchange.fillOrderAsync( + txHash = await contractWrappers.exchange.fillOrderAsync( signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const eventName = ExchangeEvents.LogFill; const indexFilterValues = {}; - const logs = await zeroEx.exchange.getLogsAsync(eventName, blockRange, indexFilterValues); + const logs = await contractWrappers.exchange.getLogsAsync(eventName, blockRange, indexFilterValues); expect(logs).to.have.length(1); expect(logs[0].event).to.be.equal(eventName); }); @@ -1097,16 +1126,20 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - txHash = await zeroEx.exchange.fillOrderAsync( + txHash = await contractWrappers.exchange.fillOrderAsync( signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const differentEventName = ExchangeEvents.LogCancel; const indexFilterValues = {}; - const logs = await zeroEx.exchange.getLogsAsync(differentEventName, blockRange, indexFilterValues); + const logs = await contractWrappers.exchange.getLogsAsync( + differentEventName, + blockRange, + indexFilterValues, + ); expect(logs).to.have.length(0); }); it('should only get the logs with the correct indexed fields', async () => { @@ -1117,13 +1150,13 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - txHash = await zeroEx.exchange.fillOrderAsync( + txHash = await contractWrappers.exchange.fillOrderAsync( signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const differentMakerAddress = userAddresses[2]; const anotherSignedOrder = await fillScenarios.createFillableSignedOrderAsync( @@ -1133,19 +1166,19 @@ describe('ExchangeWrapper', () => { takerAddress, fillableAmount, ); - txHash = await zeroEx.exchange.fillOrderAsync( + txHash = await contractWrappers.exchange.fillOrderAsync( anotherSignedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, takerAddress, ); - await zeroEx.awaitTransactionMinedAsync(txHash); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const eventName = ExchangeEvents.LogFill; const indexFilterValues = { maker: differentMakerAddress, }; - const logs = await zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>( + const logs = await contractWrappers.exchange.getLogsAsync<LogFillContractEventArgs>( eventName, blockRange, indexFilterValues, @@ -1162,10 +1195,10 @@ describe('ExchangeWrapper', () => { let takerToken: Token; let signedOrder: SignedOrder; let orderState: OrderState; - const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), constants.ZRX_DECIMALS); + const fillableAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(5), constants.ZRX_DECIMALS); before(async () => { [, maker, taker] = userAddresses; - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); [makerToken, takerToken] = tokenUtils.getDummyTokens(); }); it('should report orderStateValid when order is fillable', async () => { @@ -1176,7 +1209,7 @@ describe('ExchangeWrapper', () => { taker, fillableAmount, ); - orderState = await zeroEx.exchange.getOrderStateAsync(signedOrder); + orderState = await contractWrappers.exchange.getOrderStateAsync(signedOrder); expect(orderState.isValid).to.be.true(); }); it('should report orderStateInvalid when maker allowance set to 0', async () => { @@ -1187,8 +1220,8 @@ describe('ExchangeWrapper', () => { taker, fillableAmount, ); - await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0)); - orderState = await zeroEx.exchange.getOrderStateAsync(signedOrder); + await contractWrappers.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0)); + orderState = await contractWrappers.exchange.getOrderStateAsync(signedOrder); expect(orderState.isValid).to.be.false(); }); }); diff --git a/packages/contract-wrappers/test/global_hooks.ts b/packages/contract-wrappers/test/global_hooks.ts new file mode 100644 index 000000000..e3c986524 --- /dev/null +++ b/packages/contract-wrappers/test/global_hooks.ts @@ -0,0 +1,7 @@ +import { runMigrationsAsync } from '@0xproject/migrations'; + +import { deployer } from './utils/deployer'; + +before('migrate contracts', async () => { + await runMigrationsAsync(deployer); +}); diff --git a/packages/0x.js/test/order_validation_test.ts b/packages/contract-wrappers/test/order_validation_test.ts index 0cb95c1b6..d28549ba2 100644 --- a/packages/0x.js/test/order_validation_test.ts +++ b/packages/contract-wrappers/test/order_validation_test.ts @@ -1,18 +1,18 @@ import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; +import { FillScenarios } from '@0xproject/fill-scenarios'; import { OrderError } from '@0xproject/order-utils'; import { BlockParamLiteral } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import * as Sinon from 'sinon'; -import { ExchangeContractErrs, SignedOrder, Token, ZeroEx, ZeroExError } from '../src'; +import { ContractWrappers, ContractWrappersError, ExchangeContractErrs, SignedOrder, Token } from '../src'; import { TradeSide, TransferType } from '../src/types'; import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator'; import { OrderValidationUtils } from '../src/utils/order_validation_utils'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { FillScenarios } from './utils/fill_scenarios'; import { TokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -21,7 +21,7 @@ const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('OrderValidation', () => { - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; let userAddresses: string[]; let tokens: Token[]; let tokenUtils: TokenUtils; @@ -40,14 +40,14 @@ describe('OrderValidation', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(provider, config); - exchangeContractAddress = zeroEx.exchange.getContractAddress(); - userAddresses = await zeroEx.getAvailableAddressesAsync(); + contractWrappers = new ContractWrappers(provider, config); + exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses; - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); tokenUtils = new TokenUtils(tokens); zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address; - fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress); + fillScenarios = new FillScenarios(provider, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress); const [makerToken, takerToken] = tokenUtils.getDummyTokens(); makerTokenAddress = makerToken.address; takerTokenAddress = takerToken.address; @@ -67,7 +67,7 @@ describe('OrderValidation', () => { takerAddress, fillableAmount, ); - await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder); + await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder); }); it('should succeed if the maker is buying ZRX and has no ZRX balance', async () => { const makerFee = new BigNumber(2); @@ -82,9 +82,9 @@ describe('OrderValidation', () => { fillableAmount, feeRecipient, ); - const zrxMakerBalance = await zeroEx.token.getBalanceAsync(zrxTokenAddress, makerAddress); - await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance); - await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder); + const zrxMakerBalance = await contractWrappers.token.getBalanceAsync(zrxTokenAddress, makerAddress); + await contractWrappers.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance); + await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder); }); it('should succeed if the maker is buying ZRX and has no ZRX balance and there is no specified taker', async () => { const makerFee = new BigNumber(2); @@ -99,9 +99,9 @@ describe('OrderValidation', () => { fillableAmount, feeRecipient, ); - const zrxMakerBalance = await zeroEx.token.getBalanceAsync(zrxTokenAddress, makerAddress); - await zeroEx.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance); - await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder); + const zrxMakerBalance = await contractWrappers.token.getBalanceAsync(zrxTokenAddress, makerAddress); + await contractWrappers.token.transferAsync(zrxTokenAddress, makerAddress, takerAddress, zrxMakerBalance); + await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder); }); it('should succeed if the order is asymmetric and fillable', async () => { const makerFillableAmount = fillableAmount; @@ -114,7 +114,7 @@ describe('OrderValidation', () => { makerFillableAmount, takerFillableAmount, ); - await zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder); + await contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder); }); it('should throw when the order is fully filled or cancelled', async () => { const signedOrder = await fillScenarios.createFillableSignedOrderAsync( @@ -124,8 +124,8 @@ describe('OrderValidation', () => { takerAddress, fillableAmount, ); - await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount); - return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith( + await contractWrappers.exchange.cancelOrderAsync(signedOrder, fillableAmount); + return expect(contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith( ExchangeContractErrs.OrderRemainingFillAmountZero, ); }); @@ -139,7 +139,7 @@ describe('OrderValidation', () => { fillableAmount, expirationInPast, ); - return expect(zeroEx.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith( + return expect(contractWrappers.exchange.validateOrderFillableOrThrowAsync(signedOrder)).to.be.rejectedWith( ExchangeContractErrs.OrderFillExpired, ); }); @@ -155,7 +155,11 @@ describe('OrderValidation', () => { ); const zeroFillAmount = new BigNumber(0); return expect( - zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, zeroFillAmount, takerAddress), + contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( + signedOrder, + zeroFillAmount, + takerAddress, + ), ).to.be.rejectedWith(ExchangeContractErrs.OrderFillAmountZero); }); it('should throw when the signature is invalid', async () => { @@ -169,7 +173,11 @@ describe('OrderValidation', () => { // 27 <--> 28 signedOrder.ecSignature.v = 28 - signedOrder.ecSignature.v + 27; return expect( - zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress), + contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( + signedOrder, + fillableAmount, + takerAddress, + ), ).to.be.rejectedWith(OrderError.InvalidSignature); }); it('should throw when the order is fully filled or cancelled', async () => { @@ -180,9 +188,13 @@ describe('OrderValidation', () => { takerAddress, fillableAmount, ); - await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount); + await contractWrappers.exchange.cancelOrderAsync(signedOrder, fillableAmount); return expect( - zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillableAmount, takerAddress), + contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( + signedOrder, + fillableAmount, + takerAddress, + ), ).to.be.rejectedWith(ExchangeContractErrs.OrderRemainingFillAmountZero); }); it('should throw when sender is not a taker', async () => { @@ -195,7 +207,11 @@ describe('OrderValidation', () => { ); const nonTakerAddress = userAddresses[6]; return expect( - zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillTakerAmount, nonTakerAddress), + contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( + signedOrder, + fillTakerAmount, + nonTakerAddress, + ), ).to.be.rejectedWith(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker); }); it('should throw when order is expired', async () => { @@ -209,7 +225,11 @@ describe('OrderValidation', () => { expirationInPast, ); return expect( - zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(signedOrder, fillTakerAmount, takerAddress), + contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( + signedOrder, + fillTakerAmount, + takerAddress, + ), ).to.be.rejectedWith(ExchangeContractErrs.OrderFillExpired); }); it('should throw when there a rounding error would have occurred', async () => { @@ -225,7 +245,7 @@ describe('OrderValidation', () => { ); const fillTakerAmountThatCausesRoundingError = new BigNumber(3); return expect( - zeroEx.exchange.validateFillOrderThrowIfInvalidAsync( + contractWrappers.exchange.validateFillOrderThrowIfInvalidAsync( signedOrder, fillTakerAmountThatCausesRoundingError, takerAddress, @@ -244,13 +264,13 @@ describe('OrderValidation', () => { ); const tooLargeFillAmount = new BigNumber(7); const fillAmountDifference = tooLargeFillAmount.minus(fillableAmount); - await zeroEx.token.transferAsync(takerTokenAddress, coinbase, takerAddress, fillAmountDifference); - await zeroEx.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, tooLargeFillAmount); - await zeroEx.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference); - await zeroEx.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount); + await contractWrappers.token.transferAsync(takerTokenAddress, coinbase, takerAddress, fillAmountDifference); + await contractWrappers.token.setProxyAllowanceAsync(takerTokenAddress, takerAddress, tooLargeFillAmount); + await contractWrappers.token.transferAsync(makerTokenAddress, coinbase, makerAddress, fillAmountDifference); + await contractWrappers.token.setProxyAllowanceAsync(makerTokenAddress, makerAddress, tooLargeFillAmount); return expect( - zeroEx.exchange.validateFillOrKillOrderThrowIfInvalidAsync( + contractWrappers.exchange.validateFillOrKillOrderThrowIfInvalidAsync( signedOrder, tooLargeFillAmount, takerAddress, @@ -277,7 +297,7 @@ describe('OrderValidation', () => { it('should throw when cancel amount is zero', async () => { const zeroCancelAmount = new BigNumber(0); return expect( - zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount), + contractWrappers.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, zeroCancelAmount), ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelAmountZero); }); it('should throw when order is expired', async () => { @@ -291,13 +311,13 @@ describe('OrderValidation', () => { expirationInPast, ); return expect( - zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount), + contractWrappers.exchange.validateCancelOrderThrowIfInvalidAsync(expiredSignedOrder, cancelAmount), ).to.be.rejectedWith(ExchangeContractErrs.OrderCancelExpired); }); it('should throw when order is already cancelled or filled', async () => { - await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount); + await contractWrappers.exchange.cancelOrderAsync(signedOrder, fillableAmount); return expect( - zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount), + contractWrappers.exchange.validateCancelOrderThrowIfInvalidAsync(signedOrder, fillableAmount), ).to.be.rejectedWith(ExchangeContractErrs.OrderAlreadyCancelledOrFilled); }); }); @@ -308,7 +328,7 @@ describe('OrderValidation', () => { return Sinon.match((value: BigNumber) => value.eq(expected)); }; beforeEach('create exchangeTransferSimulator', async () => { - exchangeTransferSimulator = new ExchangeTransferSimulator(zeroEx.token, BlockParamLiteral.Latest); + exchangeTransferSimulator = new ExchangeTransferSimulator(contractWrappers.token, BlockParamLiteral.Latest); transferFromAsync = Sinon.spy(); exchangeTransferSimulator.transferFromAsync = transferFromAsync as any; }); @@ -391,7 +411,7 @@ describe('OrderValidation', () => { makerFee, takerFee, makerAddress, - ZeroEx.NULL_ADDRESS, + constants.NULL_ADDRESS, fillableAmount, feeRecipient, ); @@ -485,7 +505,7 @@ describe('OrderValidation', () => { makerAddress, takerAddress, fillableAmount, - ZeroEx.NULL_ADDRESS, + constants.NULL_ADDRESS, ); const fillTakerTokenAmount = fillableAmount.div(2).round(0); await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync( diff --git a/packages/0x.js/test/subscription_test.ts b/packages/contract-wrappers/test/subscription_test.ts index ed4f838c0..64262ad9c 100644 --- a/packages/0x.js/test/subscription_test.ts +++ b/packages/contract-wrappers/test/subscription_test.ts @@ -1,22 +1,21 @@ -import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; +import { BlockchainLifecycle, callbackErrorReporter, devConstants } from '@0xproject/dev-utils'; +import { DoneCallback } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import 'mocha'; import * as Sinon from 'sinon'; -import { ApprovalContractEventArgs, DecodedLogEvent, Token, TokenEvents, ZeroEx } from '../src'; -import { DoneCallback } from '../src/types'; +import { ApprovalContractEventArgs, ContractWrappers, DecodedLogEvent, Token, TokenEvents } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { assertNodeCallbackError } from './utils/report_callback_errors'; import { provider, web3Wrapper } from './utils/web3_wrapper'; chaiSetup.configure(); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('SubscriptionTest', () => { - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; let userAddresses: string[]; let tokens: Token[]; let coinbase: string; @@ -25,9 +24,9 @@ describe('SubscriptionTest', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(provider, config); - userAddresses = await zeroEx.getAvailableAddressesAsync(); - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + contractWrappers = new ContractWrappers(provider, config); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); coinbase = userAddresses[0]; addressWithoutFunds = userAddresses[1]; }); @@ -47,34 +46,48 @@ describe('SubscriptionTest', () => { tokenAddress = token.address; }); afterEach(() => { - zeroEx.token.unsubscribeAll(); + contractWrappers.token.unsubscribeAll(); _.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 = assertNodeCallbackError(done, errMsg); - stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error(errMsg))]; - zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); - await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount); + const callback = callbackErrorReporter.assertNodeCallbackError(done, errMsg); + stubs = [Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws(new Error(errMsg))]; + contractWrappers.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); + await contractWrappers.token.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 = assertNodeCallbackError(done, errMsg); - stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getLogsAsync').throws(new Error(errMsg))]; - zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); - await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount); + const callback = callbackErrorReporter.assertNodeCallbackError(done, errMsg); + stubs = [Sinon.stub((contractWrappers as any)._web3Wrapper, 'getLogsAsync').throws(new Error(errMsg))]; + contractWrappers.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); + await contractWrappers.token.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<ApprovalContractEventArgs>) => _.noop; - zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); - stubs = [Sinon.stub((zeroEx as any)._web3Wrapper, 'getBlockAsync').throws(new Error('JSON RPC error'))]; - zeroEx.token.unsubscribeAll(); + contractWrappers.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); + stubs = [ + Sinon.stub((contractWrappers as any)._web3Wrapper, 'getBlockAsync').throws( + new Error('JSON RPC error'), + ), + ]; + contractWrappers.token.unsubscribeAll(); done(); })().catch(done); }); diff --git a/packages/0x.js/test/token_registry_wrapper_test.ts b/packages/contract-wrappers/test/token_registry_wrapper_test.ts index 19caa2ed4..1b8ce4d74 100644 --- a/packages/0x.js/test/token_registry_wrapper_test.ts +++ b/packages/contract-wrappers/test/token_registry_wrapper_test.ts @@ -4,7 +4,7 @@ import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; -import { Token, ZeroEx } from '../src'; +import { ContractWrappers, Token } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; @@ -17,7 +17,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const TOKEN_REGISTRY_SIZE_AFTER_MIGRATION = 7; describe('TokenRegistryWrapper', () => { - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; let tokens: Token[]; const tokenAddressBySymbol: { [symbol: string]: string } = {}; const tokenAddressByName: { [symbol: string]: string } = {}; @@ -31,8 +31,8 @@ describe('TokenRegistryWrapper', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(provider, config); - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + contractWrappers = new ContractWrappers(provider, config); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); _.map(tokens, token => { tokenAddressBySymbol[token.symbol] = token.address; tokenAddressByName[token.name] = token.address; @@ -59,54 +59,60 @@ describe('TokenRegistryWrapper', () => { }); describe('#getTokenAddressesAsync', () => { it('should return all the token addresses added to the tokenRegistry during the migration', async () => { - const tokenAddresses = await zeroEx.tokenRegistry.getTokenAddressesAsync(); + const tokenAddresses = await contractWrappers.tokenRegistry.getTokenAddressesAsync(); expect(tokenAddresses).to.have.lengthOf(TOKEN_REGISTRY_SIZE_AFTER_MIGRATION); const schemaValidator = new SchemaValidator(); _.each(tokenAddresses, tokenAddress => { const validationResult = schemaValidator.validate(tokenAddress, schemas.addressSchema); expect(validationResult.errors).to.have.lengthOf(0); - expect(tokenAddress).to.not.be.equal(ZeroEx.NULL_ADDRESS); + expect(tokenAddress).to.not.be.equal(constants.NULL_ADDRESS); }); }); }); describe('#getTokenAddressBySymbol', () => { it('should return correct address for a token in the registry', async () => { - const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(registeredSymbol); + const tokenAddress = await contractWrappers.tokenRegistry.getTokenAddressBySymbolIfExistsAsync( + registeredSymbol, + ); expect(tokenAddress).to.be.equal(tokenAddressBySymbol[registeredSymbol]); }); it('should return undefined for a token out of registry', async () => { - const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressBySymbolIfExistsAsync(unregisteredSymbol); + const tokenAddress = await contractWrappers.tokenRegistry.getTokenAddressBySymbolIfExistsAsync( + unregisteredSymbol, + ); expect(tokenAddress).to.be.undefined(); }); }); describe('#getTokenAddressByName', () => { it('should return correct address for a token in the registry', async () => { - const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync(registeredName); + const tokenAddress = await contractWrappers.tokenRegistry.getTokenAddressByNameIfExistsAsync(registeredName); expect(tokenAddress).to.be.equal(tokenAddressByName[registeredName]); }); it('should return undefined for a token out of registry', async () => { - const tokenAddress = await zeroEx.tokenRegistry.getTokenAddressByNameIfExistsAsync(unregisteredName); + const tokenAddress = await contractWrappers.tokenRegistry.getTokenAddressByNameIfExistsAsync( + unregisteredName, + ); expect(tokenAddress).to.be.undefined(); }); }); describe('#getTokenBySymbol', () => { it('should return correct token for a token in the registry', async () => { - const token = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync(registeredSymbol); + const token = await contractWrappers.tokenRegistry.getTokenBySymbolIfExistsAsync(registeredSymbol); expect(token).to.be.deep.equal(tokenBySymbol[registeredSymbol]); }); it('should return undefined for a token out of registry', async () => { - const token = await zeroEx.tokenRegistry.getTokenBySymbolIfExistsAsync(unregisteredSymbol); + const token = await contractWrappers.tokenRegistry.getTokenBySymbolIfExistsAsync(unregisteredSymbol); expect(token).to.be.undefined(); }); }); describe('#getTokenByName', () => { it('should return correct token for a token in the registry', async () => { - const token = await zeroEx.tokenRegistry.getTokenByNameIfExistsAsync(registeredName); + const token = await contractWrappers.tokenRegistry.getTokenByNameIfExistsAsync(registeredName); expect(token).to.be.deep.equal(tokenByName[registeredName]); }); it('should return undefined for a token out of registry', async () => { - const token = await zeroEx.tokenRegistry.getTokenByNameIfExistsAsync(unregisteredName); + const token = await contractWrappers.tokenRegistry.getTokenByNameIfExistsAsync(unregisteredName); expect(token).to.be.undefined(); }); }); @@ -114,14 +120,14 @@ describe('TokenRegistryWrapper', () => { it('should return the token added to the tokenRegistry during the migration', async () => { const aToken = tokens[0]; - const token = await zeroEx.tokenRegistry.getTokenIfExistsAsync(aToken.address); + const token = await contractWrappers.tokenRegistry.getTokenIfExistsAsync(aToken.address); const schemaValidator = new SchemaValidator(); const validationResult = schemaValidator.validate(token, schemas.tokenSchema); expect(validationResult.errors).to.have.lengthOf(0); }); it('should return return undefined when passed a token address not in the tokenRegistry', async () => { const unregisteredTokenAddress = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; - const tokenIfExists = await zeroEx.tokenRegistry.getTokenIfExistsAsync(unregisteredTokenAddress); + const tokenIfExists = await contractWrappers.tokenRegistry.getTokenIfExistsAsync(unregisteredTokenAddress); expect(tokenIfExists).to.be.undefined(); }); }); diff --git a/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts b/packages/contract-wrappers/test/token_transfer_proxy_wrapper_test.ts index 9415d7c08..0b66985aa 100644 --- a/packages/0x.js/test/token_transfer_proxy_wrapper_test.ts +++ b/packages/contract-wrappers/test/token_transfer_proxy_wrapper_test.ts @@ -1,6 +1,6 @@ import * as chai from 'chai'; -import { ZeroEx } from '../src'; +import { ContractWrappers } from '../src'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; @@ -10,24 +10,24 @@ chaiSetup.configure(); const expect = chai.expect; describe('TokenTransferProxyWrapper', () => { - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; const config = { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(provider, config); + contractWrappers = new ContractWrappers(provider, config); }); describe('#isAuthorizedAsync', () => { it('should return false if the address is not authorized', async () => { - const isAuthorized = await zeroEx.proxy.isAuthorizedAsync(ZeroEx.NULL_ADDRESS); + const isAuthorized = await contractWrappers.proxy.isAuthorizedAsync(constants.NULL_ADDRESS); expect(isAuthorized).to.be.false(); }); }); describe('#getAuthorizedAddressesAsync', () => { it('should return the list of authorized addresses', async () => { - const authorizedAddresses = await zeroEx.proxy.getAuthorizedAddressesAsync(); + const authorizedAddresses = await contractWrappers.proxy.getAuthorizedAddressesAsync(); for (const authorizedAddress of authorizedAddresses) { - const isAuthorized = await zeroEx.proxy.isAuthorizedAsync(authorizedAddress); + const isAuthorized = await contractWrappers.proxy.isAuthorizedAsync(authorizedAddress); expect(isAuthorized).to.be.true(); } }); diff --git a/packages/0x.js/test/token_wrapper_test.ts b/packages/contract-wrappers/test/token_wrapper_test.ts index 04fd943aa..053901c85 100644 --- a/packages/0x.js/test/token_wrapper_test.ts +++ b/packages/contract-wrappers/test/token_wrapper_test.ts @@ -1,6 +1,6 @@ -import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; +import { BlockchainLifecycle, callbackErrorReporter, devConstants } from '@0xproject/dev-utils'; import { EmptyWalletSubprovider } from '@0xproject/subproviders'; -import { Provider } from '@0xproject/types'; +import { DoneCallback, Provider } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import 'mocha'; @@ -10,18 +10,16 @@ import { ApprovalContractEventArgs, BlockParamLiteral, BlockRange, + ContractWrappers, + ContractWrappersError, DecodedLogEvent, Token, TokenEvents, TransferContractEventArgs, - ZeroEx, - ZeroExError, } from '../src'; -import { DoneCallback } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -30,7 +28,7 @@ const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('TokenWrapper', () => { - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; let userAddresses: string[]; let tokens: Token[]; let tokenUtils: TokenUtils; @@ -40,9 +38,9 @@ describe('TokenWrapper', () => { networkId: constants.TESTRPC_NETWORK_ID, }; before(async () => { - zeroEx = new ZeroEx(provider, config); - userAddresses = await zeroEx.getAvailableAddressesAsync(); - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + contractWrappers = new ContractWrappers(provider, config); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); tokenUtils = new TokenUtils(tokens); coinbase = userAddresses[0]; addressWithoutFunds = userAddresses[1]; @@ -63,26 +61,26 @@ describe('TokenWrapper', () => { it('should successfully transfer tokens', async () => { const fromAddress = coinbase; const toAddress = addressWithoutFunds; - const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress); + const preBalance = await contractWrappers.token.getBalanceAsync(token.address, toAddress); expect(preBalance).to.be.bignumber.equal(0); - await zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount); - const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress); + await contractWrappers.token.transferAsync(token.address, fromAddress, toAddress, transferAmount); + const postBalance = await contractWrappers.token.getBalanceAsync(token.address, toAddress); return expect(postBalance).to.be.bignumber.equal(transferAmount); }); it('should fail to transfer tokens if fromAddress has an insufficient balance', async () => { const fromAddress = addressWithoutFunds; const toAddress = coinbase; return expect( - zeroEx.token.transferAsync(token.address, fromAddress, toAddress, transferAmount), - ).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer); + contractWrappers.token.transferAsync(token.address, fromAddress, toAddress, transferAmount), + ).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer); }); it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; const fromAddress = coinbase; const toAddress = coinbase; return expect( - zeroEx.token.transferAsync(nonExistentTokenAddress, fromAddress, toAddress, transferAmount), - ).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist); + contractWrappers.token.transferAsync(nonExistentTokenAddress, fromAddress, toAddress, transferAmount), + ).to.be.rejectedWith(ContractWrappersError.TokenContractDoesNotExist); }); }); describe('#transferFromAsync', () => { @@ -98,35 +96,51 @@ describe('TokenWrapper', () => { const fromAddress = coinbase; const transferAmount = new BigNumber(42); - const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress); + const fromAddressBalance = await contractWrappers.token.getBalanceAsync(token.address, fromAddress); expect(fromAddressBalance).to.be.bignumber.greaterThan(transferAmount); - const fromAddressAllowance = await zeroEx.token.getAllowanceAsync(token.address, fromAddress, toAddress); + const fromAddressAllowance = await contractWrappers.token.getAllowanceAsync( + token.address, + fromAddress, + toAddress, + ); expect(fromAddressAllowance).to.be.bignumber.equal(0); return expect( - zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount), - ).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer); + contractWrappers.token.transferFromAsync( + token.address, + fromAddress, + toAddress, + senderAddress, + transferAmount, + ), + ).to.be.rejectedWith(ContractWrappersError.InsufficientAllowanceForTransfer); }); it('[regression] should fail to transfer tokens if set allowance for toAddress instead of senderAddress', async () => { const fromAddress = coinbase; const transferAmount = new BigNumber(42); - await zeroEx.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount); + await contractWrappers.token.setAllowanceAsync(token.address, fromAddress, toAddress, transferAmount); return expect( - zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount), - ).to.be.rejectedWith(ZeroExError.InsufficientAllowanceForTransfer); + contractWrappers.token.transferFromAsync( + token.address, + fromAddress, + toAddress, + senderAddress, + transferAmount, + ), + ).to.be.rejectedWith(ContractWrappersError.InsufficientAllowanceForTransfer); }); it('should fail to transfer tokens if fromAddress has insufficient balance', async () => { const fromAddress = addressWithoutFunds; const transferAmount = new BigNumber(42); - const fromAddressBalance = await zeroEx.token.getBalanceAsync(token.address, fromAddress); + const fromAddressBalance = await contractWrappers.token.getBalanceAsync(token.address, fromAddress); expect(fromAddressBalance).to.be.bignumber.equal(0); - await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount); - const fromAddressAllowance = await zeroEx.token.getAllowanceAsync( + await contractWrappers.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount); + const fromAddressAllowance = await contractWrappers.token.getAllowanceAsync( token.address, fromAddress, senderAddress, @@ -134,34 +148,46 @@ describe('TokenWrapper', () => { expect(fromAddressAllowance).to.be.bignumber.equal(transferAmount); return expect( - zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount), - ).to.be.rejectedWith(ZeroExError.InsufficientBalanceForTransfer); + contractWrappers.token.transferFromAsync( + token.address, + fromAddress, + toAddress, + senderAddress, + transferAmount, + ), + ).to.be.rejectedWith(ContractWrappersError.InsufficientBalanceForTransfer); }); it('should successfully transfer tokens', async () => { const fromAddress = coinbase; - const preBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress); + const preBalance = await contractWrappers.token.getBalanceAsync(token.address, toAddress); expect(preBalance).to.be.bignumber.equal(0); const transferAmount = new BigNumber(42); - await zeroEx.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount); + await contractWrappers.token.setAllowanceAsync(token.address, fromAddress, senderAddress, transferAmount); - await zeroEx.token.transferFromAsync(token.address, fromAddress, toAddress, senderAddress, transferAmount); - const postBalance = await zeroEx.token.getBalanceAsync(token.address, toAddress); + await contractWrappers.token.transferFromAsync( + token.address, + fromAddress, + toAddress, + senderAddress, + transferAmount, + ); + const postBalance = await contractWrappers.token.getBalanceAsync(token.address, toAddress); return expect(postBalance).to.be.bignumber.equal(transferAmount); }); it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { const fromAddress = coinbase; const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; return expect( - zeroEx.token.transferFromAsync( + contractWrappers.token.transferFromAsync( nonExistentTokenAddress, fromAddress, toAddress, senderAddress, new BigNumber(42), ), - ).to.be.rejectedWith(ZeroExError.TokenContractDoesNotExist); + ).to.be.rejectedWith(ContractWrappersError.TokenContractDoesNotExist); }); }); describe('#getBalanceAsync', () => { @@ -169,36 +195,36 @@ describe('TokenWrapper', () => { it('should return the balance for an existing ERC20 token', async () => { const token = tokens[0]; const ownerAddress = coinbase; - const balance = await zeroEx.token.getBalanceAsync(token.address, ownerAddress); + const balance = await contractWrappers.token.getBalanceAsync(token.address, ownerAddress); const expectedBalance = new BigNumber('1000000000000000000000000000'); return expect(balance).to.be.bignumber.equal(expectedBalance); }); it('should throw a CONTRACT_DOES_NOT_EXIST error for a non-existent token contract', async () => { const nonExistentTokenAddress = '0x9dd402f14d67e001d8efbe6583e51bf9706aa065'; const ownerAddress = coinbase; - return expect(zeroEx.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress)).to.be.rejectedWith( - ZeroExError.TokenContractDoesNotExist, - ); + return expect( + contractWrappers.token.getBalanceAsync(nonExistentTokenAddress, ownerAddress), + ).to.be.rejectedWith(ContractWrappersError.TokenContractDoesNotExist); }); it('should return a balance of 0 for a non-existent owner address', async () => { const token = tokens[0]; const nonExistentOwner = '0x198c6ad858f213fb31b6fe809e25040e6b964593'; - const balance = await zeroEx.token.getBalanceAsync(token.address, nonExistentOwner); + const balance = await contractWrappers.token.getBalanceAsync(token.address, nonExistentOwner); const expectedBalance = new BigNumber(0); return expect(balance).to.be.bignumber.equal(expectedBalance); }); }); describe('With provider without accounts', () => { - let zeroExWithoutAccounts: ZeroEx; + let zeroExContractWithoutAccounts: ContractWrappers; before(async () => { const hasAddresses = false; const emptyWalletProvider = addEmptyWalletSubprovider(provider); - zeroExWithoutAccounts = new ZeroEx(emptyWalletProvider, config); + zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config); }); it('should return balance even when called with provider instance without addresses', async () => { const token = tokens[0]; const ownerAddress = coinbase; - const balance = await zeroExWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress); + const balance = await zeroExContractWithoutAccounts.token.getBalanceAsync(token.address, ownerAddress); const expectedBalance = new BigNumber('1000000000000000000000000000'); return expect(balance).to.be.bignumber.equal(expectedBalance); }); @@ -210,7 +236,7 @@ describe('TokenWrapper', () => { const ownerAddress = coinbase; const spenderAddress = addressWithoutFunds; - const allowanceBeforeSet = await zeroEx.token.getAllowanceAsync( + const allowanceBeforeSet = await contractWrappers.token.getAllowanceAsync( token.address, ownerAddress, spenderAddress, @@ -219,9 +245,18 @@ describe('TokenWrapper', () => { expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet); const amountInBaseUnits = new BigNumber(50); - await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits); + await contractWrappers.token.setAllowanceAsync( + token.address, + ownerAddress, + spenderAddress, + amountInBaseUnits, + ); - const allowanceAfterSet = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress); + const allowanceAfterSet = await contractWrappers.token.getAllowanceAsync( + token.address, + ownerAddress, + spenderAddress, + ); const expectedAllowanceAfterAllowanceSet = amountInBaseUnits; return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet); }); @@ -232,30 +267,39 @@ describe('TokenWrapper', () => { const ownerAddress = coinbase; const spenderAddress = addressWithoutFunds; - await zeroEx.token.setUnlimitedAllowanceAsync(token.address, ownerAddress, spenderAddress); - const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress); - return expect(allowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + await contractWrappers.token.setUnlimitedAllowanceAsync(token.address, ownerAddress, spenderAddress); + const allowance = await contractWrappers.token.getAllowanceAsync( + token.address, + ownerAddress, + spenderAddress, + ); + return expect(allowance).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => { const transferAmount = new BigNumber(5); const zrx = tokenUtils.getProtocolTokenOrThrow(); const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses; - await zeroEx.token.setAllowanceAsync(zrx.address, coinbase, userWithNormalAllowance, transferAmount); - await zeroEx.token.setUnlimitedAllowanceAsync(zrx.address, coinbase, userWithUnlimitedAllowance); + await contractWrappers.token.setAllowanceAsync( + zrx.address, + coinbase, + userWithNormalAllowance, + transferAmount, + ); + await contractWrappers.token.setUnlimitedAllowanceAsync(zrx.address, coinbase, userWithUnlimitedAllowance); const initBalanceWithNormalAllowance = await web3Wrapper.getBalanceInWeiAsync(userWithNormalAllowance); const initBalanceWithUnlimitedAllowance = await web3Wrapper.getBalanceInWeiAsync( userWithUnlimitedAllowance, ); - await zeroEx.token.transferFromAsync( + await contractWrappers.token.transferFromAsync( zrx.address, coinbase, userWithNormalAllowance, userWithNormalAllowance, transferAmount, ); - await zeroEx.token.transferFromAsync( + await contractWrappers.token.transferFromAsync( zrx.address, coinbase, userWithUnlimitedAllowance, @@ -285,9 +329,18 @@ describe('TokenWrapper', () => { const spenderAddress = addressWithoutFunds; const amountInBaseUnits = new BigNumber(50); - await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits); + await contractWrappers.token.setAllowanceAsync( + token.address, + ownerAddress, + spenderAddress, + amountInBaseUnits, + ); - const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress); + const allowance = await contractWrappers.token.getAllowanceAsync( + token.address, + ownerAddress, + spenderAddress, + ); const expectedAllowance = amountInBaseUnits; return expect(allowance).to.be.bignumber.equal(expectedAllowance); }); @@ -295,17 +348,21 @@ describe('TokenWrapper', () => { const token = tokens[0]; const ownerAddress = coinbase; const spenderAddress = addressWithoutFunds; - const allowance = await zeroEx.token.getAllowanceAsync(token.address, ownerAddress, spenderAddress); + const allowance = await contractWrappers.token.getAllowanceAsync( + token.address, + ownerAddress, + spenderAddress, + ); const expectedAllowance = new BigNumber(0); return expect(allowance).to.be.bignumber.equal(expectedAllowance); }); }); describe('With provider without accounts', () => { - let zeroExWithoutAccounts: ZeroEx; + let zeroExContractWithoutAccounts: ContractWrappers; before(async () => { const hasAddresses = false; const emptyWalletProvider = addEmptyWalletSubprovider(provider); - zeroExWithoutAccounts = new ZeroEx(emptyWalletProvider, config); + zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config); }); it('should get the proxy allowance', async () => { const token = tokens[0]; @@ -313,9 +370,14 @@ describe('TokenWrapper', () => { const spenderAddress = addressWithoutFunds; const amountInBaseUnits = new BigNumber(50); - await zeroEx.token.setAllowanceAsync(token.address, ownerAddress, spenderAddress, amountInBaseUnits); + await contractWrappers.token.setAllowanceAsync( + token.address, + ownerAddress, + spenderAddress, + amountInBaseUnits, + ); - const allowance = await zeroExWithoutAccounts.token.getAllowanceAsync( + const allowance = await zeroExContractWithoutAccounts.token.getAllowanceAsync( token.address, ownerAddress, spenderAddress, @@ -331,9 +393,9 @@ describe('TokenWrapper', () => { const ownerAddress = coinbase; const amountInBaseUnits = new BigNumber(50); - await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits); + await contractWrappers.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits); - const allowance = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress); + const allowance = await contractWrappers.token.getProxyAllowanceAsync(token.address, ownerAddress); const expectedAllowance = amountInBaseUnits; return expect(allowance).to.be.bignumber.equal(expectedAllowance); }); @@ -343,14 +405,14 @@ describe('TokenWrapper', () => { const token = tokens[0]; const ownerAddress = coinbase; - const allowanceBeforeSet = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress); + const allowanceBeforeSet = await contractWrappers.token.getProxyAllowanceAsync(token.address, ownerAddress); const expectedAllowanceBeforeAllowanceSet = new BigNumber(0); expect(allowanceBeforeSet).to.be.bignumber.equal(expectedAllowanceBeforeAllowanceSet); const amountInBaseUnits = new BigNumber(50); - await zeroEx.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits); + await contractWrappers.token.setProxyAllowanceAsync(token.address, ownerAddress, amountInBaseUnits); - const allowanceAfterSet = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress); + const allowanceAfterSet = await contractWrappers.token.getProxyAllowanceAsync(token.address, ownerAddress); const expectedAllowanceAfterAllowanceSet = amountInBaseUnits; return expect(allowanceAfterSet).to.be.bignumber.equal(expectedAllowanceAfterAllowanceSet); }); @@ -360,9 +422,9 @@ describe('TokenWrapper', () => { const token = tokens[0]; const ownerAddress = coinbase; - await zeroEx.token.setUnlimitedProxyAllowanceAsync(token.address, ownerAddress); - const allowance = await zeroEx.token.getProxyAllowanceAsync(token.address, ownerAddress); - return expect(allowance).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + await contractWrappers.token.setUnlimitedProxyAllowanceAsync(token.address, ownerAddress); + const allowance = await contractWrappers.token.getProxyAllowanceAsync(token.address, ownerAddress); + return expect(allowance).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); }); describe('#subscribe', () => { @@ -375,7 +437,7 @@ describe('TokenWrapper', () => { tokenAddress = token.address; }); afterEach(() => { - zeroEx.token.unsubscribeAll(); + contractWrappers.token.unsubscribeAll(); }); // Hack: Mocha does not allow a test to be both async and have a `done` callback // Since we need to await the receipt of the event in the `subscribe` callback, @@ -384,7 +446,7 @@ describe('TokenWrapper', () => { // Source: https://github.com/mochajs/mocha/issues/2407 it('Should receive the Transfer event when tokens are transfered', (done: DoneCallback) => { (async () => { - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<TransferContractEventArgs>) => { expect(logEvent.isRemoved).to.be.false(); expect(logEvent.log.logIndex).to.be.equal(0); @@ -396,13 +458,13 @@ describe('TokenWrapper', () => { expect(args._value).to.be.bignumber.equal(transferAmount); }, ); - zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callback); - await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount); + contractWrappers.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callback); + await contractWrappers.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount); })().catch(done); }); it('Should receive the Approval event when allowance is being set', (done: DoneCallback) => { (async () => { - const callback = reportNodeCallbackErrors(done)( + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => { expect(logEvent).to.not.be.undefined(); expect(logEvent.isRemoved).to.be.false(); @@ -412,39 +474,54 @@ describe('TokenWrapper', () => { expect(args._value).to.be.bignumber.equal(allowanceAmount); }, ); - zeroEx.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); - await zeroEx.token.setAllowanceAsync(tokenAddress, coinbase, addressWithoutFunds, allowanceAmount); + contractWrappers.token.subscribe(tokenAddress, TokenEvents.Approval, indexFilterValues, callback); + await contractWrappers.token.setAllowanceAsync( + tokenAddress, + coinbase, + addressWithoutFunds, + allowanceAmount, + ); })().catch(done); }); - it('Outstanding subscriptions are cancelled when zeroEx.setProvider called', (done: DoneCallback) => { + it('Outstanding subscriptions are cancelled when contractWrappers.setProvider called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = reportNodeCallbackErrors(done)( + const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }, ); - zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled); - const callbackToBeCalled = reportNodeCallbackErrors(done)(); - zeroEx.setProvider(provider, constants.TESTRPC_NETWORK_ID); - zeroEx.token.subscribe(tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackToBeCalled); - await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount); + contractWrappers.token.subscribe( + tokenAddress, + TokenEvents.Transfer, + indexFilterValues, + callbackNeverToBeCalled, + ); + const callbackToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)(); + contractWrappers.setProvider(provider, constants.TESTRPC_NETWORK_ID); + contractWrappers.token.subscribe( + tokenAddress, + TokenEvents.Transfer, + indexFilterValues, + callbackToBeCalled, + ); + await contractWrappers.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount); })().catch(done); }); it('Should cancel subscription when unsubscribe called', (done: DoneCallback) => { (async () => { - const callbackNeverToBeCalled = reportNodeCallbackErrors(done)( + const callbackNeverToBeCalled = callbackErrorReporter.reportNodeCallbackErrors(done)( (logEvent: DecodedLogEvent<ApprovalContractEventArgs>) => { done(new Error('Expected this subscription to have been cancelled')); }, ); - const subscriptionToken = zeroEx.token.subscribe( + const subscriptionToken = contractWrappers.token.subscribe( tokenAddress, TokenEvents.Transfer, indexFilterValues, callbackNeverToBeCalled, ); - zeroEx.token.unsubscribe(subscriptionToken); - await zeroEx.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount); + contractWrappers.token.unsubscribe(subscriptionToken); + await contractWrappers.token.transferAsync(tokenAddress, coinbase, addressWithoutFunds, transferAmount); done(); })().catch(done); }); @@ -460,14 +537,14 @@ describe('TokenWrapper', () => { before(() => { const token = tokens[0]; tokenAddress = token.address; - tokenTransferProxyAddress = zeroEx.proxy.getContractAddress(); + tokenTransferProxyAddress = contractWrappers.proxy.getContractAddress(); }); it('should get logs with decoded args emitted by Approval', async () => { - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const eventName = TokenEvents.Approval; const indexFilterValues = {}; - const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>( + const logs = await contractWrappers.token.getLogsAsync<ApprovalContractEventArgs>( tokenAddress, eventName, blockRange, @@ -478,14 +555,14 @@ describe('TokenWrapper', () => { expect(logs[0].event).to.be.equal(eventName); expect(args._owner).to.be.equal(coinbase); expect(args._spender).to.be.equal(tokenTransferProxyAddress); - expect(args._value).to.be.bignumber.equal(zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + expect(args._value).to.be.bignumber.equal(contractWrappers.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); it('should only get the logs with the correct event name', async () => { - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const differentEventName = TokenEvents.Transfer; const indexFilterValues = {}; - const logs = await zeroEx.token.getLogsAsync( + const logs = await contractWrappers.token.getLogsAsync( tokenAddress, differentEventName, blockRange, @@ -494,15 +571,15 @@ describe('TokenWrapper', () => { expect(logs).to.have.length(0); }); it('should only get the logs with the correct indexed fields', async () => { - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); - await zeroEx.awaitTransactionMinedAsync(txHash); - txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(tokenAddress, addressWithoutFunds); - await zeroEx.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(tokenAddress, coinbase); + await web3Wrapper.awaitTransactionMinedAsync(txHash); + txHash = await contractWrappers.token.setUnlimitedProxyAllowanceAsync(tokenAddress, addressWithoutFunds); + await web3Wrapper.awaitTransactionMinedAsync(txHash); const eventName = TokenEvents.Approval; const indexFilterValues = { _owner: coinbase, }; - const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>( + const logs = await contractWrappers.token.getLogsAsync<ApprovalContractEventArgs>( tokenAddress, eventName, blockRange, diff --git a/packages/contract-wrappers/test/utils/chai_setup.ts b/packages/contract-wrappers/test/utils/chai_setup.ts new file mode 100644 index 000000000..078edd309 --- /dev/null +++ b/packages/contract-wrappers/test/utils/chai_setup.ts @@ -0,0 +1,13 @@ +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() { + chai.config.includeStack = true; + chai.use(ChaiBigNumber()); + chai.use(dirtyChai); + chai.use(chaiAsPromised); + }, +}; diff --git a/packages/contract-wrappers/test/utils/constants.ts b/packages/contract-wrappers/test/utils/constants.ts new file mode 100644 index 000000000..cf030259c --- /dev/null +++ b/packages/contract-wrappers/test/utils/constants.ts @@ -0,0 +1,9 @@ +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, +}; diff --git a/packages/contract-wrappers/test/utils/deployer.ts b/packages/contract-wrappers/test/utils/deployer.ts new file mode 100644 index 000000000..b092322e2 --- /dev/null +++ b/packages/contract-wrappers/test/utils/deployer.ts @@ -0,0 +1,18 @@ +import { Deployer } from '@0xproject/deployer'; +import { devConstants } from '@0xproject/dev-utils'; +import * as path from 'path'; + +import { constants } from './constants'; + +import { provider } from './web3_wrapper'; + +const artifactsDir = path.resolve('test', 'artifacts'); +const deployerOpts = { + artifactsDir, + provider, + networkId: constants.TESTRPC_NETWORK_ID, + defaults: { + gas: devConstants.GAS_ESTIMATE, + }, +}; +export const deployer = new Deployer(deployerOpts); diff --git a/packages/contract-wrappers/test/utils/token_utils.ts b/packages/contract-wrappers/test/utils/token_utils.ts new file mode 100644 index 000000000..fe85de085 --- /dev/null +++ b/packages/contract-wrappers/test/utils/token_utils.ts @@ -0,0 +1,33 @@ +import * as _ from 'lodash'; + +import { InternalContractWrappersError, Token } from '../../src/types'; + +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(InternalContractWrappersError.ZrxNotInTokenRegistry); + } + return zrxToken; + } + public getWethTokenOrThrow(): Token { + const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL }); + if (_.isUndefined(wethToken)) { + throw new Error(InternalContractWrappersError.WethNotInTokenRegistry); + } + return wethToken; + } + public getDummyTokens(): Token[] { + const dummyTokens = _.filter(this._tokens, token => { + return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol); + }); + return dummyTokens; + } +} diff --git a/packages/contract-wrappers/test/utils/web3_wrapper.ts b/packages/contract-wrappers/test/utils/web3_wrapper.ts new file mode 100644 index 000000000..b0ccfa546 --- /dev/null +++ b/packages/contract-wrappers/test/utils/web3_wrapper.ts @@ -0,0 +1,9 @@ +import { devConstants, web3Factory } from '@0xproject/dev-utils'; +import { Provider } from '@0xproject/types'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; + +const web3 = web3Factory.create({ shouldUseInProcessGanache: true }); +const provider: Provider = web3.currentProvider; +const web3Wrapper = new Web3Wrapper(web3.currentProvider); + +export { provider, web3Wrapper }; diff --git a/packages/contract-wrappers/tsconfig.json b/packages/contract-wrappers/tsconfig.json new file mode 100644 index 000000000..e35816553 --- /dev/null +++ b/packages/contract-wrappers/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/contract-wrappers/tslint.json b/packages/contract-wrappers/tslint.json new file mode 100644 index 000000000..ffaefe83a --- /dev/null +++ b/packages/contract-wrappers/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": ["@0xproject/tslint-config"] +} diff --git a/packages/contracts/test/ether_token.ts b/packages/contracts/test/ether_token.ts index 4023abad0..2123d60dd 100644 --- a/packages/contracts/test/ether_token.ts +++ b/packages/contracts/test/ether_token.ts @@ -1,4 +1,4 @@ -import { ZeroEx, ZeroExError } from '0x.js'; +import { ZeroEx, ContractWrappersError } from '0x.js'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BigNumber, promisify } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -43,7 +43,7 @@ describe('EtherToken', () => { const ethToDeposit = initEthBalance.plus(1); return expect(zeroEx.etherToken.depositAsync(etherTokenAddress, ethToDeposit, account)).to.be.rejectedWith( - ZeroExError.InsufficientEthBalanceForDeposit, + ContractWrappersError.InsufficientEthBalanceForDeposit, ); }); @@ -72,7 +72,7 @@ describe('EtherToken', () => { return expect( zeroEx.etherToken.withdrawAsync(etherTokenAddress, ethTokensToWithdraw, account), - ).to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal); + ).to.be.rejectedWith(ContractWrappersError.InsufficientWEthBalanceForWithdrawal); }); it('should convert ether tokens to ether with sufficient balance', async () => { diff --git a/packages/contracts/test/multi_sig_with_time_lock.ts b/packages/contracts/test/multi_sig_with_time_lock.ts index 5cc744713..cf3893780 100644 --- a/packages/contracts/test/multi_sig_with_time_lock.ts +++ b/packages/contracts/test/multi_sig_with_time_lock.ts @@ -17,7 +17,7 @@ import { chaiSetup } from './utils/chai_setup'; import { deployer } from './utils/deployer'; import { provider, web3Wrapper } from './utils/web3_wrapper'; -const MULTI_SIG_ABI = artifacts.MultiSigWalletWithTimeLockArtifact.compilerOutput.abi; +const MULTI_SIG_ABI = artifacts.MultiSigWalletWithTimeLock.compilerOutput.abi; chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); diff --git a/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts b/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts index 06fa30d96..3ff5b82ed 100644 --- a/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts +++ b/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts @@ -17,9 +17,9 @@ import { ContractName, SubmissionContractEventArgs, TransactionDataParams } from import { chaiSetup } from './utils/chai_setup'; import { deployer } from './utils/deployer'; import { provider, web3Wrapper } from './utils/web3_wrapper'; -const PROXY_ABI = artifacts.TokenTransferProxyArtifact.compilerOutput.abi; +const PROXY_ABI = artifacts.TokenTransferProxy.compilerOutput.abi; const MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_AUTHORIZED_ADDRESS_ABI = - artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact.compilerOutput.abi; + artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.compilerOutput.abi; chaiSetup.configure(); const expect = chai.expect; diff --git a/packages/contracts/test/tutorials/arbitrage.ts b/packages/contracts/test/tutorials/arbitrage.ts index ad83bbca3..2fbf850d0 100644 --- a/packages/contracts/test/tutorials/arbitrage.ts +++ b/packages/contracts/test/tutorials/arbitrage.ts @@ -1,5 +1,6 @@ import { ECSignature, SignedOrder, ZeroEx } from '0x.js'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; +import { ExchangeContractErrs } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; @@ -14,7 +15,7 @@ import { constants } from '../../util/constants'; import { crypto } from '../../util/crypto'; import { ExchangeWrapper } from '../../util/exchange_wrapper'; import { OrderFactory } from '../../util/order_factory'; -import { BalancesByOwner, ContractName, ExchangeContractErrs } from '../../util/types'; +import { BalancesByOwner, ContractName } from '../../util/types'; import { chaiSetup } from '../utils/chai_setup'; import { deployer } from '../utils/deployer'; import { provider, web3Wrapper } from '../utils/web3_wrapper'; diff --git a/packages/contracts/util/artifacts.ts b/packages/contracts/util/artifacts.ts index a1d6e5060..d262b8058 100644 --- a/packages/contracts/util/artifacts.ts +++ b/packages/contracts/util/artifacts.ts @@ -1,25 +1,25 @@ import { ContractArtifact } from '@0xproject/deployer'; -import * as DummyTokenArtifact from '../src/artifacts/DummyToken.json'; -import * as ExchangeArtifact from '../src/artifacts/Exchange.json'; -import * as MaliciousTokenArtifact from '../src/artifacts/MaliciousToken.json'; -import * as MultiSigWalletWithTimeLockArtifact from '../src/artifacts/MultiSigWalletWithTimeLock.json'; -import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact from '../src/artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json'; -import * as TokenArtifact from '../src/artifacts/Token.json'; -import * as TokenRegistryArtifact from '../src/artifacts/TokenRegistry.json'; -import * as TokenTransferProxyArtifact from '../src/artifacts/TokenTransferProxy.json'; -import * as EtherTokenArtifact from '../src/artifacts/WETH9.json'; -import * as ZRXArtifact from '../src/artifacts/ZRXToken.json'; +import * as DummyToken from '../src/artifacts/DummyToken.json'; +import * as Exchange from '../src/artifacts/Exchange.json'; +import * as MaliciousToken from '../src/artifacts/MaliciousToken.json'; +import * as MultiSigWalletWithTimeLock from '../src/artifacts/MultiSigWalletWithTimeLock.json'; +import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress from '../src/artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json'; +import * as Token from '../src/artifacts/Token.json'; +import * as TokenRegistry from '../src/artifacts/TokenRegistry.json'; +import * as TokenTransferProxy from '../src/artifacts/TokenTransferProxy.json'; +import * as EtherToken from '../src/artifacts/WETH9.json'; +import * as ZRX from '../src/artifacts/ZRXToken.json'; export const artifacts = { - ZRXArtifact: (ZRXArtifact as any) as ContractArtifact, - DummyTokenArtifact: (DummyTokenArtifact as any) as ContractArtifact, - TokenArtifact: (TokenArtifact as any) as ContractArtifact, - ExchangeArtifact: (ExchangeArtifact as any) as ContractArtifact, - EtherTokenArtifact: (EtherTokenArtifact as any) as ContractArtifact, - TokenRegistryArtifact: (TokenRegistryArtifact as any) as ContractArtifact, - MaliciousTokenArtifact: (MaliciousTokenArtifact as any) as ContractArtifact, - TokenTransferProxyArtifact: (TokenTransferProxyArtifact as any) as ContractArtifact, - MultiSigWalletWithTimeLockArtifact: (MultiSigWalletWithTimeLockArtifact as any) as ContractArtifact, - MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact: (MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact as any) as ContractArtifact, + ZRX: (ZRX as any) as ContractArtifact, + DummyToken: (DummyToken as any) as ContractArtifact, + Token: (Token as any) as ContractArtifact, + Exchange: (Exchange as any) as ContractArtifact, + EtherToken: (EtherToken as any) as ContractArtifact, + TokenRegistry: (TokenRegistry as any) as ContractArtifact, + MaliciousToken: (MaliciousToken as any) as ContractArtifact, + TokenTransferProxy: (TokenTransferProxy as any) as ContractArtifact, + MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact, + MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: (MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress as any) as ContractArtifact, }; diff --git a/packages/deployer/package.json b/packages/deployer/package.json index 73bcd52f1..958f96441 100644 --- a/packages/deployer/package.json +++ b/packages/deployer/package.json @@ -14,7 +14,7 @@ "compile": "npm run build; node lib/src/cli.js compile", "clean": "shx rm -rf lib scripts", "migrate": "npm run build; node lib/src/cli.js migrate", - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "lint": "tslint --project .", "test:circleci": "yarn test:coverage", "docs:stage": "yarn build && node ./scripts/stage_docs.js", "manual:postpublish": "yarn build; node ./scripts/postpublish.js", diff --git a/packages/deployer/test/compiler_test.ts b/packages/deployer/test/compiler_test.ts index 9baf433d4..4c53a871a 100644 --- a/packages/deployer/test/compiler_test.ts +++ b/packages/deployer/test/compiler_test.ts @@ -1,9 +1,10 @@ +import { DoneCallback } from '@0xproject/types'; import * as chai from 'chai'; import 'mocha'; import { Compiler } from '../src/compiler'; import { fsWrapper } from '../src/utils/fs_wrapper'; -import { CompilerOptions, ContractArtifact, ContractNetworkData, DoneCallback } from '../src/utils/types'; +import { CompilerOptions, ContractArtifact, ContractNetworkData } from '../src/utils/types'; import { exchange_binary } from './fixtures/exchange_bin'; import { constants } from './util/constants'; diff --git a/packages/deployer/test/deployer_test.ts b/packages/deployer/test/deployer_test.ts index a8abc6454..8c92b38ca 100644 --- a/packages/deployer/test/deployer_test.ts +++ b/packages/deployer/test/deployer_test.ts @@ -1,10 +1,11 @@ +import { DoneCallback } from '@0xproject/types'; import * as chai from 'chai'; import 'mocha'; import { Compiler } from '../src/compiler'; import { Deployer } from '../src/deployer'; import { fsWrapper } from '../src/utils/fs_wrapper'; -import { CompilerOptions, ContractArtifact, ContractNetworkData, DoneCallback } from '../src/utils/types'; +import { CompilerOptions, ContractArtifact, ContractNetworkData } from '../src/utils/types'; import { constructor_args, exchange_binary } from './fixtures/exchange_bin'; import { constants } from './util/constants'; diff --git a/packages/dev-utils/CHANGELOG.json b/packages/dev-utils/CHANGELOG.json index 9da323f48..3f70a93cc 100644 --- a/packages/dev-utils/CHANGELOG.json +++ b/packages/dev-utils/CHANGELOG.json @@ -1,5 +1,14 @@ [ { + "version": "0.4.2", + "changes": [ + { + "note": "Move callbackErrorReporter over from 0x.js", + "pr": 579 + } + ] + }, + { "timestamp": 1525477860, "version": "0.4.1", "changes": [ diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 0422794ff..67b448024 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -13,7 +13,7 @@ "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 lib scripts", - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "lint": "tslint --project .", "manual:postpublish": "yarn build; node ./scripts/postpublish.js" }, "license": "Apache-2.0", diff --git a/packages/dev-utils/src/callback_error_reporter.ts b/packages/dev-utils/src/callback_error_reporter.ts new file mode 100644 index 000000000..c8e693673 --- /dev/null +++ b/packages/dev-utils/src/callback_error_reporter.ts @@ -0,0 +1,68 @@ +import * as chai from 'chai'; +import * as _ from 'lodash'; + +import { DoneCallback } from '@0xproject/types'; + +const expect = chai.expect; + +export const callbackErrorReporter = { + reportNoErrorCallbackErrors(done: DoneCallback, expectToBeCalledOnce = true) { + const callback = <T>(f?: (value: T) => void) => { + const wrapped = (value: T) => { + if (_.isUndefined(f)) { + done(); + return; + } + try { + f(value); + if (expectToBeCalledOnce) { + done(); + } + } catch (err) { + done(err); + } + }; + return wrapped; + }; + return callback; + }, + reportNodeCallbackErrors(done: DoneCallback, expectToBeCalledOnce = true) { + const callback = <T>(f?: (value: T) => void) => { + const wrapped = (error: Error | null, value: T | undefined) => { + if (!_.isNull(error)) { + done(error); + } else { + if (_.isUndefined(f)) { + done(); + return; + } + try { + f(value as T); + if (expectToBeCalledOnce) { + done(); + } + } catch (err) { + done(err); + } + } + }; + return wrapped; + }; + return callback; + }, + assertNodeCallbackError(done: DoneCallback, errMsg: string) { + const wrapped = <T>(error: Error | null, value: T | undefined) => { + if (_.isNull(error)) { + done(new Error('Expected callback to receive an error')); + } else { + try { + expect(error.message).to.be.equal(errMsg); + done(); + } catch (err) { + done(err); + } + } + }; + return wrapped; + }, +}; diff --git a/packages/dev-utils/src/index.ts b/packages/dev-utils/src/index.ts index 2ff2a2238..9124f3e28 100644 --- a/packages/dev-utils/src/index.ts +++ b/packages/dev-utils/src/index.ts @@ -3,3 +3,4 @@ export { web3Factory } from './web3_factory'; export { constants as devConstants } from './constants'; export { coverage } from './coverage'; export { env, EnvVars } from './env'; +export { callbackErrorReporter } from './callback_error_reporter'; diff --git a/packages/fill-scenarios/.npmignore b/packages/fill-scenarios/.npmignore new file mode 100644 index 000000000..24e65ad5b --- /dev/null +++ b/packages/fill-scenarios/.npmignore @@ -0,0 +1,6 @@ +.* +yarn-error.log +/scripts/ +/src/ +tsconfig.json +/lib/monorepo_scripts/ diff --git a/packages/fill-scenarios/CHANGELOG.json b/packages/fill-scenarios/CHANGELOG.json new file mode 100644 index 000000000..3cbba3ecb --- /dev/null +++ b/packages/fill-scenarios/CHANGELOG.json @@ -0,0 +1,11 @@ +[ + { + "version": "0.0.1", + "changes": [ + { + "note": "Move FillScenarios out of 0x.js", + "pr": 579 + } + ] + } +] diff --git a/packages/fill-scenarios/README.md b/packages/fill-scenarios/README.md new file mode 100644 index 000000000..e4cec0695 --- /dev/null +++ b/packages/fill-scenarios/README.md @@ -0,0 +1,75 @@ +## @0xproject/fill-scenarios + +0x order fill scenario generator + +## Installation + +```bash +yarn add @0xproject/fill-scenarios +``` + +If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: + +```json +"compilerOptions": { + "typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"], +} +``` + +## Contributing + +We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository. + +Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. + +### Install dependencies + +If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: + +```bash +yarn config set workspaces-experimental true +``` + +Then install dependencies + +```bash +yarn install +``` + +### Build + +If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory: + +```bash +yarn lerna:rebuild +``` + +Or continuously rebuild on change: + +```bash +yarn dev +``` + +You can also build this specific package by running the following from within its directory: + +```bash +yarn build +``` + +or continuously rebuild on change: + +```bash +yarn build:watch +``` + +### Clean + +```bash +yarn clean +``` + +### Lint + +```bash +yarn lint +``` diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json new file mode 100644 index 000000000..9ac419159 --- /dev/null +++ b/packages/fill-scenarios/package.json @@ -0,0 +1,48 @@ +{ + "name": "@0xproject/fill-scenarios", + "version": "0.0.1", + "description": "0x order fill scenario generator", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "scripts": { + "build:watch": "tsc -w", + "prebuild": "run-s clean generate_contract_wrappers", + "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'", + "build": "tsc && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", + "clean": "shx rm -rf lib scripts", + "lint": "tslint --project .", + "manual:postpublish": "yarn build; node ./scripts/postpublish.js" + }, + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/0xProject/0x-monorepo.git" + }, + "bugs": { + "url": "https://github.com/0xProject/0x-monorepo/issues" + }, + "homepage": "https://github.com/0xProject/0x-monorepo/packages/fill-scenarios/README.md", + "devDependencies": { + "@0xproject/monorepo-scripts": "^0.1.19", + "@0xproject/tslint-config": "^0.4.17", + "@types/lodash": "4.14.104", + "copyfiles": "^1.2.0", + "npm-run-all": "^4.1.2", + "shx": "^0.2.2", + "tslint": "5.8.0", + "typescript": "2.7.1" + }, + "dependencies": { + "@0xproject/base-contract": "^0.3.1", + "@0xproject/order-utils": "^0.0.4", + "@0xproject/types": "^0.6.3", + "@0xproject/typescript-typings": "^0.3.1", + "@0xproject/utils": "^0.6.1", + "@0xproject/web3-wrapper": "^0.6.3", + "ethers": "^3.0.15", + "lodash": "^4.17.4" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/fill-scenarios/src/artifacts.ts b/packages/fill-scenarios/src/artifacts.ts new file mode 100644 index 000000000..aa60e2fc4 --- /dev/null +++ b/packages/fill-scenarios/src/artifacts.ts @@ -0,0 +1,13 @@ +import { Artifact } from '@0xproject/types'; + +import * as DummyToken from './compact_artifacts/DummyToken.json'; +import * as Exchange from './compact_artifacts/Exchange.json'; +import * as Token from './compact_artifacts/Token.json'; +import * as TokenTransferProxy from './compact_artifacts/TokenTransferProxy.json'; + +export const artifacts = { + DummyToken: (DummyToken as any) as Artifact, + Token: (Token as any) as Artifact, + TokenTransferProxy: (TokenTransferProxy as any) as Artifact, + Exchange: (Exchange as any) as Artifact, +}; diff --git a/packages/fill-scenarios/src/compact_artifacts/DummyToken.json b/packages/fill-scenarios/src/compact_artifacts/DummyToken.json new file mode 100644 index 000000000..f64a8cd3d --- /dev/null +++ b/packages/fill-scenarios/src/compact_artifacts/DummyToken.json @@ -0,0 +1,22 @@ +{ + "contract_name": "DummyToken", + "abi": [ + { + "constant": false, + "inputs": [ + { + "name": "_target", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "setBalance", + "outputs": [], + "payable": false, + "type": "function" + } + ] +} diff --git a/packages/fill-scenarios/src/compact_artifacts/EtherToken.json b/packages/fill-scenarios/src/compact_artifacts/EtherToken.json new file mode 100644 index 000000000..26cca57cd --- /dev/null +++ b/packages/fill-scenarios/src/compact_artifacts/EtherToken.json @@ -0,0 +1,287 @@ +{ + "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" + } + } +} diff --git a/packages/fill-scenarios/src/compact_artifacts/Exchange.json b/packages/fill-scenarios/src/compact_artifacts/Exchange.json new file mode 100644 index 000000000..af8db7360 --- /dev/null +++ b/packages/fill-scenarios/src/compact_artifacts/Exchange.json @@ -0,0 +1,610 @@ +{ + "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" + } + } +} diff --git a/packages/fill-scenarios/src/compact_artifacts/Token.json b/packages/fill-scenarios/src/compact_artifacts/Token.json new file mode 100644 index 000000000..3b5a86ae0 --- /dev/null +++ b/packages/fill-scenarios/src/compact_artifacts/Token.json @@ -0,0 +1,172 @@ +{ + "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" + } + ] +} diff --git a/packages/fill-scenarios/src/compact_artifacts/TokenRegistry.json b/packages/fill-scenarios/src/compact_artifacts/TokenRegistry.json new file mode 100644 index 000000000..0f583628c --- /dev/null +++ b/packages/fill-scenarios/src/compact_artifacts/TokenRegistry.json @@ -0,0 +1,547 @@ +{ + "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" + } + } +} diff --git a/packages/fill-scenarios/src/compact_artifacts/TokenTransferProxy.json b/packages/fill-scenarios/src/compact_artifacts/TokenTransferProxy.json new file mode 100644 index 000000000..8cf551ddb --- /dev/null +++ b/packages/fill-scenarios/src/compact_artifacts/TokenTransferProxy.json @@ -0,0 +1,187 @@ +{ + "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" + } + } +} diff --git a/packages/fill-scenarios/src/compact_artifacts/ZRX.json b/packages/fill-scenarios/src/compact_artifacts/ZRX.json new file mode 100644 index 000000000..e40b8f268 --- /dev/null +++ b/packages/fill-scenarios/src/compact_artifacts/ZRX.json @@ -0,0 +1,20 @@ +{ + "contract_name": "ZRX", + "networks": { + "1": { + "address": "0xe41d2489571d322189246dafa5ebde1f4699f498" + }, + "3": { + "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d" + }, + "4": { + "address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8" + }, + "42": { + "address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570" + }, + "50": { + "address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401" + } + } +} diff --git a/packages/fill-scenarios/src/constants.ts b/packages/fill-scenarios/src/constants.ts new file mode 100644 index 000000000..0cd3d607a --- /dev/null +++ b/packages/fill-scenarios/src/constants.ts @@ -0,0 +1,4 @@ +export const constants = { + NULL_ADDRESS: '0x0000000000000000000000000000000000000000', + TEST_RPC_NETWORK_ID: 50, +}; diff --git a/packages/fill-scenarios/src/globals.d.ts b/packages/fill-scenarios/src/globals.d.ts new file mode 100644 index 000000000..94e63a32d --- /dev/null +++ b/packages/fill-scenarios/src/globals.d.ts @@ -0,0 +1,6 @@ +declare module '*.json' { + const json: any; + /* tslint:disable */ + export default json; + /* tslint:enable */ +} diff --git a/packages/0x.js/test/utils/fill_scenarios.ts b/packages/fill-scenarios/src/index.ts index 5a82a56d2..673a65226 100644 --- a/packages/0x.js/test/utils/fill_scenarios.ts +++ b/packages/fill-scenarios/src/index.ts @@ -1,30 +1,32 @@ -import { orderFactory } from '@0xproject/order-utils'; +import { formatters, orderFactory } from '@0xproject/order-utils'; +import { Provider, SignedOrder, Token } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as _ from 'lodash'; -import { SignedOrder, Token, ZeroEx } from '../../src'; -import { artifacts } from '../../src/artifacts'; -import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token'; - +import { artifacts } from './artifacts'; import { constants } from './constants'; +import { DummyTokenContract } from './generated_contract_wrappers/dummy_token'; +import { ExchangeContract } from './generated_contract_wrappers/exchange'; +import { TokenContract } from './generated_contract_wrappers/token'; const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100); export class FillScenarios { - private _zeroEx: ZeroEx; + private _web3Wrapper: Web3Wrapper; private _userAddresses: string[]; private _tokens: Token[]; private _coinbase: string; private _zrxTokenAddress: string; private _exchangeContractAddress: string; constructor( - zeroEx: ZeroEx, + provider: Provider, userAddresses: string[], tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string, ) { - this._zeroEx = zeroEx; + this._web3Wrapper = new Web3Wrapper(provider); this._userAddresses = userAddresses; this._tokens = tokens; this._coinbase = userAddresses[0]; @@ -32,21 +34,23 @@ export class FillScenarios { this._exchangeContractAddress = exchangeContractAddress; } public async initTokenBalancesAsync() { - const web3Wrapper = (this._zeroEx as any)._web3Wrapper as Web3Wrapper; for (const token of this._tokens) { if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') { const defaults = {}; const dummyToken = new DummyTokenContract( - artifacts.DummyTokenArtifact.abi, + artifacts.DummyToken.abi, token.address, - web3Wrapper.getProvider(), - web3Wrapper.getContractDefaults(), + this._web3Wrapper.getProvider(), + this._web3Wrapper.getContractDefaults(), + ); + const tokenSupply = Web3Wrapper.toBaseUnitAmount( + INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, + token.decimals, ); - const tokenSupply = ZeroEx.toBaseUnitAmount(INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, token.decimals); const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, { from: this._coinbase, }); - await this._zeroEx.awaitTransactionMinedAsync(txHash); + await this._web3Wrapper.awaitTransactionMinedAsync(txHash); } } } @@ -134,11 +138,24 @@ export class FillScenarios { fillableAmount, ); const shouldThrowOnInsufficientBalanceOrAllowance = false; - await this._zeroEx.exchange.fillOrderAsync( - signedOrder, + const exchangeInstance = new ExchangeContract( + artifacts.Exchange.abi, + signedOrder.exchangeContractAddress, + this._web3Wrapper.getProvider(), + this._web3Wrapper.getContractDefaults(), + ); + + const [orderAddresses, orderValues] = formatters.getOrderAddressesAndValues(signedOrder); + + await exchangeInstance.fillOrder.sendTransactionAsync( + orderAddresses, + orderValues, partialFillAmount, shouldThrowOnInsufficientBalanceOrAllowance, - takerAddress, + signedOrder.ecSignature.v, + signedOrder.ecSignature.r, + signedOrder.ecSignature.s, + { from: takerAddress }, ); return signedOrder; } @@ -164,7 +181,7 @@ export class FillScenarios { ]); const signedOrder = await orderFactory.createSignedOrderAsync( - this._zeroEx.getProvider(), + this._web3Wrapper.getProvider(), makerAddress, takerAddress, makerFee, @@ -184,7 +201,7 @@ export class FillScenarios { address: string, amount: BigNumber, ): Promise<void> { - if (amount.isZero() || address === ZeroEx.NULL_ADDRESS) { + if (amount.isZero() || address === constants.NULL_ADDRESS) { return; // noop } await Promise.all([ @@ -193,11 +210,33 @@ export class FillScenarios { ]); } private async _increaseBalanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> { - await this._zeroEx.token.transferAsync(tokenAddress, this._coinbase, address, amount); + const token = new TokenContract( + artifacts.Token.abi, + tokenAddress, + this._web3Wrapper.getProvider(), + this._web3Wrapper.getContractDefaults(), + ); + await token.transfer.sendTransactionAsync(address, amount, { + from: this._coinbase, + }); } private async _increaseAllowanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> { - const oldMakerAllowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, address); + const tokenInstance = new TokenContract( + artifacts.Token.abi, + tokenAddress, + this._web3Wrapper.getProvider(), + this._web3Wrapper.getContractDefaults(), + ); + const networkArtifactsIfExists = artifacts.TokenTransferProxy.networks[constants.TEST_RPC_NETWORK_ID]; + if (_.isUndefined(networkArtifactsIfExists)) { + throw new Error(`Did not find network artifacts for networkId: ${constants.TEST_RPC_NETWORK_ID}`); + } + const proxyAddress = networkArtifactsIfExists.address; + const oldMakerAllowance = await tokenInstance.allowance.callAsync(address, proxyAddress); const newMakerAllowance = oldMakerAllowance.plus(amount); - await this._zeroEx.token.setProxyAllowanceAsync(tokenAddress, address, newMakerAllowance); + + await tokenInstance.approve.sendTransactionAsync(proxyAddress, newMakerAllowance, { + from: address, + }); } } diff --git a/packages/fill-scenarios/src/monorepo_scripts/postpublish.ts b/packages/fill-scenarios/src/monorepo_scripts/postpublish.ts new file mode 100644 index 000000000..dcb99d0f7 --- /dev/null +++ b/packages/fill-scenarios/src/monorepo_scripts/postpublish.ts @@ -0,0 +1,8 @@ +import { postpublishUtils } from '@0xproject/monorepo-scripts'; + +import * as packageJSON from '../package.json'; +import * as tsConfigJSON from '../tsconfig.json'; + +const cwd = `${__dirname}/..`; +// tslint:disable-next-line:no-floating-promises +postpublishUtils.runAsync(packageJSON, tsConfigJSON, cwd); diff --git a/packages/fill-scenarios/tsconfig.json b/packages/fill-scenarios/tsconfig.json new file mode 100644 index 000000000..f5f4b37c2 --- /dev/null +++ b/packages/fill-scenarios/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src/**/*"] +} diff --git a/packages/fill-scenarios/tslint.json b/packages/fill-scenarios/tslint.json new file mode 100644 index 000000000..ffaefe83a --- /dev/null +++ b/packages/fill-scenarios/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": ["@0xproject/tslint-config"] +} diff --git a/packages/json-schemas/package.json b/packages/json-schemas/package.json index f67f653f0..9da9da2b7 100644 --- a/packages/json-schemas/package.json +++ b/packages/json-schemas/package.json @@ -6,7 +6,7 @@ "types": "lib/src/index.d.ts", "scripts": { "build:watch": "tsc -w", - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "lint": "tslint --project .", "test": "run-s clean build run_mocha", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", diff --git a/packages/migrations/package.json b/packages/migrations/package.json index 8c85aa337..509cf81fb 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -8,7 +8,7 @@ "build:watch": "tsc -w", "build": "tsc", "clean": "shx rm -rf lib", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "migrate": "run-s build compile script:migrate", "script:migrate": "node ./lib/migrate.js", "copy_artifacts": "copyfiles 'src/artifacts/**/*' ./lib", diff --git a/packages/monorepo-scripts/package.json b/packages/monorepo-scripts/package.json index a6b6f2d15..859c23149 100644 --- a/packages/monorepo-scripts/package.json +++ b/packages/monorepo-scripts/package.json @@ -6,7 +6,7 @@ "types": "lib/index.d.ts", "scripts": { "build:watch": "tsc -w", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "clean": "shx rm -rf lib", "build": "tsc", "test:publish": "run-s build script:publish", diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 44f919bc2..9399379fa 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -1,5 +1,17 @@ [ { + "version": "0.0.5", + "changes": [ + { + "note": "Add formatters package for converting signedOrder to orderAddresses & orderValues", + "note": "Add RemainingFillableCalculator to calculate the remaining fillable amount of an order", + "note": "Add AbstractBalanceAndProxyAllowanceFetcher and AbstractOrderFilledCancelledFetcher", + "note": + "Add orderStateUtils, a module for computing order state needed to decide if an order is still valid" + } + ] + }, + { "timestamp": 1525477860, "version": "0.0.4", "changes": [ diff --git a/packages/0x.js/src/abstract/balance_and_proxy_allowance_fetcher.ts b/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts index c357f8447..857c6167f 100644 --- a/packages/0x.js/src/abstract/balance_and_proxy_allowance_fetcher.ts +++ b/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts @@ -1,6 +1,6 @@ import { BigNumber } from '@0xproject/utils'; -export abstract class BalanceAndProxyAllowanceFetcher { +export abstract class AbstractBalanceAndProxyAllowanceFetcher { public abstract async getBalanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; public abstract async getProxyAllowanceAsync(tokenAddress: string, userAddress: string): Promise<BigNumber>; } diff --git a/packages/0x.js/src/abstract/order_filled_cancelled_fetcher.ts b/packages/order-utils/src/abstract/abstract_order_filled_cancelled_fetcher.ts index 81ae04b9c..f54bed6f1 100644 --- a/packages/0x.js/src/abstract/order_filled_cancelled_fetcher.ts +++ b/packages/order-utils/src/abstract/abstract_order_filled_cancelled_fetcher.ts @@ -1,6 +1,8 @@ import { BigNumber } from '@0xproject/utils'; -export abstract class OrderFilledCancelledFetcher { +export abstract class AbstractOrderFilledCancelledFetcher { public abstract async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>; public abstract async getCancelledTakerAmountAsync(orderHash: string): Promise<BigNumber>; + public abstract async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber>; + public abstract getZRXTokenAddress(): string; } diff --git a/packages/order-utils/src/compact_artifacts/DummyToken.json b/packages/order-utils/src/compact_artifacts/DummyToken.json new file mode 100644 index 000000000..f64a8cd3d --- /dev/null +++ b/packages/order-utils/src/compact_artifacts/DummyToken.json @@ -0,0 +1,22 @@ +{ + "contract_name": "DummyToken", + "abi": [ + { + "constant": false, + "inputs": [ + { + "name": "_target", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "setBalance", + "outputs": [], + "payable": false, + "type": "function" + } + ] +} diff --git a/packages/order-utils/src/compact_artifacts/EtherToken.json b/packages/order-utils/src/compact_artifacts/EtherToken.json new file mode 100644 index 000000000..26cca57cd --- /dev/null +++ b/packages/order-utils/src/compact_artifacts/EtherToken.json @@ -0,0 +1,287 @@ +{ + "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" + } + } +} diff --git a/packages/order-utils/src/compact_artifacts/Exchange.json b/packages/order-utils/src/compact_artifacts/Exchange.json new file mode 100644 index 000000000..af8db7360 --- /dev/null +++ b/packages/order-utils/src/compact_artifacts/Exchange.json @@ -0,0 +1,610 @@ +{ + "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" + } + } +} diff --git a/packages/order-utils/src/compact_artifacts/Token.json b/packages/order-utils/src/compact_artifacts/Token.json new file mode 100644 index 000000000..3b5a86ae0 --- /dev/null +++ b/packages/order-utils/src/compact_artifacts/Token.json @@ -0,0 +1,172 @@ +{ + "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" + } + ] +} diff --git a/packages/order-utils/src/compact_artifacts/TokenRegistry.json b/packages/order-utils/src/compact_artifacts/TokenRegistry.json new file mode 100644 index 000000000..0f583628c --- /dev/null +++ b/packages/order-utils/src/compact_artifacts/TokenRegistry.json @@ -0,0 +1,547 @@ +{ + "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" + } + } +} diff --git a/packages/order-utils/src/compact_artifacts/TokenTransferProxy.json b/packages/order-utils/src/compact_artifacts/TokenTransferProxy.json new file mode 100644 index 000000000..8cf551ddb --- /dev/null +++ b/packages/order-utils/src/compact_artifacts/TokenTransferProxy.json @@ -0,0 +1,187 @@ +{ + "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" + } + } +} diff --git a/packages/order-utils/src/compact_artifacts/ZRX.json b/packages/order-utils/src/compact_artifacts/ZRX.json new file mode 100644 index 000000000..e40b8f268 --- /dev/null +++ b/packages/order-utils/src/compact_artifacts/ZRX.json @@ -0,0 +1,20 @@ +{ + "contract_name": "ZRX", + "networks": { + "1": { + "address": "0xe41d2489571d322189246dafa5ebde1f4699f498" + }, + "3": { + "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d" + }, + "4": { + "address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8" + }, + "42": { + "address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570" + }, + "50": { + "address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401" + } + } +} diff --git a/packages/order-utils/src/formatters.ts b/packages/order-utils/src/formatters.ts new file mode 100644 index 000000000..2b6f4ddb7 --- /dev/null +++ b/packages/order-utils/src/formatters.ts @@ -0,0 +1,23 @@ +import { Order, OrderAddresses, OrderValues } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; + +export const formatters = { + getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] { + const orderAddresses: OrderAddresses = [ + order.maker, + order.taker, + order.makerTokenAddress, + order.takerTokenAddress, + order.feeRecipient, + ]; + const orderValues: OrderValues = [ + order.makerTokenAmount, + order.takerTokenAmount, + order.makerFee, + order.takerFee, + order.expirationUnixTimestampSec, + order.salt, + ]; + return [orderAddresses, orderValues]; + }, +}; diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index b85432c84..e9cea95ed 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -4,3 +4,8 @@ export { orderFactory } from './order_factory'; export { constants } from './constants'; export { generatePseudoRandomSalt } from './salt'; export { OrderError } from './types'; +export { formatters } from './formatters'; +export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher'; +export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher'; +export { RemainingFillableCalculator } from './remaining_fillable_calculator'; +export { OrderStateUtils } from './order_state_utils'; diff --git a/packages/0x.js/src/utils/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index b0310d8a8..36171f526 100644 --- a/packages/0x.js/src/utils/order_state_utils.ts +++ b/packages/order-utils/src/order_state_utils.ts @@ -1,19 +1,24 @@ -import { SignedOrder } from '@0xproject/types'; +import { + ExchangeContractErrs, + OrderRelevantState, + OrderState, + OrderStateInvalid, + OrderStateValid, + SignedOrder, +} from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; -import { ZeroEx } from '../0x'; -import { BalanceAndProxyAllowanceFetcher } from '../abstract/balance_and_proxy_allowance_fetcher'; -import { OrderFilledCancelledFetcher } from '../abstract/order_filled_cancelled_fetcher'; -import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; -import { RemainingFillableCalculator } from '../order_watcher/remaining_fillable_calculator'; -import { ExchangeContractErrs, OrderRelevantState, OrderState, OrderStateInvalid, OrderStateValid } from '../types'; +import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher'; +import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher'; +import { getOrderHashHex } from './order_hash'; +import { RemainingFillableCalculator } from './remaining_fillable_calculator'; const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001; export class OrderStateUtils { - private _balanceAndProxyAllowanceFetcher: BalanceAndProxyAllowanceFetcher; - private _orderFilledCancelledFetcher: OrderFilledCancelledFetcher; + private _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; + private _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; private static _validateIfOrderIsValid(signedOrder: SignedOrder, orderRelevantState: OrderRelevantState): void { const unavailableTakerTokenAmount = orderRelevantState.cancelledTakerTokenAmount.add( orderRelevantState.filledTakerTokenAmount, @@ -49,15 +54,15 @@ export class OrderStateUtils { } } constructor( - balanceAndProxyAllowanceFetcher: BalanceAndProxyAllowanceFetcher, - orderFilledCancelledFetcher: OrderFilledCancelledFetcher, + balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher, + orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher, ) { this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher; this._orderFilledCancelledFetcher = orderFilledCancelledFetcher; } public async getOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> { const orderRelevantState = await this.getOrderRelevantStateAsync(signedOrder); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); + const orderHash = getOrderHashHex(signedOrder); try { OrderStateUtils._validateIfOrderIsValid(signedOrder, orderRelevantState); const orderState: OrderStateValid = { @@ -76,13 +81,8 @@ export class OrderStateUtils { } } public async getOrderRelevantStateAsync(signedOrder: SignedOrder): Promise<OrderRelevantState> { - // HACK: We access the private property here but otherwise the interface will be less nice. - // If we pass it from the instantiator - there is no opportunity to get it there - // because JS doesn't support async constructors. - // Moreover - it's cached under the hood so it's equivalent to an async constructor. - const exchange = (this._orderFilledCancelledFetcher as any)._exchangeWrapper as ExchangeWrapper; - const zrxTokenAddress = exchange.getZRXTokenAddress(); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); + const zrxTokenAddress = this._orderFilledCancelledFetcher.getZRXTokenAddress(); + const orderHash = getOrderHashHex(signedOrder); const makerBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync( signedOrder.makerTokenAddress, signedOrder.maker, @@ -103,7 +103,9 @@ export class OrderStateUtils { const cancelledTakerTokenAmount = await this._orderFilledCancelledFetcher.getCancelledTakerAmountAsync( orderHash, ); - const unavailableTakerTokenAmount = await exchange.getUnavailableTakerAmountAsync(orderHash); + const unavailableTakerTokenAmount = await this._orderFilledCancelledFetcher.getUnavailableTakerAmountAsync( + orderHash, + ); const totalMakerTokenAmount = signedOrder.makerTokenAmount; const totalTakerTokenAmount = signedOrder.takerTokenAmount; const remainingTakerTokenAmount = totalTakerTokenAmount.minus(unavailableTakerTokenAmount); diff --git a/packages/0x.js/src/order_watcher/remaining_fillable_calculator.ts b/packages/order-utils/src/remaining_fillable_calculator.ts index 184c13aa4..184c13aa4 100644 --- a/packages/0x.js/src/order_watcher/remaining_fillable_calculator.ts +++ b/packages/order-utils/src/remaining_fillable_calculator.ts diff --git a/packages/order-watcher/.npmignore b/packages/order-watcher/.npmignore new file mode 100644 index 000000000..c5be1b302 --- /dev/null +++ b/packages/order-watcher/.npmignore @@ -0,0 +1,10 @@ +.* +tsconfig.json +webpack.config.js +yarn-error.log +test/ +/src/ +/_bundles/ +/generated_docs/ +/scripts/ +/lib/src/monorepo_scripts/ diff --git a/packages/order-watcher/CHANGELOG.json b/packages/order-watcher/CHANGELOG.json new file mode 100644 index 000000000..87f40bcb7 --- /dev/null +++ b/packages/order-watcher/CHANGELOG.json @@ -0,0 +1,11 @@ +[ + { + "version": "0.0.1", + "changes": [ + { + "note": "Moved OrderWatcher out of 0x.js package", + "pr": 579 + } + ] + } +] diff --git a/packages/order-watcher/README.md b/packages/order-watcher/README.md new file mode 100644 index 000000000..d461dca8d --- /dev/null +++ b/packages/order-watcher/README.md @@ -0,0 +1,91 @@ +## OrderWatcher + +An order watcher daemon that watches for order validity. + +#### Read the wiki [article](https://0xproject.com/wiki#0x-OrderWatcher). + +## Installation + +**Install** + +```bash +npm install @0xproject/order-watcher --save +``` + +**Import** + +```javascript +import { OrderWatcher } from '@0xproject/order-watcher'; +``` + +If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: + +```json +"compilerOptions": { + "typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"], +} +``` + +## Contributing + +We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. + +Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. + +### Install dependencies + +If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: + +```bash +yarn config set workspaces-experimental true +``` + +Then install dependencies + +```bash +yarn install +``` + +### Build + +If this is your **first** time building this package, you must first build **all** packages within the monorepo. This is because packages that depend on other packages located inside this monorepo are symlinked when run from **within** the monorepo. This allows you to make changes across multiple packages without first publishing dependent packages to NPM. To build all packages, run the following from the monorepo root directory: + +```bash +yarn lerna:rebuild +``` + +Or continuously rebuild on change: + +```bash +yarn dev +``` + +You can also build this specific package by running the following from within its directory: + +```bash +yarn build +``` + +or continuously rebuild on change: + +```bash +yarn build:watch +``` + +### Clean + +```bash +yarn clean +``` + +### Lint + +```bash +yarn lint +``` + +### Run Tests + +```bash +yarn test +``` diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json new file mode 100644 index 000000000..b4357bfb5 --- /dev/null +++ b/packages/order-watcher/package.json @@ -0,0 +1,94 @@ +{ + "name": "@0xproject/order-watcher", + "version": "0.0.1", + "description": "An order watcher daemon that watches for order validity", + "keywords": [ + "0x", + "0xproject", + "ethereum", + "exchange", + "orderbook" + ], + "main": "lib/src/index.js", + "types": "lib/src/index.d.ts", + "scripts": { + "build:watch": "tsc -w", + "prebuild": "run-s clean generate_contract_wrappers", + "generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'", + "lint": "tslint --project .", + "test:circleci": "run-s test:coverage", + "test": "run-s clean build run_mocha", + "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", + "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", + "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/src/artifacts/$i.json test/artifacts; done;", + "clean": "shx rm -rf _bundles lib test_temp scripts", + "build": "tsc && yarn update_artifacts && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", + "run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit", + "manual:postpublish": "yarn build; node ./scripts/postpublish.js" + }, + "config": { + "compact_artifacts": "Exchange DummyToken ZRXToken Token EtherToken TokenTransferProxy TokenRegistry", + "contracts": "Exchange DummyToken ZRXToken Token WETH9 TokenTransferProxy MultiSigWallet MultiSigWalletWithTimeLock MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress MaliciousToken TokenRegistry Arbitrage EtherDelta AccountLevels", + "postpublish": { + "assets": [ + "packages/order-watcher/_bundles/index.js", + "packages/order-watcher/_bundles/index.min.js" + ] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/0xProject/0x-monorepo" + }, + "license": "Apache-2.0", + "engines": { + "node": ">=6.0.0" + }, + "devDependencies": { + "@0xproject/deployer": "^0.4.3", + "@0xproject/dev-utils": "^0.4.1", + "@0xproject/migrations": "^0.0.5", + "@0xproject/monorepo-scripts": "^0.1.19", + "@0xproject/tslint-config": "^0.4.17", + "@types/bintrees": "^1.0.2", + "@types/lodash": "4.14.104", + "@types/mocha": "^2.2.42", + "@types/node": "^8.0.53", + "@types/sinon": "^2.2.2", + "awesome-typescript-loader": "^3.1.3", + "chai": "^4.0.1", + "chai-as-promised": "^7.1.0", + "chai-bignumber": "^2.0.1", + "copyfiles": "^1.2.0", + "dirty-chai": "^2.0.1", + "json-loader": "^0.5.4", + "mocha": "^4.0.1", + "npm-run-all": "^4.1.2", + "nyc": "^11.0.1", + "opn-cli": "^3.1.0", + "prettier": "^1.11.1", + "shx": "^0.2.2", + "sinon": "^4.0.0", + "source-map-support": "^0.5.0", + "tslint": "5.8.0", + "typescript": "2.7.1" + }, + "dependencies": { + "@0xproject/contract-wrappers": "^0.0.1", + "@0xproject/assert": "^0.2.9", + "@0xproject/base-contract": "^0.3.1", + "@0xproject/fill-scenarios": "^0.0.1", + "@0xproject/json-schemas": "^0.7.23", + "@0xproject/order-utils": "^0.0.4", + "@0xproject/types": "^0.6.3", + "@0xproject/typescript-typings": "^0.3.1", + "@0xproject/utils": "^0.6.1", + "@0xproject/web3-wrapper": "^0.6.3", + "bintrees": "^1.0.2", + "ethers": "^3.0.15", + "lodash": "^4.17.4" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/order-watcher/src/artifacts.ts b/packages/order-watcher/src/artifacts.ts new file mode 100644 index 000000000..13587984c --- /dev/null +++ b/packages/order-watcher/src/artifacts.ts @@ -0,0 +1,18 @@ +import { Artifact } from '@0xproject/types'; + +import * as DummyToken from './compact_artifacts/DummyToken.json'; +import * as EtherToken from './compact_artifacts/EtherToken.json'; +import * as Exchange from './compact_artifacts/Exchange.json'; +import * as Token from './compact_artifacts/Token.json'; +import * as TokenRegistry from './compact_artifacts/TokenRegistry.json'; +import * as TokenTransferProxy from './compact_artifacts/TokenTransferProxy.json'; +import * as ZRX from './compact_artifacts/ZRX.json'; +export const artifacts = { + ZRX: (ZRX as any) as Artifact, + DummyToken: (DummyToken as any) as Artifact, + Token: (Token as any) as Artifact, + Exchange: (Exchange as any) as Artifact, + EtherToken: (EtherToken as any) as Artifact, + TokenRegistry: (TokenRegistry as any) as Artifact, + TokenTransferProxy: (TokenTransferProxy as any) as Artifact, +}; diff --git a/packages/order-watcher/src/compact_artifacts/DummyToken.json b/packages/order-watcher/src/compact_artifacts/DummyToken.json new file mode 100644 index 000000000..f64a8cd3d --- /dev/null +++ b/packages/order-watcher/src/compact_artifacts/DummyToken.json @@ -0,0 +1,22 @@ +{ + "contract_name": "DummyToken", + "abi": [ + { + "constant": false, + "inputs": [ + { + "name": "_target", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "setBalance", + "outputs": [], + "payable": false, + "type": "function" + } + ] +} diff --git a/packages/order-watcher/src/compact_artifacts/EtherToken.json b/packages/order-watcher/src/compact_artifacts/EtherToken.json new file mode 100644 index 000000000..26cca57cd --- /dev/null +++ b/packages/order-watcher/src/compact_artifacts/EtherToken.json @@ -0,0 +1,287 @@ +{ + "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" + } + } +} diff --git a/packages/order-watcher/src/compact_artifacts/Exchange.json b/packages/order-watcher/src/compact_artifacts/Exchange.json new file mode 100644 index 000000000..af8db7360 --- /dev/null +++ b/packages/order-watcher/src/compact_artifacts/Exchange.json @@ -0,0 +1,610 @@ +{ + "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" + } + } +} diff --git a/packages/order-watcher/src/compact_artifacts/Token.json b/packages/order-watcher/src/compact_artifacts/Token.json new file mode 100644 index 000000000..3b5a86ae0 --- /dev/null +++ b/packages/order-watcher/src/compact_artifacts/Token.json @@ -0,0 +1,172 @@ +{ + "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" + } + ] +} diff --git a/packages/order-watcher/src/compact_artifacts/TokenRegistry.json b/packages/order-watcher/src/compact_artifacts/TokenRegistry.json new file mode 100644 index 000000000..0f583628c --- /dev/null +++ b/packages/order-watcher/src/compact_artifacts/TokenRegistry.json @@ -0,0 +1,547 @@ +{ + "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" + } + } +} diff --git a/packages/order-watcher/src/compact_artifacts/TokenTransferProxy.json b/packages/order-watcher/src/compact_artifacts/TokenTransferProxy.json new file mode 100644 index 000000000..8cf551ddb --- /dev/null +++ b/packages/order-watcher/src/compact_artifacts/TokenTransferProxy.json @@ -0,0 +1,187 @@ +{ + "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" + } + } +} diff --git a/packages/order-watcher/src/compact_artifacts/ZRX.json b/packages/order-watcher/src/compact_artifacts/ZRX.json new file mode 100644 index 000000000..e40b8f268 --- /dev/null +++ b/packages/order-watcher/src/compact_artifacts/ZRX.json @@ -0,0 +1,20 @@ +{ + "contract_name": "ZRX", + "networks": { + "1": { + "address": "0xe41d2489571d322189246dafa5ebde1f4699f498" + }, + "3": { + "address": "0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d" + }, + "4": { + "address": "0x00f58d6d585f84b2d7267940cede30ce2fe6eae8" + }, + "42": { + "address": "0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570" + }, + "50": { + "address": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401" + } + } +} diff --git a/packages/order-watcher/src/globals.d.ts b/packages/order-watcher/src/globals.d.ts new file mode 100644 index 000000000..94e63a32d --- /dev/null +++ b/packages/order-watcher/src/globals.d.ts @@ -0,0 +1,6 @@ +declare module '*.json' { + const json: any; + /* tslint:disable */ + export default json; + /* tslint:enable */ +} diff --git a/packages/order-watcher/src/index.ts b/packages/order-watcher/src/index.ts new file mode 100644 index 000000000..390003b1d --- /dev/null +++ b/packages/order-watcher/src/index.ts @@ -0,0 +1,7 @@ +export { OrderWatcher } from './order_watcher/order_watcher'; + +export { OrderStateValid, OrderStateInvalid, OrderState } from '@0xproject/types'; + +export { OnOrderStateChangeCallback, OrderWatcherConfig } from './types'; + +export { BlockParamLiteral, BlockParam, Order, Provider, SignedOrder } from '@0xproject/types'; diff --git a/packages/order-watcher/src/monorepo_scripts/postpublish.ts b/packages/order-watcher/src/monorepo_scripts/postpublish.ts new file mode 100644 index 000000000..dcb99d0f7 --- /dev/null +++ b/packages/order-watcher/src/monorepo_scripts/postpublish.ts @@ -0,0 +1,8 @@ +import { postpublishUtils } from '@0xproject/monorepo-scripts'; + +import * as packageJSON from '../package.json'; +import * as tsConfigJSON from '../tsconfig.json'; + +const cwd = `${__dirname}/..`; +// tslint:disable-next-line:no-floating-promises +postpublishUtils.runAsync(packageJSON, tsConfigJSON, cwd); diff --git a/packages/0x.js/src/order_watcher/event_watcher.ts b/packages/order-watcher/src/order_watcher/event_watcher.ts index de5a99a46..f39d3bf0e 100644 --- a/packages/0x.js/src/order_watcher/event_watcher.ts +++ b/packages/order-watcher/src/order_watcher/event_watcher.ts @@ -3,7 +3,7 @@ import { intervalUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; -import { EventWatcherCallback, ZeroExError } from '../types'; +import { EventWatcherCallback, OrderWatcherError } from '../types'; import { assert } from '../utils/assert'; const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200; @@ -37,7 +37,7 @@ export class EventWatcher { public subscribe(callback: EventWatcherCallback): void { assert.isFunction('callback', callback); if (!_.isUndefined(this._intervalIdIfExists)) { - throw new Error(ZeroExError.SubscriptionAlreadyPresent); + throw new Error(OrderWatcherError.SubscriptionAlreadyPresent); } this._intervalIdIfExists = intervalUtils.setAsyncExcludingInterval( this._pollForBlockchainEventsAsync.bind(this, callback), diff --git a/packages/0x.js/src/order_watcher/expiration_watcher.ts b/packages/order-watcher/src/order_watcher/expiration_watcher.ts index 27ec7107d..ec2c1ec35 100644 --- a/packages/0x.js/src/order_watcher/expiration_watcher.ts +++ b/packages/order-watcher/src/order_watcher/expiration_watcher.ts @@ -2,7 +2,7 @@ import { BigNumber, intervalUtils } from '@0xproject/utils'; import { RBTree } from 'bintrees'; import * as _ from 'lodash'; -import { ZeroExError } from '../types'; +import { OrderWatcherError } from '../types'; import { utils } from '../utils/utils'; const DEFAULT_EXPIRATION_MARGIN_MS = 0; @@ -37,7 +37,7 @@ export class ExpirationWatcher { } public subscribe(callback: (orderHash: string) => void): void { if (!_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) { - throw new Error(ZeroExError.SubscriptionAlreadyPresent); + throw new Error(OrderWatcherError.SubscriptionAlreadyPresent); } this._orderExpirationCheckingIntervalIdIfExists = intervalUtils.setInterval( this._pruneExpiredOrders.bind(this, callback), @@ -47,7 +47,7 @@ export class ExpirationWatcher { } public unsubscribe(): void { if (_.isUndefined(this._orderExpirationCheckingIntervalIdIfExists)) { - throw new Error(ZeroExError.SubscriptionNotFound); + throw new Error(OrderWatcherError.SubscriptionNotFound); } intervalUtils.clearInterval(this._orderExpirationCheckingIntervalIdIfExists); delete this._orderExpirationCheckingIntervalIdIfExists; diff --git a/packages/0x.js/src/order_watcher/order_state_watcher.ts b/packages/order-watcher/src/order_watcher/order_watcher.ts index a9df8ac9d..63f87b565 100644 --- a/packages/0x.js/src/order_watcher/order_state_watcher.ts +++ b/packages/order-watcher/src/order_watcher/order_watcher.ts @@ -1,45 +1,51 @@ +import { + BalanceAndProxyAllowanceLazyStore, + ContractWrappers, + OrderFilledCancelledLazyStore, +} from '@0xproject/contract-wrappers'; import { schemas } from '@0xproject/json-schemas'; -import { BlockParamLiteral, LogWithDecodedArgs, SignedOrder } from '@0xproject/types'; +import { getOrderHashHex, OrderStateUtils } from '@0xproject/order-utils'; +import { + BlockParamLiteral, + ExchangeContractErrs, + LogEntryEvent, + LogWithDecodedArgs, + OrderState, + Provider, + SignedOrder, +} from '@0xproject/types'; import { AbiDecoder, intervalUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; -import { ZeroEx } from '../0x'; -import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; +import { artifacts } from '../artifacts'; import { DepositContractEventArgs, + EtherTokenContractEventArgs, EtherTokenEvents, WithdrawalContractEventArgs, -} from '../contract_wrappers/generated/ether_token'; +} from '../generated_contract_wrappers/ether_token'; import { + ExchangeContractEventArgs, ExchangeEvents, LogCancelContractEventArgs, LogFillContractEventArgs, -} from '../contract_wrappers/generated/exchange'; +} from '../generated_contract_wrappers/exchange'; import { ApprovalContractEventArgs, + TokenContractEventArgs, TokenEvents, TransferContractEventArgs, -} from '../contract_wrappers/generated/token'; -import { TokenWrapper } from '../contract_wrappers/token_wrapper'; -import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store'; -import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store'; -import { - ContractEventArgs, - ExchangeContractErrs, - LogEvent, - OnOrderStateChangeCallback, - OrderState, - OrderStateWatcherConfig, - ZeroExError, -} from '../types'; +} from '../generated_contract_wrappers/token'; +import { OnOrderStateChangeCallback, OrderWatcherConfig, OrderWatcherError } from '../types'; import { assert } from '../utils/assert'; -import { OrderStateUtils } from '../utils/order_state_utils'; import { utils } from '../utils/utils'; import { EventWatcher } from './event_watcher'; import { ExpirationWatcher } from './expiration_watcher'; +type ContractEventArgs = EtherTokenContractEventArgs | ExchangeContractEventArgs | TokenContractEventArgs; + interface DependentOrderHashes { [makerAddress: string]: { [makerToken: string]: Set<string>; @@ -62,7 +68,8 @@ const DEFAULT_CLEANUP_JOB_INTERVAL_MS = 1000 * 60 * 60; // 1h * the subscriber of these changes so that a final decision can be made on whether * the order should be deemed invalid. */ -export class OrderStateWatcher { +export class OrderWatcher { + private _contractWrappers: ContractWrappers; private _orderStateByOrderHashCache: OrderStateByOrderHash = {}; private _orderByOrderHash: OrderByOrderHash = {}; private _dependentOrderHashes: DependentOrderHashes = {}; @@ -75,19 +82,26 @@ export class OrderStateWatcher { private _balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore; private _cleanupJobInterval: number; private _cleanupJobIntervalIdIfExists?: NodeJS.Timer; - constructor( - web3Wrapper: Web3Wrapper, - token: TokenWrapper, - exchange: ExchangeWrapper, - config?: OrderStateWatcherConfig, - ) { - this._web3Wrapper = web3Wrapper; + constructor(provider: Provider, networkId: number, config?: OrderWatcherConfig) { + this._web3Wrapper = new Web3Wrapper(provider); + const artifactJSONs = _.values(artifacts); + const abiArrays = _.map(artifactJSONs, artifact => artifact.abi); + _.forEach(abiArrays, abi => { + this._web3Wrapper.abiDecoder.addABI(abi); + }); + this._contractWrappers = new ContractWrappers(provider, { networkId }); const pollingIntervalIfExistsMs = _.isUndefined(config) ? undefined : config.eventPollingIntervalMs; const stateLayer = _.isUndefined(config) || _.isUndefined(config.stateLayer) ? BlockParamLiteral.Latest : config.stateLayer; - this._eventWatcher = new EventWatcher(web3Wrapper, pollingIntervalIfExistsMs, stateLayer); - this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(token, stateLayer); - this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore(exchange, stateLayer); + this._eventWatcher = new EventWatcher(this._web3Wrapper, pollingIntervalIfExistsMs, stateLayer); + this._balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( + this._contractWrappers.token, + stateLayer, + ); + this._orderFilledCancelledLazyStore = new OrderFilledCancelledLazyStore( + this._contractWrappers.exchange, + stateLayer, + ); this._orderStateUtils = new OrderStateUtils( this._balanceAndProxyAllowanceLazyStore, this._orderFilledCancelledLazyStore, @@ -106,13 +120,13 @@ export class OrderStateWatcher { : config.cleanupJobIntervalMs; } /** - * Add an order to the orderStateWatcher. Before the order is added, it's + * Add an order to the orderWatcher. Before the order is added, it's * signature is verified. * @param signedOrder The order you wish to start watching. */ public addOrder(signedOrder: SignedOrder): void { assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); + const orderHash = getOrderHashHex(signedOrder); assert.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker); this._orderByOrderHash[orderHash] = signedOrder; this._addToDependentOrderHashes(signedOrder, orderHash); @@ -120,7 +134,7 @@ export class OrderStateWatcher { this._expirationWatcher.addOrder(orderHash, expirationUnixTimestampMs); } /** - * Removes an order from the orderStateWatcher + * Removes an order from the orderWatcher * @param orderHash The orderHash of the order you wish to stop watching. */ public removeOrder(orderHash: string): void { @@ -131,8 +145,7 @@ export class OrderStateWatcher { } delete this._orderByOrderHash[orderHash]; delete this._orderStateByOrderHashCache[orderHash]; - const exchange = (this._orderFilledCancelledLazyStore as any)._exchangeWrapper as ExchangeWrapper; - const zrxTokenAddress = exchange.getZRXTokenAddress(); + const zrxTokenAddress = this._orderFilledCancelledLazyStore.getZRXTokenAddress(); this._removeFromDependentOrderHashes(signedOrder.maker, zrxTokenAddress, orderHash); if (zrxTokenAddress !== signedOrder.makerTokenAddress) { @@ -142,7 +155,7 @@ export class OrderStateWatcher { this._expirationWatcher.removeOrder(orderHash); } /** - * Starts an orderStateWatcher subscription. The callback will be called every time a watched order's + * Starts an orderWatcher subscription. The callback will be called every time a watched order's * backing blockchain state has changed. This is a call-to-action for the caller to re-validate the order. * @param callback Receives the orderHash of the order that should be re-validated, together * with all the order-relevant blockchain state needed to re-validate the order. @@ -150,7 +163,7 @@ export class OrderStateWatcher { public subscribe(callback: OnOrderStateChangeCallback): void { assert.isFunction('callback', callback); if (!_.isUndefined(this._callbackIfExists)) { - throw new Error(ZeroExError.SubscriptionAlreadyPresent); + throw new Error(OrderWatcherError.SubscriptionAlreadyPresent); } this._callbackIfExists = callback; this._eventWatcher.subscribe(this._onEventWatcherCallbackAsync.bind(this)); @@ -165,11 +178,11 @@ export class OrderStateWatcher { ); } /** - * Ends an orderStateWatcher subscription. + * Ends an orderWatcher subscription. */ public unsubscribe(): void { if (_.isUndefined(this._callbackIfExists) || _.isUndefined(this._cleanupJobIntervalIdIfExists)) { - throw new Error(ZeroExError.SubscriptionNotFound); + throw new Error(OrderWatcherError.SubscriptionNotFound); } this._balanceAndProxyAllowanceLazyStore.deleteAll(); this._orderFilledCancelledLazyStore.deleteAll(); @@ -218,7 +231,7 @@ export class OrderStateWatcher { } } } - private async _onEventWatcherCallbackAsync(err: Error | null, logIfExists?: LogEvent): Promise<void> { + private async _onEventWatcherCallbackAsync(err: Error | null, logIfExists?: LogEntryEvent): Promise<void> { if (!_.isNull(err)) { if (!_.isUndefined(this._callbackIfExists)) { this._callbackIfExists(err); @@ -226,7 +239,7 @@ export class OrderStateWatcher { } return; } - const log = logIfExists as LogEvent; // At this moment we are sure that no error occured and log is defined. + const log = logIfExists as LogEntryEvent; // At this moment we are sure that no error occured and log is defined. const maybeDecodedLog = this._web3Wrapper.abiDecoder.tryToDecodeLogOrNoop<ContractEventArgs>(log); const isLogDecoded = !_.isUndefined(((maybeDecodedLog as any) as LogWithDecodedArgs<ContractEventArgs>).event); if (!isLogDecoded) { @@ -374,8 +387,7 @@ export class OrderStateWatcher { } } private _getZRXTokenAddress(): string { - const exchange = (this._orderFilledCancelledLazyStore as any)._exchangeWrapper as ExchangeWrapper; - const zrxTokenAddress = exchange.getZRXTokenAddress(); + const zrxTokenAddress = this._orderFilledCancelledLazyStore.getZRXTokenAddress(); return zrxTokenAddress; } } diff --git a/packages/order-watcher/src/types.ts b/packages/order-watcher/src/types.ts new file mode 100644 index 000000000..9125af236 --- /dev/null +++ b/packages/order-watcher/src/types.ts @@ -0,0 +1,46 @@ +import { BigNumber } from '@0xproject/utils'; + +import { + BlockParam, + BlockParamLiteral, + ContractAbi, + ContractEventArg, + ExchangeContractErrs, + FilterObject, + LogEntryEvent, + LogWithDecodedArgs, + Order, + OrderState, + SignedOrder, +} from '@0xproject/types'; + +export enum OrderWatcherError { + SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT', + SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND', +} + +export type EventWatcherCallback = (err: null | Error, log?: LogEntryEvent) => void; + +/** + * orderExpirationCheckingIntervalMs: How often to check for expired orders. Default=50. + * eventPollingIntervalMs: How often to poll the Ethereum node for new events. Default=200. + * expirationMarginMs: Amount of time before order expiry that you'd like to be notified + * of an orders expiration. Default=0. + * cleanupJobIntervalMs: How often to run a cleanup job which revalidates all the orders. Default=1hr. + * stateLayer: Optional blockchain state layer OrderWatcher will monitor for new events. Default=latest. + */ +export interface OrderWatcherConfig { + orderExpirationCheckingIntervalMs?: number; + eventPollingIntervalMs?: number; + expirationMarginMs?: number; + cleanupJobIntervalMs?: number; + stateLayer: BlockParamLiteral; +} + +export type OnOrderStateChangeCallback = (err: Error | null, orderState?: OrderState) => void; + +export enum InternalOrderWatcherError { + NoAbiDecoder = 'NO_ABI_DECODER', + ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY', + WethNotInTokenRegistry = 'WETH_NOT_IN_TOKEN_REGISTRY', +} diff --git a/packages/order-watcher/src/utils/assert.ts b/packages/order-watcher/src/utils/assert.ts new file mode 100644 index 000000000..f96bcebc1 --- /dev/null +++ b/packages/order-watcher/src/utils/assert.ts @@ -0,0 +1,19 @@ +import { assert as sharedAssert } from '@0xproject/assert'; +// 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 } from '@0xproject/json-schemas'; +// tslint:disable-next-line:no-unused-variable +import { ECSignature } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as _ from 'lodash'; + +import { isValidSignature } from '@0xproject/order-utils'; + +export const assert = { + ...sharedAssert, + isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string) { + const isValid = isValidSignature(orderHash, ecSignature, signerAddress); + this.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`); + }, +}; diff --git a/packages/order-watcher/src/utils/utils.ts b/packages/order-watcher/src/utils/utils.ts new file mode 100644 index 000000000..af1125632 --- /dev/null +++ b/packages/order-watcher/src/utils/utils.ts @@ -0,0 +1,13 @@ +import { BigNumber } from '@0xproject/utils'; + +export const utils = { + spawnSwitchErr(name: string, value: any): Error { + return new Error(`Unexpected switch value: ${value} encountered for ${name}`); + }, + getCurrentUnixTimestampSec(): BigNumber { + return new BigNumber(Date.now() / 1000).round(); + }, + getCurrentUnixTimestampMs(): BigNumber { + return new BigNumber(Date.now()); + }, +}; diff --git a/packages/0x.js/test/event_watcher_test.ts b/packages/order-watcher/test/event_watcher_test.ts index 40ffcc2f6..b4eca315e 100644 --- a/packages/0x.js/test/event_watcher_test.ts +++ b/packages/order-watcher/test/event_watcher_test.ts @@ -1,17 +1,14 @@ -import { web3Factory } from '@0xproject/dev-utils'; -import { LogEntry } from '@0xproject/types'; +import { callbackErrorReporter, web3Factory } from '@0xproject/dev-utils'; +import { DoneCallback, LogEntry, LogEntryEvent } from '@0xproject/types'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; import * as Sinon from 'sinon'; -import { LogEvent } from '../src'; import { EventWatcher } from '../src/order_watcher/event_watcher'; -import { DoneCallback } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; -import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { provider } from './utils/web3_wrapper'; chaiSetup.configure(); @@ -78,13 +75,15 @@ describe('EventWatcher', () => { getLogsStub.onCall(0).returns(logs); stubs.push(getLogsStub); const expectedToBeCalledOnce = false; - const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => { - const expectedLogEvent = expectedLogEvents.shift(); - expect(event).to.be.deep.equal(expectedLogEvent); - if (_.isEmpty(expectedLogEvents)) { - done(); - } - }); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done, expectedToBeCalledOnce)( + (event: LogEntryEvent) => { + const expectedLogEvent = expectedLogEvents.shift(); + expect(event).to.be.deep.equal(expectedLogEvent); + if (_.isEmpty(expectedLogEvents)) { + done(); + } + }, + ); eventWatcher.subscribe(callback); }); it('correctly computes the difference and emits only changes', (done: DoneCallback) => { @@ -113,13 +112,15 @@ describe('EventWatcher', () => { getLogsStub.onCall(1).returns(changedLogs); stubs.push(getLogsStub); const expectedToBeCalledOnce = false; - const callback = reportNodeCallbackErrors(done, expectedToBeCalledOnce)((event: LogEvent) => { - const expectedLogEvent = expectedLogEvents.shift(); - expect(event).to.be.deep.equal(expectedLogEvent); - if (_.isEmpty(expectedLogEvents)) { - done(); - } - }); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done, expectedToBeCalledOnce)( + (event: LogEntryEvent) => { + const expectedLogEvent = expectedLogEvents.shift(); + expect(event).to.be.deep.equal(expectedLogEvent); + if (_.isEmpty(expectedLogEvents)) { + done(); + } + }, + ); eventWatcher.subscribe(callback); }); }); diff --git a/packages/0x.js/test/expiration_watcher_test.ts b/packages/order-watcher/test/expiration_watcher_test.ts index 1b022539a..0a2524d78 100644 --- a/packages/0x.js/test/expiration_watcher_test.ts +++ b/packages/order-watcher/test/expiration_watcher_test.ts @@ -1,19 +1,20 @@ -import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; +import { ContractWrappers } from '@0xproject/contract-wrappers'; +import { BlockchainLifecycle, callbackErrorReporter, devConstants } from '@0xproject/dev-utils'; +import { FillScenarios } from '@0xproject/fill-scenarios'; +import { getOrderHashHex } from '@0xproject/order-utils'; +import { DoneCallback, Token } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import * as _ from 'lodash'; import 'mocha'; import * as Sinon from 'sinon'; -import { ZeroEx } from '../src/0x'; +import { artifacts } from '../src/artifacts'; import { ExpirationWatcher } from '../src/order_watcher/expiration_watcher'; -import { DoneCallback, Token } from '../src/types'; import { utils } from '../src/utils/utils'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { FillScenarios } from './utils/fill_scenarios'; -import { reportNoErrorCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -22,7 +23,7 @@ const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); describe('ExpirationWatcher', () => { - let zeroEx: ZeroEx; + let contractWrappers: ContractWrappers; let tokenUtils: TokenUtils; let tokens: Token[]; let userAddresses: string[]; @@ -43,15 +44,15 @@ describe('ExpirationWatcher', () => { const config = { networkId: constants.TESTRPC_NETWORK_ID, }; - zeroEx = new ZeroEx(provider, config); - exchangeContractAddress = zeroEx.exchange.getContractAddress(); - userAddresses = await zeroEx.getAvailableAddressesAsync(); - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + contractWrappers = new ContractWrappers(provider, config); + exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); tokenUtils = new TokenUtils(tokens); zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address; - fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress); + fillScenarios = new FillScenarios(provider, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress); [coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses; - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); const [makerToken, takerToken] = tokenUtils.getDummyTokens(); makerTokenAddress = makerToken.address; takerTokenAddress = takerToken.address; @@ -81,9 +82,9 @@ describe('ExpirationWatcher', () => { fillableAmount, expirationUnixTimestampSec, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); + const orderHash = getOrderHashHex(signedOrder); expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000)); - const callbackAsync = reportNoErrorCallbackErrors(done)((hash: string) => { + const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done)((hash: string) => { expect(hash).to.be.equal(orderHash); expect(utils.getCurrentUnixTimestampSec()).to.be.bignumber.gte(expirationUnixTimestampSec); }); @@ -103,9 +104,9 @@ describe('ExpirationWatcher', () => { fillableAmount, expirationUnixTimestampSec, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); + const orderHash = getOrderHashHex(signedOrder); expirationWatcher.addOrder(orderHash, signedOrder.expirationUnixTimestampSec.times(1000)); - const callbackAsync = reportNoErrorCallbackErrors(done)(async (hash: string) => { + const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done)(async (hash: string) => { done(new Error('Emitted expiration went before the order actually expired')); }); expirationWatcher.subscribe(callbackAsync); @@ -136,19 +137,21 @@ describe('ExpirationWatcher', () => { fillableAmount, order2ExpirationUnixTimestampSec, ); - const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1); - const orderHash2 = ZeroEx.getOrderHashHex(signedOrder2); + const orderHash1 = getOrderHashHex(signedOrder1); + const orderHash2 = getOrderHashHex(signedOrder2); expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000)); expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000)); const expirationOrder = [orderHash1, orderHash2]; const expectToBeCalledOnce = false; - const callbackAsync = reportNoErrorCallbackErrors(done, expectToBeCalledOnce)((hash: string) => { - const orderHash = expirationOrder.shift(); - expect(hash).to.be.equal(orderHash); - if (_.isEmpty(expirationOrder)) { - done(); - } - }); + const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done, expectToBeCalledOnce)( + (hash: string) => { + const orderHash = expirationOrder.shift(); + expect(hash).to.be.equal(orderHash); + if (_.isEmpty(expirationOrder)) { + done(); + } + }, + ); expirationWatcher.subscribe(callbackAsync); timer.tick(order2Lifetime * 1000); })().catch(done); @@ -175,19 +178,21 @@ describe('ExpirationWatcher', () => { fillableAmount, order2ExpirationUnixTimestampSec, ); - const orderHash1 = ZeroEx.getOrderHashHex(signedOrder1); - const orderHash2 = ZeroEx.getOrderHashHex(signedOrder2); + const orderHash1 = getOrderHashHex(signedOrder1); + const orderHash2 = getOrderHashHex(signedOrder2); expirationWatcher.addOrder(orderHash1, signedOrder1.expirationUnixTimestampSec.times(1000)); expirationWatcher.addOrder(orderHash2, signedOrder2.expirationUnixTimestampSec.times(1000)); const expirationOrder = orderHash1 < orderHash2 ? [orderHash1, orderHash2] : [orderHash2, orderHash1]; const expectToBeCalledOnce = false; - const callbackAsync = reportNoErrorCallbackErrors(done, expectToBeCalledOnce)((hash: string) => { - const orderHash = expirationOrder.shift(); - expect(hash).to.be.equal(orderHash); - if (_.isEmpty(expirationOrder)) { - done(); - } - }); + const callbackAsync = callbackErrorReporter.reportNoErrorCallbackErrors(done, expectToBeCalledOnce)( + (hash: string) => { + const orderHash = expirationOrder.shift(); + expect(hash).to.be.equal(orderHash); + if (_.isEmpty(expirationOrder)) { + done(); + } + }, + ); expirationWatcher.subscribe(callbackAsync); timer.tick(order2Lifetime * 1000); })().catch(done); diff --git a/packages/order-watcher/test/global_hooks.ts b/packages/order-watcher/test/global_hooks.ts new file mode 100644 index 000000000..e3c986524 --- /dev/null +++ b/packages/order-watcher/test/global_hooks.ts @@ -0,0 +1,7 @@ +import { runMigrationsAsync } from '@0xproject/migrations'; + +import { deployer } from './utils/deployer'; + +before('migrate contracts', async () => { + await runMigrationsAsync(deployer); +}); diff --git a/packages/0x.js/test/order_state_watcher_test.ts b/packages/order-watcher/test/order_watcher_test.ts index 45a292c8b..8c9249f58 100644 --- a/packages/0x.js/test/order_state_watcher_test.ts +++ b/packages/order-watcher/test/order_watcher_test.ts @@ -1,26 +1,27 @@ -import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; -import { BigNumber } from '@0xproject/utils'; -import * as chai from 'chai'; -import * as _ from 'lodash'; -import 'mocha'; - +import { ContractWrappers } from '@0xproject/contract-wrappers'; +import { BlockchainLifecycle, callbackErrorReporter, devConstants } from '@0xproject/dev-utils'; +import { FillScenarios } from '@0xproject/fill-scenarios'; +import { getOrderHashHex } from '@0xproject/order-utils'; import { + DoneCallback, ExchangeContractErrs, OrderState, OrderStateInvalid, OrderStateValid, SignedOrder, Token, - ZeroEx, - ZeroExError, -} from '../src'; -import { OrderStateWatcher } from '../src/order_watcher/order_state_watcher'; -import { DoneCallback } from '../src/types'; +} from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as chai from 'chai'; +import * as _ from 'lodash'; +import 'mocha'; + +import { OrderWatcher } from '../src/order_watcher/order_watcher'; +import { OrderWatcherError } from '../src/types'; import { chaiSetup } from './utils/chai_setup'; import { constants } from './utils/constants'; -import { FillScenarios } from './utils/fill_scenarios'; -import { reportNodeCallbackErrors } from './utils/report_callback_errors'; import { TokenUtils } from './utils/token_utils'; import { provider, web3Wrapper } from './utils/web3_wrapper'; @@ -30,8 +31,8 @@ chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -describe('OrderStateWatcher', () => { - let zeroEx: ZeroEx; +describe('OrderWatcher', () => { + let contractWrappers: ContractWrappers; let tokens: Token[]; let tokenUtils: TokenUtils; let fillScenarios: FillScenarios; @@ -43,22 +44,23 @@ describe('OrderStateWatcher', () => { let maker: string; let taker: string; let signedOrder: SignedOrder; - let orderStateWatcher: OrderStateWatcher; + let orderWatcher: OrderWatcher; const config = { networkId: constants.TESTRPC_NETWORK_ID, }; const decimals = constants.ZRX_DECIMALS; - const fillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals); + const fillableAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals); before(async () => { - zeroEx = new ZeroEx(provider, config); - orderStateWatcher = zeroEx.createOrderStateWatcher(); - exchangeContractAddress = zeroEx.exchange.getContractAddress(); - userAddresses = await zeroEx.getAvailableAddressesAsync(); + contractWrappers = new ContractWrappers(provider, config); + const networkId = await web3Wrapper.getNetworkIdAsync(); + orderWatcher = new OrderWatcher(provider, constants.TESTRPC_NETWORK_ID); + exchangeContractAddress = contractWrappers.exchange.getContractAddress(); + userAddresses = await web3Wrapper.getAvailableAddressesAsync(); [, maker, taker] = userAddresses; - tokens = await zeroEx.tokenRegistry.getTokensAsync(); + tokens = await contractWrappers.tokenRegistry.getTokensAsync(); tokenUtils = new TokenUtils(tokens); zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address; - fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress); + fillScenarios = new FillScenarios(provider, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress); await fillScenarios.initTokenBalancesAsync(); [makerToken, takerToken] = tokenUtils.getDummyTokens(); }); @@ -77,18 +79,18 @@ describe('OrderStateWatcher', () => { taker, fillableAmount, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); - expect((orderStateWatcher as any)._orderByOrderHash).to.include({ + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); + expect((orderWatcher as any)._orderByOrderHash).to.include({ [orderHash]: signedOrder, }); - let dependentOrderHashes = (orderStateWatcher as any)._dependentOrderHashes; + let dependentOrderHashes = (orderWatcher as any)._dependentOrderHashes; expect(dependentOrderHashes[signedOrder.maker][signedOrder.makerTokenAddress]).to.have.keys(orderHash); - orderStateWatcher.removeOrder(orderHash); - expect((orderStateWatcher as any)._orderByOrderHash).to.not.include({ + orderWatcher.removeOrder(orderHash); + expect((orderWatcher as any)._orderByOrderHash).to.not.include({ [orderHash]: signedOrder, }); - dependentOrderHashes = (orderStateWatcher as any)._dependentOrderHashes; + dependentOrderHashes = (orderWatcher as any)._dependentOrderHashes; expect(dependentOrderHashes[signedOrder.maker]).to.be.undefined(); }); it('should no-op when removing a non-existing order', async () => { @@ -99,29 +101,29 @@ describe('OrderStateWatcher', () => { taker, fillableAmount, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); + const orderHash = getOrderHashHex(signedOrder); const nonExistentOrderHash = `0x${orderHash .substr(2) .split('') .reverse() .join('')}`; - orderStateWatcher.removeOrder(nonExistentOrderHash); + orderWatcher.removeOrder(nonExistentOrderHash); }); }); describe('#subscribe', async () => { afterEach(async () => { - orderStateWatcher.unsubscribe(); + orderWatcher.unsubscribe(); }); it('should fail when trying to subscribe twice', async () => { - orderStateWatcher.subscribe(_.noop); - expect(() => orderStateWatcher.subscribe(_.noop)).to.throw(ZeroExError.SubscriptionAlreadyPresent); + orderWatcher.subscribe(_.noop); + expect(() => orderWatcher.subscribe(_.noop)).to.throw(OrderWatcherError.SubscriptionAlreadyPresent); }); }); describe('tests with cleanup', async () => { afterEach(async () => { - orderStateWatcher.unsubscribe(); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.removeOrder(orderHash); + orderWatcher.unsubscribe(); + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.removeOrder(orderHash); }); it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => { (async () => { @@ -132,16 +134,16 @@ describe('OrderStateWatcher', () => { taker, fillableAmount, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.false(); const invalidOrderState = orderState as OrderStateInvalid; expect(invalidOrderState.orderHash).to.be.equal(orderHash); expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance); }); - orderStateWatcher.subscribe(callback); - await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0)); + orderWatcher.subscribe(callback); + await contractWrappers.token.setProxyAllowanceAsync(makerToken.address, maker, new BigNumber(0)); })().catch(done); }); it('should not emit an orderState event when irrelevant Transfer event received', (done: DoneCallback) => { @@ -153,15 +155,20 @@ describe('OrderStateWatcher', () => { taker, fillableAmount, ); - orderStateWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + orderWatcher.addOrder(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { throw new Error('OrderState callback fired for irrelevant order'); }); - orderStateWatcher.subscribe(callback); + orderWatcher.subscribe(callback); const notTheMaker = userAddresses[0]; const anyRecipient = taker; const transferAmount = new BigNumber(2); - await zeroEx.token.transferAsync(makerToken.address, notTheMaker, anyRecipient, transferAmount); + await contractWrappers.token.transferAsync( + makerToken.address, + notTheMaker, + anyRecipient, + transferAmount, + ); setTimeout(() => { done(); }, TIMEOUT_MS); @@ -176,18 +183,18 @@ describe('OrderStateWatcher', () => { taker, fillableAmount, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.false(); const invalidOrderState = orderState as OrderStateInvalid; expect(invalidOrderState.orderHash).to.be.equal(orderHash); expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance); }); - orderStateWatcher.subscribe(callback); + orderWatcher.subscribe(callback); const anyRecipient = taker; - const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker); - await zeroEx.token.transferAsync(makerToken.address, maker, anyRecipient, makerBalance); + const makerBalance = await contractWrappers.token.getBalanceAsync(makerToken.address, maker); + await contractWrappers.token.transferAsync(makerToken.address, maker, anyRecipient, makerBalance); })().catch(done); }); it('should emit orderStateInvalid when watched order fully filled', (done: DoneCallback) => { @@ -199,19 +206,19 @@ describe('OrderStateWatcher', () => { taker, fillableAmount, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.false(); const invalidOrderState = orderState as OrderStateInvalid; expect(invalidOrderState.orderHash).to.be.equal(orderHash); expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero); }); - orderStateWatcher.subscribe(callback); + orderWatcher.subscribe(callback); const shouldThrowOnInsufficientBalanceOrAllowance = true; - await zeroEx.exchange.fillOrderAsync( + await contractWrappers.exchange.fillOrderAsync( signedOrder, fillableAmount, shouldThrowOnInsufficientBalanceOrAllowance, @@ -229,12 +236,12 @@ describe('OrderStateWatcher', () => { fillableAmount, ); - const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker); + const makerBalance = await contractWrappers.token.getBalanceAsync(makerToken.address, maker); const fillAmountInBaseUnits = new BigNumber(2); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.true(); const validOrderState = orderState as OrderStateValid; expect(validOrderState.orderHash).to.be.equal(orderHash); @@ -249,9 +256,9 @@ describe('OrderStateWatcher', () => { ); expect(orderRelevantState.makerBalance).to.be.bignumber.equal(remainingMakerBalance); }); - orderStateWatcher.subscribe(callback); + orderWatcher.subscribe(callback); const shouldThrowOnInsufficientBalanceOrAllowance = true; - await zeroEx.exchange.fillOrderAsync( + await contractWrappers.exchange.fillOrderAsync( signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, @@ -261,8 +268,8 @@ describe('OrderStateWatcher', () => { }); it('should trigger the callback when orders backing ZRX allowance changes', (done: DoneCallback) => { (async () => { - const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), 18); - const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), 18); + const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18); + const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), 18); signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( makerToken.address, takerToken.address, @@ -273,17 +280,17 @@ describe('OrderStateWatcher', () => { fillableAmount, taker, ); - const callback = reportNodeCallbackErrors(done)(); - orderStateWatcher.addOrder(signedOrder); - orderStateWatcher.subscribe(callback); - await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0)); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)(); + orderWatcher.addOrder(signedOrder); + orderWatcher.subscribe(callback); + await contractWrappers.token.setProxyAllowanceAsync(zrxTokenAddress, maker, new BigNumber(0)); })().catch(done); }); describe('remainingFillable(M|T)akerTokenAmount', () => { it('should calculate correct remaining fillable', (done: DoneCallback) => { (async () => { - const takerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(10), decimals); - const makerFillableAmount = ZeroEx.toBaseUnitAmount(new BigNumber(20), decimals); + const takerFillableAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(10), decimals); + const makerFillableAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(20), decimals); signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync( makerToken.address, takerToken.address, @@ -292,24 +299,24 @@ describe('OrderStateWatcher', () => { makerFillableAmount, takerFillableAmount, ); - const fillAmountInBaseUnits = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const fillAmountInBaseUnits = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.true(); const validOrderState = orderState as OrderStateValid; expect(validOrderState.orderHash).to.be.equal(orderHash); const orderRelevantState = validOrderState.orderRelevantState; expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal( - ZeroEx.toBaseUnitAmount(new BigNumber(16), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(16), decimals), ); expect(orderRelevantState.remainingFillableTakerTokenAmount).to.be.bignumber.equal( - ZeroEx.toBaseUnitAmount(new BigNumber(8), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(8), decimals), ); }); - orderStateWatcher.subscribe(callback); + orderWatcher.subscribe(callback); const shouldThrowOnInsufficientBalanceOrAllowance = true; - await zeroEx.exchange.fillOrderAsync( + await contractWrappers.exchange.fillOrderAsync( signedOrder, fillAmountInBaseUnits, shouldThrowOnInsufficientBalanceOrAllowance, @@ -327,10 +334,10 @@ describe('OrderStateWatcher', () => { fillableAmount, ); - const changedMakerApprovalAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals); - orderStateWatcher.addOrder(signedOrder); + const changedMakerApprovalAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { const validOrderState = orderState as OrderStateValid; const orderRelevantState = validOrderState.orderRelevantState; expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal( @@ -340,8 +347,12 @@ describe('OrderStateWatcher', () => { changedMakerApprovalAmount, ); }); - orderStateWatcher.subscribe(callback); - await zeroEx.token.setProxyAllowanceAsync(makerToken.address, maker, changedMakerApprovalAmount); + orderWatcher.subscribe(callback); + await contractWrappers.token.setProxyAllowanceAsync( + makerToken.address, + maker, + changedMakerApprovalAmount, + ); })().catch(done); }); it('should equal balance amount when balance amount is lowest', (done: DoneCallback) => { @@ -354,13 +365,13 @@ describe('OrderStateWatcher', () => { fillableAmount, ); - const makerBalance = await zeroEx.token.getBalanceAsync(makerToken.address, maker); + const makerBalance = await contractWrappers.token.getBalanceAsync(makerToken.address, maker); - const remainingAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals); + const remainingAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); const transferAmount = makerBalance.sub(remainingAmount); - orderStateWatcher.addOrder(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.true(); const validOrderState = orderState as OrderStateValid; const orderRelevantState = validOrderState.orderRelevantState; @@ -371,14 +382,19 @@ describe('OrderStateWatcher', () => { remainingAmount, ); }); - orderStateWatcher.subscribe(callback); - await zeroEx.token.transferAsync(makerToken.address, maker, ZeroEx.NULL_ADDRESS, transferAmount); + orderWatcher.subscribe(callback); + await contractWrappers.token.transferAsync( + makerToken.address, + maker, + constants.NULL_ADDRESS, + transferAmount, + ); })().catch(done); }); it('should equal remaining amount when partially cancelled and order has fees', (done: DoneCallback) => { (async () => { - const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals); - const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals); + const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), decimals); + const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals); const feeRecipient = taker; signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( makerToken.address, @@ -391,11 +407,11 @@ describe('OrderStateWatcher', () => { feeRecipient, ); - const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals); + const remainingTokenAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(4), decimals); const transferTokenAmount = makerFee.sub(remainingTokenAmount); - orderStateWatcher.addOrder(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.true(); const validOrderState = orderState as OrderStateValid; const orderRelevantState = validOrderState.orderRelevantState; @@ -403,14 +419,14 @@ describe('OrderStateWatcher', () => { remainingTokenAmount, ); }); - orderStateWatcher.subscribe(callback); - await zeroEx.exchange.cancelOrderAsync(signedOrder, transferTokenAmount); + orderWatcher.subscribe(callback); + await contractWrappers.exchange.cancelOrderAsync(signedOrder, transferTokenAmount); })().catch(done); }); it('should equal ratio amount when fee balance is lowered', (done: DoneCallback) => { (async () => { - const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals); - const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals); + const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), decimals); + const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals); const feeRecipient = taker; signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( makerToken.address, @@ -423,33 +439,33 @@ describe('OrderStateWatcher', () => { feeRecipient, ); - const remainingFeeAmount = ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals); + const remainingFeeAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals); - const remainingTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(4), decimals); + const remainingTokenAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(4), decimals); const transferTokenAmount = makerFee.sub(remainingTokenAmount); - orderStateWatcher.addOrder(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { const validOrderState = orderState as OrderStateValid; const orderRelevantState = validOrderState.orderRelevantState; expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal( remainingFeeAmount, ); }); - orderStateWatcher.subscribe(callback); - await zeroEx.token.setProxyAllowanceAsync(zrxTokenAddress, maker, remainingFeeAmount); - await zeroEx.token.transferAsync( + orderWatcher.subscribe(callback); + await contractWrappers.token.setProxyAllowanceAsync(zrxTokenAddress, maker, remainingFeeAmount); + await contractWrappers.token.transferAsync( makerToken.address, maker, - ZeroEx.NULL_ADDRESS, + constants.NULL_ADDRESS, transferTokenAmount, ); })().catch(done); }); it('should calculate full amount when all available and non-divisible', (done: DoneCallback) => { (async () => { - const takerFee = ZeroEx.toBaseUnitAmount(new BigNumber(0), decimals); - const makerFee = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals); + const takerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(0), decimals); + const makerFee = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); const feeRecipient = taker; signedOrder = await fillScenarios.createFillableSignedOrderWithFeesAsync( makerToken.address, @@ -462,20 +478,20 @@ describe('OrderStateWatcher', () => { feeRecipient, ); - orderStateWatcher.addOrder(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { const validOrderState = orderState as OrderStateValid; const orderRelevantState = validOrderState.orderRelevantState; expect(orderRelevantState.remainingFillableMakerTokenAmount).to.be.bignumber.equal( fillableAmount, ); }); - orderStateWatcher.subscribe(callback); - await zeroEx.token.setProxyAllowanceAsync( + orderWatcher.subscribe(callback); + await contractWrappers.token.setProxyAllowanceAsync( makerToken.address, maker, - ZeroEx.toBaseUnitAmount(new BigNumber(100), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(100), decimals), ); })().catch(done); }); @@ -489,18 +505,18 @@ describe('OrderStateWatcher', () => { taker, fillableAmount, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.false(); const invalidOrderState = orderState as OrderStateInvalid; expect(invalidOrderState.orderHash).to.be.equal(orderHash); expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderRemainingFillAmountZero); }); - orderStateWatcher.subscribe(callback); + orderWatcher.subscribe(callback); - await zeroEx.exchange.cancelOrderAsync(signedOrder, fillableAmount); + await contractWrappers.exchange.cancelOrderAsync(signedOrder, fillableAmount); })().catch(done); }); it('should emit orderStateInvalid when within rounding error range', (done: DoneCallback) => { @@ -513,17 +529,17 @@ describe('OrderStateWatcher', () => { taker, fillableAmount, ); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.false(); const invalidOrderState = orderState as OrderStateInvalid; expect(invalidOrderState.orderHash).to.be.equal(orderHash); expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError); }); - orderStateWatcher.subscribe(callback); - await zeroEx.exchange.cancelOrderAsync( + orderWatcher.subscribe(callback); + await contractWrappers.exchange.cancelOrderAsync( signedOrder, fillableAmount.minus(remainingFillableAmountInBaseUnits), ); @@ -540,18 +556,18 @@ describe('OrderStateWatcher', () => { ); const cancelAmountInBaseUnits = new BigNumber(2); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - orderStateWatcher.addOrder(signedOrder); + const orderHash = getOrderHashHex(signedOrder); + orderWatcher.addOrder(signedOrder); - const callback = reportNodeCallbackErrors(done)((orderState: OrderState) => { + const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => { expect(orderState.isValid).to.be.true(); const validOrderState = orderState as OrderStateValid; expect(validOrderState.orderHash).to.be.equal(orderHash); const orderRelevantState = validOrderState.orderRelevantState; expect(orderRelevantState.cancelledTakerTokenAmount).to.be.bignumber.equal(cancelAmountInBaseUnits); }); - orderStateWatcher.subscribe(callback); - await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmountInBaseUnits); + orderWatcher.subscribe(callback); + await contractWrappers.exchange.cancelOrderAsync(signedOrder, cancelAmountInBaseUnits); })().catch(done); }); }); diff --git a/packages/0x.js/test/remaining_fillable_calculator_test.ts b/packages/order-watcher/test/remaining_fillable_calculator_test.ts index d97402ef6..7ec3f1ebc 100644 --- a/packages/0x.js/test/remaining_fillable_calculator_test.ts +++ b/packages/order-watcher/test/remaining_fillable_calculator_test.ts @@ -1,10 +1,10 @@ import { ECSignature, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; import 'mocha'; -import { ZeroEx } from '../src/0x'; -import { RemainingFillableCalculator } from '../src/order_watcher/remaining_fillable_calculator'; +import { RemainingFillableCalculator } from '@0xproject/order-utils'; import { chaiSetup } from './utils/chai_setup'; @@ -29,13 +29,13 @@ describe('RemainingFillableCalculator', () => { const signature: ECSignature = { v: 27, r: '', s: '' }; beforeEach(async () => { [makerAmount, takerAmount, makerFeeAmount] = [ - ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals), - ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals), - ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(50), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals), ]; [transferrableMakerTokenAmount, transferrableMakerFeeTokenAmount] = [ - ZeroEx.toBaseUnitAmount(new BigNumber(50), decimals), - ZeroEx.toBaseUnitAmount(new BigNumber(5), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(50), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals), ]; }); function buildSignedOrder(): SignedOrder { @@ -73,7 +73,7 @@ describe('RemainingFillableCalculator', () => { }); it('calculates the correct amount when partially filled and funds available', () => { signedOrder = buildSignedOrder(); - remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals); + remainingMakerTokenAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); calculator = new RemainingFillableCalculator( signedOrder, isMakerTokenZRX, @@ -98,7 +98,7 @@ describe('RemainingFillableCalculator', () => { }); it('calculates the correct amount when balance is less than remaining fillable', () => { signedOrder = buildSignedOrder(); - const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals); + const partiallyFilledAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount); transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount); calculator = new RemainingFillableCalculator( @@ -113,15 +113,15 @@ describe('RemainingFillableCalculator', () => { describe('Order to Fee Ratio is < 1', () => { beforeEach(async () => { [makerAmount, takerAmount, makerFeeAmount] = [ - ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals), - ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals), - ZeroEx.toBaseUnitAmount(new BigNumber(6), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(6), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(6), decimals), ]; }); it('calculates the correct amount when funds unavailable', () => { signedOrder = buildSignedOrder(); remainingMakerTokenAmount = signedOrder.makerTokenAmount; - const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals); + const transferredAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount); calculator = new RemainingFillableCalculator( signedOrder, @@ -136,15 +136,15 @@ describe('RemainingFillableCalculator', () => { describe('Ratio is not evenly divisble', () => { beforeEach(async () => { [makerAmount, takerAmount, makerFeeAmount] = [ - ZeroEx.toBaseUnitAmount(new BigNumber(3), decimals), - ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals), - ZeroEx.toBaseUnitAmount(new BigNumber(7), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(7), decimals), + Web3Wrapper.toBaseUnitAmount(new BigNumber(7), decimals), ]; }); it('calculates the correct amount when funds unavailable', () => { signedOrder = buildSignedOrder(); remainingMakerTokenAmount = signedOrder.makerTokenAmount; - const transferredAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals); + const transferredAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(transferredAmount); calculator = new RemainingFillableCalculator( signedOrder, @@ -182,7 +182,7 @@ describe('RemainingFillableCalculator', () => { }); it('calculates the correct amount when partially filled and funds available', () => { signedOrder = buildSignedOrder(); - remainingMakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(1), decimals); + remainingMakerTokenAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); calculator = new RemainingFillableCalculator( signedOrder, isMakerTokenZRX, @@ -208,7 +208,7 @@ describe('RemainingFillableCalculator', () => { }); it('calculates the correct amount when balance is less than remaining fillable', () => { signedOrder = buildSignedOrder(); - const partiallyFilledAmount = ZeroEx.toBaseUnitAmount(new BigNumber(2), decimals); + const partiallyFilledAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); remainingMakerTokenAmount = signedOrder.makerTokenAmount.minus(partiallyFilledAmount); transferrableMakerTokenAmount = remainingMakerTokenAmount.minus(partiallyFilledAmount); transferrableMakerFeeTokenAmount = transferrableMakerTokenAmount; diff --git a/packages/order-watcher/test/utils/chai_setup.ts b/packages/order-watcher/test/utils/chai_setup.ts new file mode 100644 index 000000000..078edd309 --- /dev/null +++ b/packages/order-watcher/test/utils/chai_setup.ts @@ -0,0 +1,13 @@ +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() { + chai.config.includeStack = true; + chai.use(ChaiBigNumber()); + chai.use(dirtyChai); + chai.use(chaiAsPromised); + }, +}; diff --git a/packages/order-watcher/test/utils/constants.ts b/packages/order-watcher/test/utils/constants.ts new file mode 100644 index 000000000..78037647c --- /dev/null +++ b/packages/order-watcher/test/utils/constants.ts @@ -0,0 +1,5 @@ +export const constants = { + NULL_ADDRESS: '0x0000000000000000000000000000000000000000', + TESTRPC_NETWORK_ID: 50, + ZRX_DECIMALS: 18, +}; diff --git a/packages/order-watcher/test/utils/deployer.ts b/packages/order-watcher/test/utils/deployer.ts new file mode 100644 index 000000000..b092322e2 --- /dev/null +++ b/packages/order-watcher/test/utils/deployer.ts @@ -0,0 +1,18 @@ +import { Deployer } from '@0xproject/deployer'; +import { devConstants } from '@0xproject/dev-utils'; +import * as path from 'path'; + +import { constants } from './constants'; + +import { provider } from './web3_wrapper'; + +const artifactsDir = path.resolve('test', 'artifacts'); +const deployerOpts = { + artifactsDir, + provider, + networkId: constants.TESTRPC_NETWORK_ID, + defaults: { + gas: devConstants.GAS_ESTIMATE, + }, +}; +export const deployer = new Deployer(deployerOpts); diff --git a/packages/order-watcher/test/utils/token_utils.ts b/packages/order-watcher/test/utils/token_utils.ts new file mode 100644 index 000000000..e1191b5bb --- /dev/null +++ b/packages/order-watcher/test/utils/token_utils.ts @@ -0,0 +1,34 @@ +import { Token } from '@0xproject/types'; +import * as _ from 'lodash'; + +import { InternalOrderWatcherError } from '../../src/types'; + +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(InternalOrderWatcherError.ZrxNotInTokenRegistry); + } + return zrxToken; + } + public getWethTokenOrThrow(): Token { + const wethToken = _.find(this._tokens, { symbol: WETH_TOKEN_SYMBOL }); + if (_.isUndefined(wethToken)) { + throw new Error(InternalOrderWatcherError.WethNotInTokenRegistry); + } + return wethToken; + } + public getDummyTokens(): Token[] { + const dummyTokens = _.filter(this._tokens, token => { + return !_.includes([PROTOCOL_TOKEN_SYMBOL, WETH_TOKEN_SYMBOL], token.symbol); + }); + return dummyTokens; + } +} diff --git a/packages/order-watcher/test/utils/web3_wrapper.ts b/packages/order-watcher/test/utils/web3_wrapper.ts new file mode 100644 index 000000000..b0ccfa546 --- /dev/null +++ b/packages/order-watcher/test/utils/web3_wrapper.ts @@ -0,0 +1,9 @@ +import { devConstants, web3Factory } from '@0xproject/dev-utils'; +import { Provider } from '@0xproject/types'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; + +const web3 = web3Factory.create({ shouldUseInProcessGanache: true }); +const provider: Provider = web3.currentProvider; +const web3Wrapper = new Web3Wrapper(web3.currentProvider); + +export { provider, web3Wrapper }; diff --git a/packages/order-watcher/tsconfig.json b/packages/order-watcher/tsconfig.json new file mode 100644 index 000000000..e35816553 --- /dev/null +++ b/packages/order-watcher/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["./src/**/*", "./test/**/*"] +} diff --git a/packages/order-watcher/tslint.json b/packages/order-watcher/tslint.json new file mode 100644 index 000000000..ffaefe83a --- /dev/null +++ b/packages/order-watcher/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": ["@0xproject/tslint-config"] +} diff --git a/packages/sol-cov/package.json b/packages/sol-cov/package.json index 425b561a6..536d05370 100644 --- a/packages/sol-cov/package.json +++ b/packages/sol-cov/package.json @@ -6,7 +6,7 @@ "types": "lib/src/index.d.ts", "scripts": { "build:watch": "tsc -w", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "test": "run-s clean build compile_test run_mocha", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json index 238c8417a..92377f118 100644 --- a/packages/subproviders/package.json +++ b/packages/subproviders/package.json @@ -8,7 +8,7 @@ "build:watch": "tsc -w", "clean": "shx rm -rf lib scripts", "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", - "lint": "tslint --project . 'src/**/*.ts' 'test/**/*.ts'", + "lint": "tslint --project .", "run_mocha_unit": "mocha lib/test/unit/**/*_test.js --timeout 10000 --bail --exit", "run_mocha_integration": "mocha lib/test/integration/**/*_test.js --timeout 10000 --bail --exit", "test": "npm run test:unit", diff --git a/packages/subproviders/test/integration/ledger_subprovider_test.ts b/packages/subproviders/test/integration/ledger_subprovider_test.ts index 0d6e67bd1..f1c634a77 100644 --- a/packages/subproviders/test/integration/ledger_subprovider_test.ts +++ b/packages/subproviders/test/integration/ledger_subprovider_test.ts @@ -1,4 +1,4 @@ -import { JSONRPCResponsePayload } from '@0xproject/types'; +import { DoneCallback, JSONRPCResponsePayload } from '@0xproject/types'; import { promisify } from '@0xproject/utils'; import Eth from '@ledgerhq/hw-app-eth'; // HACK: This dependency is optional and tslint skips optional dependencies @@ -12,7 +12,7 @@ import Web3ProviderEngine = require('web3-provider-engine'); import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import { LedgerSubprovider } from '../../src'; -import { DoneCallback, LedgerEthereumClient } from '../../src/types'; +import { LedgerEthereumClient } from '../../src/types'; import { chaiSetup } from '../chai_setup'; import { fixtureData } from '../utils/fixture_data'; import { reportCallbackErrors } from '../utils/report_callback_errors'; diff --git a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts index e25cb7eb7..9115186f4 100644 --- a/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts +++ b/packages/subproviders/test/unit/redundant_rpc_subprovider_test.ts @@ -1,4 +1,4 @@ -import { JSONRPCResponsePayload } from '@0xproject/types'; +import { DoneCallback, JSONRPCResponsePayload } from '@0xproject/types'; import * as chai from 'chai'; import * as _ from 'lodash'; import Web3 = require('web3'); @@ -7,7 +7,6 @@ import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import { RedundantSubprovider } from '../../src'; import { Subprovider } from '../../src/subproviders/subprovider'; -import { DoneCallback } from '../../src/types'; import { chaiSetup } from '../chai_setup'; import { ganacheSubprovider } from '../utils/ganache_subprovider'; import { reportCallbackErrors } from '../utils/report_callback_errors'; diff --git a/packages/subproviders/test/utils/report_callback_errors.ts b/packages/subproviders/test/utils/report_callback_errors.ts index 8a8f4d966..eaefea7c3 100644 --- a/packages/subproviders/test/utils/report_callback_errors.ts +++ b/packages/subproviders/test/utils/report_callback_errors.ts @@ -1,4 +1,4 @@ -import { DoneCallback } from '../../src/types'; +import { DoneCallback } from '@0xproject/types'; export const reportCallbackErrors = (done: DoneCallback) => { return (f: (...args: any[]) => void) => { diff --git a/packages/testnet-faucets/package.json b/packages/testnet-faucets/package.json index 481770310..198c0b2f7 100644 --- a/packages/testnet-faucets/package.json +++ b/packages/testnet-faucets/package.json @@ -9,7 +9,7 @@ "build": "node ../../node_modules/gulp/bin/gulp.js build", "dev": "node ../../node_modules/gulp/bin/gulp.js run", "start": "node ./bin/server.js", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "clean": "shx rm -rf bin" }, "author": "Fabio Berger", diff --git a/packages/types/CHANGELOG.json b/packages/types/CHANGELOG.json index 241acbf9c..afcfd862c 100644 --- a/packages/types/CHANGELOG.json +++ b/packages/types/CHANGELOG.json @@ -1,5 +1,15 @@ [ { + "version": "0.7.0", + "changes": [ + { + "note": + "Moved ExchangeContractErrs, DoneCallback, Token, OrderRelevantState, OrderStateValid, OrderStateInvalid, OrderState, OrderAddresses and OrderValues types from 0x.js", + "pr": 579 + } + ] + }, + { "timestamp": 1525477860, "version": "0.6.3", "changes": [ diff --git a/packages/types/package.json b/packages/types/package.json index 0971f424e..973d5b8d0 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -8,7 +8,7 @@ "build:watch": "tsc -w", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib scripts", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "manual:postpublish": "yarn build; node ./scripts/postpublish.js" }, "license": "Apache-2.0", diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 044aae3c8..a85d48cf7 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -292,3 +292,81 @@ export interface ECSignature { r: string; s: string; } + +/** + * Errors originating from the 0x exchange contract + */ +export enum ExchangeContractErrs { + OrderFillExpired = 'ORDER_FILL_EXPIRED', + OrderCancelExpired = 'ORDER_CANCEL_EXPIRED', + OrderCancelAmountZero = 'ORDER_CANCEL_AMOUNT_ZERO', + OrderAlreadyCancelledOrFilled = 'ORDER_ALREADY_CANCELLED_OR_FILLED', + OrderFillAmountZero = 'ORDER_FILL_AMOUNT_ZERO', + OrderRemainingFillAmountZero = 'ORDER_REMAINING_FILL_AMOUNT_ZERO', + OrderFillRoundingError = 'ORDER_FILL_ROUNDING_ERROR', + FillBalanceAllowanceError = 'FILL_BALANCE_ALLOWANCE_ERROR', + InsufficientTakerBalance = 'INSUFFICIENT_TAKER_BALANCE', + InsufficientTakerAllowance = 'INSUFFICIENT_TAKER_ALLOWANCE', + InsufficientMakerBalance = 'INSUFFICIENT_MAKER_BALANCE', + InsufficientMakerAllowance = 'INSUFFICIENT_MAKER_ALLOWANCE', + InsufficientTakerFeeBalance = 'INSUFFICIENT_TAKER_FEE_BALANCE', + InsufficientTakerFeeAllowance = 'INSUFFICIENT_TAKER_FEE_ALLOWANCE', + InsufficientMakerFeeBalance = 'INSUFFICIENT_MAKER_FEE_BALANCE', + InsufficientMakerFeeAllowance = 'INSUFFICIENT_MAKER_FEE_ALLOWANCE', + TransactionSenderIsNotFillOrderTaker = 'TRANSACTION_SENDER_IS_NOT_FILL_ORDER_TAKER', + MultipleMakersInSingleCancelBatchDisallowed = 'MULTIPLE_MAKERS_IN_SINGLE_CANCEL_BATCH_DISALLOWED', + InsufficientRemainingFillAmount = 'INSUFFICIENT_REMAINING_FILL_AMOUNT', + MultipleTakerTokensInFillUpToDisallowed = 'MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED', + BatchOrdersMustHaveSameExchangeAddress = 'BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS', + BatchOrdersMustHaveAtLeastOneItem = 'BATCH_ORDERS_MUST_HAVE_AT_LEAST_ONE_ITEM', +} + +export type ArtifactContractName = 'ZRX' | 'TokenTransferProxy' | 'TokenRegistry' | 'Token' | 'Exchange' | 'EtherToken'; + +export interface Artifact { + contract_name: ArtifactContractName; + abi: ContractAbi; + networks: { + [networkId: number]: { + address: string; + }; + }; +} + +export type OrderAddresses = [string, string, string, string, string]; + +export type OrderValues = [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber, BigNumber]; + +export type DoneCallback = (err?: Error) => void; + +export interface OrderRelevantState { + makerBalance: BigNumber; + makerProxyAllowance: BigNumber; + makerFeeBalance: BigNumber; + makerFeeProxyAllowance: BigNumber; + filledTakerTokenAmount: BigNumber; + cancelledTakerTokenAmount: BigNumber; + remainingFillableMakerTokenAmount: BigNumber; + remainingFillableTakerTokenAmount: BigNumber; +} + +export interface OrderStateValid { + isValid: true; + orderHash: string; + orderRelevantState: OrderRelevantState; +} + +export interface OrderStateInvalid { + isValid: false; + orderHash: string; + error: ExchangeContractErrs; +} + +export type OrderState = OrderStateValid | OrderStateInvalid; + +export interface Token { + name: string; + address: string; + symbol: string; + decimals: number; +} diff --git a/packages/utils/package.json b/packages/utils/package.json index 496ea1fb0..0924aefc3 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -8,7 +8,7 @@ "build:watch": "tsc -w", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib scripts", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "manual:postpublish": "yarn build; node ./scripts/postpublish.js" }, "license": "Apache-2.0", diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json index 3ee9631cc..bc38df00d 100644 --- a/packages/web3-wrapper/package.json +++ b/packages/web3-wrapper/package.json @@ -8,7 +8,7 @@ "build:watch": "tsc -w", "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "clean": "shx rm -rf lib scripts", - "lint": "tslint --project . 'src/**/*.ts'", + "lint": "tslint --project .", "test": "run-s clean build run_mocha", "test:circleci": "yarn test:coverage", "run_mocha": "mocha lib/test/**/*_test.js --bail --exit", diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts index 5e6ff3239..49fddb27b 100644 --- a/packages/web3-wrapper/src/web3_wrapper.ts +++ b/packages/web3-wrapper/src/web3_wrapper.ts @@ -324,6 +324,13 @@ export class Web3Wrapper { const txHash = await promisify<string>(this._web3.eth.sendTransaction)(txData); return txHash; } + /** + * 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 = 1000, diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts index 40853cb9e..f68e2335f 100644 --- a/packages/website/ts/containers/zero_ex_js_documentation.ts +++ b/packages/website/ts/containers/zero_ex_js_documentation.ts @@ -68,32 +68,38 @@ const docsInfoConfig: DocsInfoConfig = { [zeroExJsDocSections.exchange]: [ '"0x.js/src/contract_wrappers/exchange_wrapper"', '"src/contract_wrappers/exchange_wrapper"', + '"contract-wrappers/src/contract_wrappers/exchange_wrapper"', ], [zeroExJsDocSections.tokenRegistry]: [ '"0x.js/src/contract_wrappers/token_registry_wrapper"', '"src/contract_wrappers/token_registry_wrapper"', + '"contract-wrappers/src/contract_wrappers/token_registry_wrapper"', ], [zeroExJsDocSections.token]: [ '"0x.js/src/contract_wrappers/token_wrapper"', '"src/contract_wrappers/token_wrapper"', + '"contract-wrappers/src/contract_wrappers/token_wrapper"', ], [zeroExJsDocSections.etherToken]: [ '"0x.js/src/contract_wrappers/ether_token_wrapper"', '"src/contract_wrappers/ether_token_wrapper"', + '"contract-wrappers/src/contract_wrappers/ether_token_wrapper"', ], [zeroExJsDocSections.proxy]: [ '"0x.js/src/contract_wrappers/proxy_wrapper"', '"0x.js/src/contract_wrappers/token_transfer_proxy_wrapper"', - '"src/contract_wrappers/token_transfer_proxy_wrapper"', + '"contract-wrappers/src/contract_wrappers/token_transfer_proxy_wrapper"', ], [zeroExJsDocSections.orderWatcher]: [ '"0x.js/src/order_watcher/order_state_watcher"', '"src/order_watcher/order_state_watcher"', + '"order-watcher/src/order_watcher/order_watcher"', ], [zeroExJsDocSections.types]: [ '"0x.js/src/types"', '"src/types"', '"types/src/index"', + '"contract-wrappers/src/types"', '"0x.js/src/contract_wrappers/generated/ether_token"', '"0x.js/src/contract_wrappers/generated/token"', '"0x.js/src/contract_wrappers/generated/exchange"', @@ -114,7 +120,7 @@ const docsInfoConfig: DocsInfoConfig = { 'Order', 'SignedOrder', 'ECSignature', - 'ZeroExError', + 'ContractWrappersError', 'EventCallback', 'EventCallbackAsync', 'EventCallbackSync', diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 0d77b9e72..472870f31 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -1,4 +1,4 @@ -import { ECSignature, ExchangeContractErrs, ZeroEx, ZeroExError } from '0x.js'; +import { ContractWrappersError, ECSignature, ExchangeContractErrs, ZeroEx } from '0x.js'; import { OrderError } from '@0xproject/order-utils'; import { constants as sharedConstants, EtherscanLinkSuffixes, Networks } from '@0xproject/react-shared'; import { Provider } from '@0xproject/types'; @@ -6,7 +6,17 @@ import { BigNumber } from '@0xproject/utils'; import deepEqual = require('deep-equal'); import * as _ from 'lodash'; import * as moment from 'moment'; -import { Environments, Order, Providers, ScreenWidths, Side, SideToAssetToken, Token, TokenByAddress } from 'ts/types'; +import { + BlockchainCallErrs, + Environments, + Order, + Providers, + ScreenWidths, + Side, + SideToAssetToken, + Token, + TokenByAddress, +} from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import * as u2f from 'ts/vendor/u2f_api'; @@ -193,21 +203,20 @@ export const utils = { const isUniqueSymbol = _.isUndefined(tokenWithSameSymbolIfExists); return isUniqueName && isUniqueSymbol; }, - zeroExErrToHumanReadableErrMsg(error: ZeroExError | ExchangeContractErrs, takerAddress: string): string { - const ZeroExErrorToHumanReadableError: { [error: string]: string } = { - [ZeroExError.ExchangeContractDoesNotExist]: 'Exchange contract does not exist', - [ZeroExError.EtherTokenContractDoesNotExist]: 'EtherToken contract does not exist', - [ZeroExError.TokenTransferProxyContractDoesNotExist]: 'TokenTransferProxy contract does not exist', - [ZeroExError.TokenRegistryContractDoesNotExist]: 'TokenRegistry contract does not exist', - [ZeroExError.TokenContractDoesNotExist]: 'Token contract does not exist', - [ZeroExError.ZRXContractDoesNotExist]: 'ZRX contract does not exist', - [ZeroExError.UnhandledError]: 'Unhandled error occured', - [ZeroExError.UserHasNoAssociatedAddress]: 'User has no addresses available', + zeroExErrToHumanReadableErrMsg(error: ContractWrappersError | ExchangeContractErrs, takerAddress: string): string { + const ContractWrappersErrorToHumanReadableError: { [error: string]: string } = { + [ContractWrappersError.ExchangeContractDoesNotExist]: 'Exchange contract does not exist', + [ContractWrappersError.EtherTokenContractDoesNotExist]: 'EtherToken contract does not exist', + [ContractWrappersError.TokenTransferProxyContractDoesNotExist]: + 'TokenTransferProxy contract does not exist', + [ContractWrappersError.TokenRegistryContractDoesNotExist]: 'TokenRegistry contract does not exist', + [ContractWrappersError.TokenContractDoesNotExist]: 'Token contract does not exist', + [ContractWrappersError.ZRXContractDoesNotExist]: 'ZRX contract does not exist', + [BlockchainCallErrs.UserHasNoAssociatedAddresses]: 'User has no addresses available', [OrderError.InvalidSignature]: 'Order signature is not valid', - [ZeroExError.ContractNotDeployedOnNetwork]: 'Contract is not deployed on the detected network', - [ZeroExError.InvalidJump]: 'Invalid jump occured while executing the transaction', - [ZeroExError.OutOfGas]: 'Transaction ran out of gas', - [ZeroExError.NoNetworkId]: 'No network id detected', + [ContractWrappersError.ContractNotDeployedOnNetwork]: 'Contract is not deployed on the detected network', + [ContractWrappersError.InvalidJump]: 'Invalid jump occured while executing the transaction', + [ContractWrappersError.OutOfGas]: 'Transaction ran out of gas', }; const exchangeContractErrorToHumanReadableError: { [error: string]: string; @@ -240,7 +249,7 @@ export const utils = { [ExchangeContractErrs.InsufficientRemainingFillAmount]: 'Insufficient remaining fill amount', }; const humanReadableErrorMsg = - exchangeContractErrorToHumanReadableError[error] || ZeroExErrorToHumanReadableError[error]; + exchangeContractErrorToHumanReadableError[error] || ContractWrappersErrorToHumanReadableError[error]; return humanReadableErrorMsg; }, isParityNode(nodeVersion: string): boolean { |