| @@ -2,8 +2,7 @@ | ||||
|  | ||||
| v0.9.0 - TBD | ||||
| ------------------------ | ||||
|     * Move `zeroEx.exchange.getAvailableContractAddressesAsync` to `zeroEx.getAvailableExchangeContractAddressesAsync` (#94) | ||||
|     * Move `zeroEx.exchange.getProxyAuthorizedContractAddressesAsync` to `zeroEx.getProxyAuthorizedExchangeContractAddressesAsync` (#94) | ||||
|     * Remove the ability to call methods on multiple authorized Exchange smart contracts (#106) | ||||
|     * Cache `net_version` requests and invalidate the cache on calls to `setProvider` (#95) | ||||
|     * Rename `zeroEx.exchange.batchCancelOrderAsync` to `zeroEx.exchange.batchCancelOrdersAsync` | ||||
|     * Rename `zeroEx.exchange.batchFillOrderAsync` to `zeroEx.exchange.batchFillOrdersAsync` | ||||
|   | ||||
							
								
								
									
										39
									
								
								src/0x.ts
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/0x.ts
									
									
									
									
									
								
							| @@ -21,7 +21,6 @@ import {ECSignature, ZeroExError, Order, SignedOrder, Web3Provider} from './type | ||||
| import {orderHashSchema} from './schemas/order_hash_schema'; | ||||
| import {orderSchema} from './schemas/order_schemas'; | ||||
| import {SchemaValidator} from './utils/schema_validator'; | ||||
| import {ExchangeArtifactsByName} from './exchange_artifacts_by_name'; | ||||
|  | ||||
| // Customize our BigNumber instances | ||||
| bigNumberConfigs.configure(); | ||||
| @@ -245,42 +244,4 @@ export class ZeroEx { | ||||
|  | ||||
|         throw new Error(ZeroExError.INVALID_SIGNATURE); | ||||
|     } | ||||
|     /** | ||||
|      * Returns the ethereum addresses of all available exchange contracts | ||||
|      * supported by this library on the network that the supplied web3 | ||||
|      * provider is connected to | ||||
|      * @return  The ethereum addresses of all available exchange contracts. | ||||
|      */ | ||||
|     public async getAvailableExchangeContractAddressesAsync(): Promise<string[]> { | ||||
|         const networkId = await this._web3Wrapper.getNetworkIdIfExistsAsync(); | ||||
|         if (_.isUndefined(networkId)) { | ||||
|             return []; | ||||
|         } else { | ||||
|             const exchangeArtifacts = _.values(ExchangeArtifactsByName); | ||||
|             const networkSpecificExchangeArtifacts = _.compact(_.map( | ||||
|                 exchangeArtifacts, exchangeArtifact => exchangeArtifact.networks[networkId])); | ||||
|             const exchangeAddresses = _.map( | ||||
|                 networkSpecificExchangeArtifacts, | ||||
|                 networkSpecificExchangeArtifact => networkSpecificExchangeArtifact.address, | ||||
|             ); | ||||
|             return exchangeAddresses; | ||||
|         } | ||||
|     } | ||||
|     /** | ||||
|      * Returns the ethereum addresses of all available exchange contracts | ||||
|      * supported by this library on the network that the supplied web3 | ||||
|      * provider is connected to that are currently authorized by the Proxy contract | ||||
|      * @return  The ethereum addresses of all available and authorized exchange contract. | ||||
|      */ | ||||
|     public async getProxyAuthorizedExchangeContractAddressesAsync(): Promise<string[]> { | ||||
|         const exchangeContractAddresses = await this.getAvailableExchangeContractAddressesAsync(); | ||||
|         const proxyAuthorizedExchangeContractAddresses = []; | ||||
|         for (const exchangeContractAddress of exchangeContractAddresses) { | ||||
|             const isAuthorized = await this.proxy.isAuthorizedAsync(exchangeContractAddress); | ||||
|             if (isAuthorized) { | ||||
|                 proxyAuthorizedExchangeContractAddresses.push(exchangeContractAddress); | ||||
|             } | ||||
|         } | ||||
|         return proxyAuthorizedExchangeContractAddresses; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -49,7 +49,7 @@ import {signedOrderSchema, orderSchema} from '../schemas/order_schemas'; | ||||
| import {constants} from '../utils/constants'; | ||||
| import {TokenWrapper} from './token_wrapper'; | ||||
| import {decorators} from '../utils/decorators'; | ||||
| import {ExchangeArtifactsByName} from '../exchange_artifacts_by_name'; | ||||
| import * as ExchangeArtifacts from '../artifacts/Exchange.json'; | ||||
|  | ||||
| /** | ||||
|  * This class includes all the functionality related to calling methods and subscribing to | ||||
| @@ -64,7 +64,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         [ExchangeContractErrCodes.ERROR_FILL_TRUNCATION]: ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR, | ||||
|         [ExchangeContractErrCodes.ERROR_FILL_BALANCE_ALLOWANCE]: ExchangeContractErrs.FILL_BALANCE_ALLOWANCE_ERROR, | ||||
|     }; | ||||
|     private _exchangeContractByAddress: ExchangeContractByAddress; | ||||
|     private _exchangeContractIfExists?: ExchangeContract; | ||||
|     private _exchangeLogEventEmitters: ContractEventEmitter[]; | ||||
|     private _tokenWrapper: TokenWrapper; | ||||
|     private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] { | ||||
| @@ -89,7 +89,6 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         super(web3Wrapper); | ||||
|         this._tokenWrapper = tokenWrapper; | ||||
|         this._exchangeLogEventEmitters = []; | ||||
|         this._exchangeContractByAddress = {}; | ||||
|     } | ||||
|     /** | ||||
|      * Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total | ||||
| @@ -97,14 +96,12 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|      * subtracting the unavailable amount from the total order takerAmount. | ||||
|      * @param   orderHash               The hex encoded orderHash for which you would like to retrieve the | ||||
|      *                                  unavailable takerAmount. | ||||
|      * @param   exchangeContractAddress The hex encoded address of the Exchange contract to call. | ||||
|      * @return  The amount of the order (in taker tokens) that has either been filled or canceled. | ||||
|      */ | ||||
|     public async getUnavailableTakerAmountAsync(orderHash: string, | ||||
|                                                 exchangeContractAddress: string): Promise<BigNumber.BigNumber> { | ||||
|     public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> { | ||||
|         assert.doesConformToSchema('orderHash', orderHash, orderHashSchema); | ||||
|  | ||||
|         const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress); | ||||
|         const exchangeContract = await this._getExchangeContractAsync(); | ||||
|         let unavailableTakerTokenAmount = await exchangeContract.getUnavailableTakerTokenAmount.call(orderHash); | ||||
|         // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber | ||||
|         unavailableTakerTokenAmount = new BigNumber(unavailableTakerTokenAmount); | ||||
| @@ -113,14 +110,12 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|     /** | ||||
|      * Retrieve the takerAmount of an order that has already been filled. | ||||
|      * @param   orderHash    The hex encoded orderHash for which you would like to retrieve the filled takerAmount. | ||||
|      * @param   exchangeContractAddress The hex encoded address of the Exchange contract to call. | ||||
|      * @return  The amount of the order (in taker tokens) that has already been filled. | ||||
|      */ | ||||
|     public async getFilledTakerAmountAsync(orderHash: string, | ||||
|                                            exchangeContractAddress: string): Promise<BigNumber.BigNumber> { | ||||
|     public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> { | ||||
|         assert.doesConformToSchema('orderHash', orderHash, orderHashSchema); | ||||
|  | ||||
|         const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress); | ||||
|         const exchangeContract = await this._getExchangeContractAsync(); | ||||
|         let fillAmountInBaseUnits = await exchangeContract.filled.call(orderHash); | ||||
|         // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber | ||||
|         fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits); | ||||
| @@ -130,14 +125,12 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|      * Retrieve the takerAmount of an order that has been cancelled. | ||||
|      * @param   orderHash    The hex encoded orderHash for which you would like to retrieve the | ||||
|      *                       cancelled takerAmount. | ||||
|      * @param   exchangeContractAddress The hex encoded address of the Exchange contract to call. | ||||
|      * @return  The amount of the order (in taker tokens) that has been cancelled. | ||||
|      */ | ||||
|     public async getCanceledTakerAmountAsync(orderHash: string, | ||||
|                                              exchangeContractAddress: string): Promise<BigNumber.BigNumber> { | ||||
|     public async getCanceledTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> { | ||||
|         assert.doesConformToSchema('orderHash', orderHash, orderHashSchema); | ||||
|  | ||||
|         const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress); | ||||
|         const exchangeContract = await this._getExchangeContractAsync(); | ||||
|         let cancelledAmountInBaseUnits = await exchangeContract.cancelled.call(orderHash); | ||||
|         // Wrap BigNumbers returned from web3 with our own (later) version of BigNumber | ||||
|         cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits); | ||||
| @@ -169,7 +162,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); | ||||
|         await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); | ||||
|  | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(signedOrder.exchangeContractAddress); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         await this._validateFillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerTokenAmount, takerAddress); | ||||
|  | ||||
|         const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); | ||||
| @@ -228,9 +221,6 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress); | ||||
|         assert.hasAtMostOneUniqueValue(takerTokenAddresses, | ||||
|                                        ExchangeContractErrs.MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED); | ||||
|         const exchangeContractAddresses = _.map(signedOrders, signedOrder => signedOrder.exchangeContractAddress); | ||||
|         assert.hasAtMostOneUniqueValue(exchangeContractAddresses, | ||||
|                                        ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS); | ||||
|         assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); | ||||
|         assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); | ||||
|         await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); | ||||
| @@ -255,7 +245,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|             orderAddressesValuesAndSignatureArray, | ||||
|         ); | ||||
|  | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         const gas = await exchangeInstance.fillOrdersUpTo.estimateGas( | ||||
|             orderAddressesArray, | ||||
|             orderValuesArray, | ||||
| @@ -310,12 +300,6 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|                                       shouldThrowOnInsufficientBalanceOrAllowance: boolean, | ||||
|                                       takerAddress: string): Promise<void> { | ||||
|         assert.doesConformToSchema('orderFillRequests', orderFillRequests, orderFillRequestsSchema); | ||||
|         const exchangeContractAddresses = _.map( | ||||
|             orderFillRequests, | ||||
|             orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress, | ||||
|         ); | ||||
|         assert.hasAtMostOneUniqueValue(exchangeContractAddresses, | ||||
|                                        ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS); | ||||
|         assert.isBoolean('shouldThrowOnInsufficientBalanceOrAllowance', shouldThrowOnInsufficientBalanceOrAllowance); | ||||
|         await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); | ||||
|         for (const orderFillRequest of orderFillRequests) { | ||||
| @@ -340,7 +324,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|             orderAddressesValuesAmountsAndSignatureArray, | ||||
|         ); | ||||
|  | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         const gas = await exchangeInstance.batchFillOrders.estimateGas( | ||||
|             orderAddressesArray, | ||||
|             orderValuesArray, | ||||
| @@ -384,11 +368,10 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         assert.isBigNumber('fillTakerTokenAmount', fillTakerTokenAmount); | ||||
|         await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper); | ||||
|  | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(signedOrder.exchangeContractAddress); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         await this._validateFillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerTokenAmount, takerAddress); | ||||
|  | ||||
|         await this._validateFillOrKillOrderAndThrowIfInvalidAsync(signedOrder, exchangeInstance.address, | ||||
|                                                                  fillTakerTokenAmount); | ||||
|         await this._validateFillOrKillOrderAndThrowIfInvalidAsync(signedOrder, fillTakerTokenAmount); | ||||
|  | ||||
|         const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder); | ||||
|  | ||||
| @@ -438,10 +421,9 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         if (_.isEmpty(orderFillOrKillRequests)) { | ||||
|             return; // no-op | ||||
|         } | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         for (const request of orderFillOrKillRequests) { | ||||
|             await this._validateFillOrKillOrderAndThrowIfInvalidAsync(request.signedOrder, exchangeInstance.address, | ||||
|                                                                      request.fillTakerAmount); | ||||
|             await this._validateFillOrKillOrderAndThrowIfInvalidAsync(request.signedOrder, request.fillTakerAmount); | ||||
|         } | ||||
|  | ||||
|         const orderAddressesValuesAndTakerTokenFillAmounts = _.map(orderFillOrKillRequests, request => { | ||||
| @@ -497,7 +479,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         assert.isBigNumber('takerTokenCancelAmount', cancelTakerTokenAmount); | ||||
|         await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper); | ||||
|  | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(order.exchangeContractAddress); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         await this._validateCancelOrderAndThrowIfInvalidAsync(order, cancelTakerTokenAmount); | ||||
|  | ||||
|         const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); | ||||
| @@ -551,7 +533,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         if (_.isEmpty(orderCancellationRequests)) { | ||||
|             return; // no-op | ||||
|         } | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => { | ||||
|             return [ | ||||
|                 ...ExchangeWrapper._getOrderAddressesAndValues(cancellationRequest.order), | ||||
| @@ -596,7 +578,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); | ||||
|         assert.doesConformToSchema('subscriptionOpts', subscriptionOpts, subscriptionOptsSchema); | ||||
|         assert.doesConformToSchema('indexFilterValues', indexFilterValues, indexFilterValuesSchema); | ||||
|         const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress); | ||||
|         const exchangeContract = await this._getExchangeContractAsync(); | ||||
|         let createLogEvent: CreateContractEvent; | ||||
|         switch (eventName) { | ||||
|             case ExchangeEvents.LogFill: | ||||
| @@ -626,18 +608,26 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         await Promise.all(stopWatchingPromises); | ||||
|         this._exchangeLogEventEmitters = []; | ||||
|     } | ||||
|     /** | ||||
|      * Retrieves the Ethereum address of the Exchange contract deployed on the network | ||||
|      * that the user-passed web3 provider is connected to. | ||||
|      * @returns The Ethereum address of the Exchange contract being used. | ||||
|      */ | ||||
|     public async getContractAddressAsync(): Promise<string> { | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         return exchangeInstance.address; | ||||
|     } | ||||
|     private async _invalidateContractInstancesAsync(): Promise<void> { | ||||
|         await this.stopWatchingAllEventsAsync(); | ||||
|         this._exchangeContractByAddress = {}; | ||||
|         delete this._exchangeContractIfExists; | ||||
|     } | ||||
|     private async _isValidSignatureUsingContractCallAsync(dataHex: string, ecSignature: ECSignature, | ||||
|                                                           signerAddressHex: string, | ||||
|                                                           exchangeContractAddress: string): Promise<boolean> { | ||||
|                                                           signerAddressHex: string): Promise<boolean> { | ||||
|         assert.isHexString('dataHex', dataHex); | ||||
|         assert.doesConformToSchema('ecSignature', ecSignature, ecSignatureSchema); | ||||
|         assert.isETHAddressHex('signerAddressHex', signerAddressHex); | ||||
|  | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|  | ||||
|         const isValidSignature = await exchangeInstance.isValidSignature.call( | ||||
|             signerAddressHex, | ||||
| @@ -649,7 +639,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         return isValidSignature; | ||||
|     } | ||||
|     private async _getOrderHashHexUsingContractCallAsync(order: Order|SignedOrder): Promise<string> { | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(order.exchangeContractAddress); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order); | ||||
|         const orderHashHex = await exchangeInstance.getOrderHash.call(orderAddresses, orderValues); | ||||
|         return orderHashHex; | ||||
| @@ -673,7 +663,6 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|  | ||||
|         const wouldRoundingErrorOccur = await this._isRoundingErrorAsync( | ||||
|             signedOrder.takerTokenAmount, fillTakerAmount, signedOrder.makerTokenAmount, | ||||
|             signedOrder.exchangeContractAddress, | ||||
|         ); | ||||
|         if (wouldRoundingErrorOccur) { | ||||
|             throw new Error(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR); | ||||
| @@ -685,7 +674,7 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|             throw new Error(ExchangeContractErrs.ORDER_CANCEL_AMOUNT_ZERO); | ||||
|         } | ||||
|         const orderHash = utils.getOrderHashHex(order); | ||||
|         const unavailableAmount = await this.getUnavailableTakerAmountAsync(orderHash, order.exchangeContractAddress); | ||||
|         const unavailableAmount = await this.getUnavailableTakerAmountAsync(orderHash); | ||||
|         if (order.takerTokenAmount.minus(unavailableAmount).eq(0)) { | ||||
|             throw new Error(ExchangeContractErrs.ORDER_ALREADY_CANCELLED_OR_FILLED); | ||||
|         } | ||||
| @@ -695,11 +684,10 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|         } | ||||
|     } | ||||
|     private async _validateFillOrKillOrderAndThrowIfInvalidAsync(signedOrder: SignedOrder, | ||||
|                                                                  exchangeContractAddress: string, | ||||
|                                                                  fillTakerAmount: BigNumber.BigNumber) { | ||||
|         // Check that fillValue available >= fillTakerAmount | ||||
|         const orderHashHex = utils.getOrderHashHex(signedOrder); | ||||
|         const unavailableTakerAmount = await this.getUnavailableTakerAmountAsync(orderHashHex, exchangeContractAddress); | ||||
|         const unavailableTakerAmount = await this.getUnavailableTakerAmountAsync(orderHashHex); | ||||
|         const remainingTakerAmount = signedOrder.takerTokenAmount.minus(unavailableTakerAmount); | ||||
|         if (remainingTakerAmount < fillTakerAmount) { | ||||
|             throw new Error(ExchangeContractErrs.INSUFFICIENT_REMAINING_FILL_AMOUNT); | ||||
| @@ -776,40 +764,24 @@ export class ExchangeWrapper extends ContractWrapper { | ||||
|     } | ||||
|     private async _isRoundingErrorAsync(numerator: BigNumber.BigNumber, | ||||
|                                         demoninator: BigNumber.BigNumber, | ||||
|                                         makerTokenAmount: BigNumber.BigNumber, | ||||
|                                         exchangeContractAddress: string): Promise<boolean> { | ||||
|                                         makerTokenAmount: BigNumber.BigNumber): Promise<boolean> { | ||||
|         await assert.isUserAddressAvailableAsync(this._web3Wrapper); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         const isRoundingError = await exchangeInstance.isRoundingError.call( | ||||
|             demoninator, numerator, makerTokenAmount, | ||||
|         ); | ||||
|         return isRoundingError; | ||||
|     } | ||||
|     private async _getExchangeContractAsync(exchangeContractAddress: string): Promise<ExchangeContract> { | ||||
|         if (!_.isUndefined(this._exchangeContractByAddress[exchangeContractAddress])) { | ||||
|             return this._exchangeContractByAddress[exchangeContractAddress]; | ||||
|     private async _getExchangeContractAsync(): Promise<ExchangeContract> { | ||||
|         if (!_.isUndefined(this._exchangeContractIfExists)) { | ||||
|             return this._exchangeContractIfExists; | ||||
|         } | ||||
|         const ExchangeArtifacts = this._getExchangeArtifactsByAddressOrThrow(exchangeContractAddress); | ||||
|         const contractInstance = await this._instantiateContractIfExistsAsync((ExchangeArtifacts as any)); | ||||
|         this._exchangeContractByAddress[exchangeContractAddress] = contractInstance as ExchangeContract; | ||||
|         return this._exchangeContractByAddress[exchangeContractAddress]; | ||||
|     } | ||||
|     private _getExchangeArtifactsByAddressOrThrow(exchangeContractAddress: string): ContractArtifact { | ||||
|         const exchangeArtifacts = _.values<ContractArtifact>(ExchangeArtifactsByName); | ||||
|         for (const exchangeArtifact of exchangeArtifacts) { | ||||
|             const networkSpecificExchangeArtifactValues = _.values(exchangeArtifact.networks); | ||||
|             const exchangeAddressesInArtifact = _.map( | ||||
|                 networkSpecificExchangeArtifactValues, | ||||
|                 networkSpecificExchangeArtifact => networkSpecificExchangeArtifact.address, | ||||
|             ); | ||||
|             if (_.includes(exchangeAddressesInArtifact, exchangeContractAddress)) { | ||||
|                 return exchangeArtifact; | ||||
|             } | ||||
|         } | ||||
|         throw new Error(ZeroExError.EXCHANGE_CONTRACT_DOES_NOT_EXIST); | ||||
|         this._exchangeContractIfExists = contractInstance as ExchangeContract; | ||||
|         return this._exchangeContractIfExists; | ||||
|     } | ||||
|     private async _getZRXTokenAddressAsync(exchangeContractAddress: string): Promise<string> { | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress); | ||||
|         const exchangeInstance = await this._getExchangeContractAsync(); | ||||
|         const ZRXtokenAddress = await exchangeInstance.ZRX_TOKEN_CONTRACT.call(); | ||||
|         return ZRXtokenAddress; | ||||
|     } | ||||
|   | ||||
| @@ -21,10 +21,9 @@ export class ProxyWrapper extends ContractWrapper { | ||||
|     } | ||||
|     /** | ||||
|      * Get the list of all Exchange contract addresses authorized by the Proxy contract. | ||||
|      * @param   exchangeContractAddress     The hex encoded address of the Exchange contract to call. | ||||
|      * @return  The list of authorized addresses. | ||||
|      */ | ||||
|     public async getAuthorizedAddressesAsync(exchangeContractAddress: string): Promise<string[]> { | ||||
|     public async getAuthorizedAddressesAsync(): Promise<string[]> { | ||||
|         const proxyContractInstance = await this._getProxyContractAsync(); | ||||
|         const authorizedAddresses = await proxyContractInstance.getAuthorizedAddresses.call(); | ||||
|         return authorizedAddresses; | ||||
|   | ||||
| @@ -1,6 +0,0 @@ | ||||
| import {ContractArtifact} from './types'; | ||||
| import * as Exchange_v1 from './artifacts/exchange/Exchange_v1.json'; | ||||
|  | ||||
| export const ExchangeArtifactsByName = { | ||||
|     Exchange_v1: Exchange_v1 as any as ContractArtifact, | ||||
| }; | ||||
| @@ -17,11 +17,10 @@ describe('ZeroEx library', () => { | ||||
|     const zeroEx = new ZeroEx(web3.currentProvider); | ||||
|     describe('#setProvider', () => { | ||||
|         it('overrides provider in nested web3s and invalidates contractInstances', async () => { | ||||
|             const [exchangeContractAddress] = await zeroEx.getAvailableExchangeContractAddressesAsync(); | ||||
|             // Instantiate the contract instances with the current provider | ||||
|             await (zeroEx.exchange as any)._getExchangeContractAsync(exchangeContractAddress); | ||||
|             await (zeroEx.exchange as any)._getExchangeContractAsync(); | ||||
|             await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync(); | ||||
|             expect((zeroEx.exchange as any)._exchangeContractByAddress[exchangeContractAddress]).to.not.be.undefined(); | ||||
|             expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined(); | ||||
|             expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined(); | ||||
|  | ||||
|             const newProvider = web3Factory.getRpcProvider(); | ||||
| @@ -30,7 +29,7 @@ describe('ZeroEx library', () => { | ||||
|             await zeroEx.setProviderAsync(newProvider); | ||||
|  | ||||
|             // Check that contractInstances with old provider are removed after provider update | ||||
|             expect((zeroEx.exchange as any)._exchangeContractByAddress[exchangeContractAddress]).to.be.undefined(); | ||||
|             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 | ||||
| @@ -52,10 +51,6 @@ describe('ZeroEx library', () => { | ||||
|             s: '0x40349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254', | ||||
|         }; | ||||
|         const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; | ||||
|         let exchangeContractAddress: string; | ||||
|         before(async () => { | ||||
|             [exchangeContractAddress] = await zeroEx.getAvailableExchangeContractAddressesAsync(); | ||||
|         }); | ||||
|         it('should return false if the data doesn\'t pertain to the signature & address', async () => { | ||||
|             expect(ZeroEx.isValidSignature('0x0', signature, address)).to.be.false(); | ||||
|             return expect( | ||||
| @@ -81,7 +76,7 @@ describe('ZeroEx library', () => { | ||||
|             const isValidSignatureLocal = ZeroEx.isValidSignature(dataHex, signature, address); | ||||
|             expect(isValidSignatureLocal).to.be.true(); | ||||
|             const isValidSignatureOnContract = await (zeroEx.exchange as any) | ||||
|                 ._isValidSignatureUsingContractCallAsync(dataHex, signature, address, exchangeContractAddress); | ||||
|                 ._isValidSignatureUsingContractCallAsync(dataHex, signature, address); | ||||
|             return expect(isValidSignatureOnContract).to.be.true(); | ||||
|         }); | ||||
|     }); | ||||
| @@ -210,22 +205,4 @@ describe('ZeroEx library', () => { | ||||
|             expect(ecSignature).to.deep.equal(expectedECSignature); | ||||
|         }); | ||||
|     }); | ||||
|     describe('#getAvailableExchangeContractAddressesAsync', () => { | ||||
|         it('returns the exchange contract addresses', async () => { | ||||
|             const exchangeAddresses = await zeroEx.getAvailableExchangeContractAddressesAsync(); | ||||
|             _.map(exchangeAddresses, exchangeAddress => { | ||||
|                 assert.isETHAddressHex('exchangeAddress', exchangeAddress); | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
|     describe('#getProxyAuthorizedExchangeContractAddressesAsync', () => { | ||||
|         it('returns the Proxy authorized exchange contract addresses', async () => { | ||||
|             const exchangeAddresses = await zeroEx.getProxyAuthorizedExchangeContractAddressesAsync(); | ||||
|             for (const exchangeAddress of exchangeAddresses) { | ||||
|                 assert.isETHAddressHex('exchangeAddress', exchangeAddress); | ||||
|                 const isAuthorized = await zeroEx.proxy.isAuthorizedAsync(exchangeAddress); | ||||
|                 expect(isAuthorized).to.be.true(); | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
|   | ||||
| @@ -27,8 +27,7 @@ describe('Artifacts', () => { | ||||
|             await (zeroEx.token as any)._getProxyAddressAsync(); | ||||
|         }).timeout(TIMEOUT); | ||||
|         it('exchange contract is deployed', async () => { | ||||
|             const exchangeContractAddresses = await zeroEx.getAvailableExchangeContractAddressesAsync(); | ||||
|             expect(exchangeContractAddresses).to.have.lengthOf.above(0); | ||||
|             await zeroEx.exchange.getContractAddressAsync(); | ||||
|         }).timeout(TIMEOUT); | ||||
|     }); | ||||
| }); | ||||
|   | ||||
| @@ -44,7 +44,7 @@ describe('ExchangeWrapper', () => { | ||||
|     before(async () => { | ||||
|         web3 = web3Factory.create(); | ||||
|         zeroEx = new ZeroEx(web3.currentProvider); | ||||
|         [exchangeContractAddress] = await zeroEx.getAvailableExchangeContractAddressesAsync(); | ||||
|         exchangeContractAddress = await zeroEx.exchange.getContractAddressAsync(); | ||||
|         userAddresses = await promisify(web3.eth.getAccounts)(); | ||||
|         tokens = await zeroEx.tokenRegistry.getTokensAsync(); | ||||
|         tokenUtils = new TokenUtils(tokens); | ||||
| @@ -418,12 +418,8 @@ describe('ExchangeWrapper', () => { | ||||
|                 }); | ||||
|                 it('should successfully fill multiple orders', async () => { | ||||
|                     await zeroEx.exchange.batchFillOrdersAsync(orderFillBatch, shouldCheckTransfer, takerAddress); | ||||
|                     const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                         signedOrderHashHex, exchangeContractAddress, | ||||
|                     ); | ||||
|                     const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                         anotherOrderHashHex, exchangeContractAddress, | ||||
|                     ); | ||||
|                     const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex); | ||||
|                     const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex); | ||||
|                     expect(filledAmount).to.be.bignumber.equal(fillTakerAmount); | ||||
|                     expect(anotherFilledAmount).to.be.bignumber.equal(fillTakerAmount); | ||||
|                 }); | ||||
| @@ -455,12 +451,8 @@ describe('ExchangeWrapper', () => { | ||||
|                     await zeroEx.exchange.fillOrdersUpToAsync( | ||||
|                         signedOrders, fillUpToAmount, shouldCheckTransfer, takerAddress, | ||||
|                     ); | ||||
|                     const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                         signedOrderHashHex, exchangeContractAddress, | ||||
|                     ); | ||||
|                     const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync( | ||||
|                         anotherOrderHashHex, exchangeContractAddress, | ||||
|                     ); | ||||
|                     const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex); | ||||
|                     const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex); | ||||
|                     expect(filledAmount).to.be.bignumber.equal(fillableAmount); | ||||
|                     const remainingFillAmount = fillableAmount.minus(1); | ||||
|                     expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount); | ||||
| @@ -520,9 +512,7 @@ describe('ExchangeWrapper', () => { | ||||
|             describe('successful cancels', () => { | ||||
|                 it('should cancel an order', async () => { | ||||
|                     await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount); | ||||
|                     const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync( | ||||
|                         orderHashHex, exchangeContractAddress, | ||||
|                     ); | ||||
|                     const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex); | ||||
|                     expect(cancelledAmount).to.be.bignumber.equal(cancelAmount); | ||||
|                 }); | ||||
|                 it('should return cancelled amount', async () => { | ||||
| @@ -568,11 +558,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.getCanceledTakerAmountAsync( | ||||
|                         orderHashHex, exchangeContractAddress, | ||||
|                     ); | ||||
|                     const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex); | ||||
|                     const anotherCancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync( | ||||
|                         anotherOrderHashHex, exchangeContractAddress, | ||||
|                         anotherOrderHashHex, | ||||
|                     ); | ||||
|                     expect(cancelledAmount).to.be.bignumber.equal(cancelAmount); | ||||
|                     expect(anotherCancelledAmount).to.be.bignumber.equal(cancelAmount); | ||||
| @@ -605,68 +593,49 @@ describe('ExchangeWrapper', () => { | ||||
|         describe('#getUnavailableTakerAmountAsync', () => { | ||||
|             it('should throw if passed an invalid orderHash', async () => { | ||||
|                 const invalidOrderHashHex = '0x123'; | ||||
|                 return expect(zeroEx.exchange.getUnavailableTakerAmountAsync( | ||||
|                     invalidOrderHashHex, exchangeContractAddress, | ||||
|                 )).to.be.rejected(); | ||||
|                 return expect(zeroEx.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, exchangeContractAddress, | ||||
|                 ); | ||||
|                 const unavailableValueT = await zeroEx.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, exchangeContractAddress, | ||||
|                 ); | ||||
|                 const unavailableValueT = await zeroEx.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, exchangeContractAddress, | ||||
|                 )).to.be.rejected(); | ||||
|                 return expect(zeroEx.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, exchangeContractAddress, | ||||
|                 const filledValueT = await zeroEx.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, exchangeContractAddress, | ||||
|                 ); | ||||
|                 const filledValueT = await zeroEx.exchange.getFilledTakerAmountAsync(orderHash); | ||||
|                 expect(filledValueT).to.be.bignumber.equal(partialFillAmount); | ||||
|             }); | ||||
|         }); | ||||
|         describe('#getCanceledTakerAmountAsync', () => { | ||||
|             it('should throw if passed an invalid orderHash', async () => { | ||||
|                 const invalidOrderHashHex = '0x123'; | ||||
|                 return expect(zeroEx.exchange.getCanceledTakerAmountAsync( | ||||
|                     invalidOrderHashHex, exchangeContractAddress, | ||||
|                 )).to.be.rejected(); | ||||
|                 return expect(zeroEx.exchange.getCanceledTakerAmountAsync(invalidOrderHashHex)).to.be.rejected(); | ||||
|             }); | ||||
|             it('should return zero if passed a valid but non-existent orderHash', async () => { | ||||
|                 const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync( | ||||
|                     NON_EXISTENT_ORDER_HASH, exchangeContractAddress, | ||||
|                 ); | ||||
|                 const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(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.getCanceledTakerAmountAsync( | ||||
|                     orderHash, exchangeContractAddress, | ||||
|                 ); | ||||
|                 const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(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.getCanceledTakerAmountAsync( | ||||
|                     orderHash, exchangeContractAddress, | ||||
|                 ); | ||||
|                 const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHash); | ||||
|                 expect(cancelledValueT).to.be.bignumber.equal(cancelAmount); | ||||
|             }); | ||||
|         }); | ||||
|   | ||||
| @@ -9,11 +9,9 @@ const expect = chai.expect; | ||||
|  | ||||
| describe('ProxyWrapper', () => { | ||||
|     let zeroEx: ZeroEx; | ||||
|     let exchangeContractAddress: string; | ||||
|     before(async () => { | ||||
|         const web3 = web3Factory.create(); | ||||
|         zeroEx = new ZeroEx(web3.currentProvider); | ||||
|         [exchangeContractAddress] = await zeroEx.getAvailableExchangeContractAddressesAsync(); | ||||
|     }); | ||||
|     describe('#isAuthorizedAsync', () => { | ||||
|         it('should return false if the address is not authorized', async () => { | ||||
| @@ -23,7 +21,7 @@ describe('ProxyWrapper', () => { | ||||
|     }); | ||||
|     describe('#getAuthorizedAddressesAsync', () => { | ||||
|         it('should return the list of authorized addresses', async () => { | ||||
|             const authorizedAddresses = await zeroEx.proxy.getAuthorizedAddressesAsync(exchangeContractAddress); | ||||
|             const authorizedAddresses = await zeroEx.proxy.getAuthorizedAddressesAsync(); | ||||
|             for (const authorizedAddress of authorizedAddresses) { | ||||
|                 const isAuthorized = await zeroEx.proxy.isAuthorizedAsync(authorizedAddress); | ||||
|                 expect(isAuthorized).to.be.true(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user