Allow multiple exchange versions t be functional at the same time
This commit is contained in:
@@ -16,7 +16,6 @@ import {EtherTokenWrapper} from './contract_wrappers/ether_token_wrapper';
|
||||
import {ecSignatureSchema} from './schemas/ec_signature_schema';
|
||||
import {TokenWrapper} from './contract_wrappers/token_wrapper';
|
||||
import {ECSignature, ZeroExError, Order, SignedOrder, Web3Provider} from './types';
|
||||
import * as ExchangeArtifacts from './artifacts/Exchange.json';
|
||||
import {orderSchema} from './schemas/order_schemas';
|
||||
|
||||
// Customize our BigNumber instances
|
||||
@@ -179,9 +178,7 @@ export class ZeroEx {
|
||||
*/
|
||||
public async getOrderHashHexAsync(order: Order|SignedOrder): Promise<string> {
|
||||
assert.doesConformToSchema('order', order, orderSchema);
|
||||
|
||||
const exchangeContractAddr = await this._getExchangeAddressAsync();
|
||||
const orderHashHex = utils.getOrderHashHex(order, exchangeContractAddr);
|
||||
const orderHashHex = utils.getOrderHashHex(order, order.exchangeContractAddress);
|
||||
return orderHashHex;
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ExchangeContract,
|
||||
ExchangeContractErrCodes,
|
||||
ExchangeContractErrs,
|
||||
ZeroExError,
|
||||
OrderValues,
|
||||
OrderAddresses,
|
||||
Order,
|
||||
@@ -25,11 +26,13 @@ import {
|
||||
LogErrorContractEventArgs,
|
||||
LogFillContractEventArgs,
|
||||
LogCancelContractEventArgs,
|
||||
ExchangeContractByAddress,
|
||||
ContractArtifact,
|
||||
} from '../types';
|
||||
import {assert} from '../utils/assert';
|
||||
import {utils} from '../utils/utils';
|
||||
import {ContractWrapper} from './contract_wrapper';
|
||||
import * as ExchangeArtifacts from '../artifacts/exchange/Exchange.json';
|
||||
import {ExchangeArtifactsByName} from '../exchange_artifacts_by_name';
|
||||
import {ecSignatureSchema} from '../schemas/ec_signature_schema';
|
||||
import {signedOrdersSchema} from '../schemas/signed_orders_schema';
|
||||
import {orderFillRequestsSchema} from '../schemas/order_fill_requests_schema';
|
||||
@@ -53,7 +56,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 _exchangeContractIfExists?: ExchangeContract;
|
||||
private _exchangeContractByAddress: ExchangeContractByAddress;
|
||||
private _exchangeLogEventEmitters: ContractEventEmitter[];
|
||||
private _tokenWrapper: TokenWrapper;
|
||||
private static _getOrderAddressesAndValues(order: Order): [OrderAddresses, OrderValues] {
|
||||
@@ -78,23 +81,26 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
super(web3Wrapper);
|
||||
this._tokenWrapper = tokenWrapper;
|
||||
this._exchangeLogEventEmitters = [];
|
||||
this._exchangeContractByAddress = {};
|
||||
}
|
||||
public async invalidateContractInstanceAsync(): Promise<void> {
|
||||
await this.stopWatchingAllEventsAsync();
|
||||
delete this._exchangeContractIfExists;
|
||||
this._exchangeContractByAddress = {};
|
||||
}
|
||||
/**
|
||||
* Returns the unavailable takerAmount of an order. Unavailable amount is defined as the total
|
||||
* amount that has been filled or cancelled. The remaining takerAmount can be calculated by
|
||||
* 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 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 use.
|
||||
* @return The amount of the order (in taker tokens) that has either been filled or canceled.
|
||||
*/
|
||||
public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> {
|
||||
public async getUnavailableTakerAmountAsync(orderHash: string,
|
||||
exchangeContractAddress: string): Promise<BigNumber.BigNumber> {
|
||||
assert.isValidOrderHash('orderHash', orderHash);
|
||||
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress);
|
||||
let unavailableAmountInBaseUnits = await exchangeContract.getUnavailableValueT.call(orderHash);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
unavailableAmountInBaseUnits = new BigNumber(unavailableAmountInBaseUnits);
|
||||
@@ -103,12 +109,14 @@ 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 use.
|
||||
* @return The amount of the order (in taker tokens) that has already been filled.
|
||||
*/
|
||||
public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> {
|
||||
public async getFilledTakerAmountAsync(orderHash: string,
|
||||
exchangeContractAddress: string): Promise<BigNumber.BigNumber> {
|
||||
assert.isValidOrderHash('orderHash', orderHash);
|
||||
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress);
|
||||
let fillAmountInBaseUnits = await exchangeContract.filled.call(orderHash);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
fillAmountInBaseUnits = new BigNumber(fillAmountInBaseUnits);
|
||||
@@ -118,12 +126,14 @@ 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 use.
|
||||
* @return The amount of the order (in taker tokens) that has been cancelled.
|
||||
*/
|
||||
public async getCanceledTakerAmountAsync(orderHash: string): Promise<BigNumber.BigNumber> {
|
||||
public async getCanceledTakerAmountAsync(orderHash: string,
|
||||
exchangeContractAddress: string): Promise<BigNumber.BigNumber> {
|
||||
assert.isValidOrderHash('orderHash', orderHash);
|
||||
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress);
|
||||
let cancelledAmountInBaseUnits = await exchangeContract.cancelled.call(orderHash);
|
||||
// Wrap BigNumbers returned from web3 with our own (later) version of BigNumber
|
||||
cancelledAmountInBaseUnits = new BigNumber(cancelledAmountInBaseUnits);
|
||||
@@ -152,7 +162,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(signedOrder.exchangeContractAddress);
|
||||
await this._validateFillOrderAndThrowIfInvalidAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
||||
|
||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(signedOrder);
|
||||
@@ -207,7 +217,10 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
shouldCheckTransfer: boolean, takerAddress: string): Promise<BigNumber.BigNumber> {
|
||||
const takerTokenAddresses = _.map(signedOrders, signedOrder => signedOrder.takerTokenAddress);
|
||||
assert.hasAtMostOneUniqueValue(takerTokenAddresses,
|
||||
ExchangeContractErrs.MULTIPLE_TAKER_TOKENS_IN_FILL_UP_TO_DISALLOWED);
|
||||
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('takerTokenFillAmount', takerTokenFillAmount);
|
||||
assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer);
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, signedOrdersSchema);
|
||||
@@ -233,7 +246,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
orderAddressesValuesAndSignatureArray,
|
||||
);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]);
|
||||
const gas = await exchangeInstance.fillUpTo.estimateGas(
|
||||
orderAddressesArray,
|
||||
orderValuesArray,
|
||||
@@ -282,6 +295,12 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
@decorators.contractCallErrorHandler
|
||||
public async batchFillOrderAsync(orderFillRequests: OrderFillRequest[],
|
||||
shouldCheckTransfer: boolean, takerAddress: string): Promise<void> {
|
||||
const exchangeContractAddresses = _.map(
|
||||
orderFillRequests,
|
||||
orderFillRequest => orderFillRequest.signedOrder.exchangeContractAddress,
|
||||
);
|
||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
||||
ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS);
|
||||
assert.isBoolean('shouldCheckTransfer', shouldCheckTransfer);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
assert.doesConformToSchema('orderFillRequests', orderFillRequests, orderFillRequestsSchema);
|
||||
@@ -307,7 +326,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
orderAddressesValuesAmountsAndSignatureArray,
|
||||
);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]);
|
||||
const gas = await exchangeInstance.batchFill.estimateGas(
|
||||
orderAddressesArray,
|
||||
orderValuesArray,
|
||||
@@ -351,7 +370,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.isBigNumber('takerTokenFillAmount', takerTokenFillAmount);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(signedOrder.exchangeContractAddress);
|
||||
await this._validateFillOrderAndThrowIfInvalidAsync(signedOrder, takerTokenFillAmount, takerAddress);
|
||||
|
||||
await this._validateFillOrKillOrderAndThrowIfInvalidAsync(signedOrder, exchangeInstance.address,
|
||||
@@ -394,9 +413,18 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
@decorators.contractCallErrorHandler
|
||||
public async batchFillOrKillAsync(orderFillOrKillRequests: OrderFillOrKillRequest[],
|
||||
takerAddress: string): Promise<void> {
|
||||
const exchangeContractAddresses = _.map(
|
||||
orderFillOrKillRequests,
|
||||
orderFillOrKillRequest => orderFillOrKillRequest.signedOrder.exchangeContractAddress,
|
||||
);
|
||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
||||
ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS);
|
||||
await assert.isSenderAddressAsync('takerAddress', takerAddress, this._web3Wrapper);
|
||||
assert.doesConformToSchema('orderFillOrKillRequests', orderFillOrKillRequests, orderFillOrKillRequestsSchema);
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
if (_.isEmpty(orderFillOrKillRequests)) {
|
||||
return; // no-op
|
||||
}
|
||||
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]);
|
||||
for (const request of orderFillOrKillRequests) {
|
||||
await this._validateFillOrKillOrderAndThrowIfInvalidAsync(request.signedOrder, exchangeInstance.address,
|
||||
request.fillTakerAmount);
|
||||
@@ -455,7 +483,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
assert.isBigNumber('takerTokenCancelAmount', takerTokenCancelAmount);
|
||||
await assert.isSenderAddressAsync('order.maker', order.maker, this._web3Wrapper);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(order.exchangeContractAddress);
|
||||
await this._validateCancelOrderAndThrowIfInvalidAsync(order, takerTokenCancelAmount);
|
||||
|
||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
|
||||
@@ -489,6 +517,12 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
*/
|
||||
@decorators.contractCallErrorHandler
|
||||
public async batchCancelOrderAsync(orderCancellationRequests: OrderCancellationRequest[]): Promise<void> {
|
||||
const exchangeContractAddresses = _.map(
|
||||
orderCancellationRequests,
|
||||
orderCancellationRequest => orderCancellationRequest.order.exchangeContractAddress,
|
||||
);
|
||||
assert.hasAtMostOneUniqueValue(exchangeContractAddresses,
|
||||
ExchangeContractErrs.BATCH_ORDERS_MUST_HAVE_SAME_EXCHANGE_ADDRESS);
|
||||
const makers = _.map(orderCancellationRequests, cancellationRequest => cancellationRequest.order.maker);
|
||||
assert.hasAtMostOneUniqueValue(makers, ExchangeContractErrs.MULTIPLE_MAKERS_IN_SINGLE_CANCEL_BATCH_DISALLOWED);
|
||||
const maker = makers[0];
|
||||
@@ -503,7 +537,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
if (_.isEmpty(orderCancellationRequests)) {
|
||||
return; // no-op
|
||||
}
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddresses[0]);
|
||||
const orderAddressesValuesAndTakerTokenCancelAmounts = _.map(orderCancellationRequests, cancellationRequest => {
|
||||
return [
|
||||
...ExchangeWrapper._getOrderAddressesAndValues(cancellationRequest.order),
|
||||
@@ -534,16 +568,17 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
}
|
||||
/**
|
||||
* Subscribe to an event type emitted by the Exchange smart contract
|
||||
* @param eventName The exchange contract event you would like to subscribe to.
|
||||
* @param subscriptionOpts Subscriptions options that let you configure the subscription.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
|
||||
* @param eventName The exchange contract event you would like to subscribe to.
|
||||
* @param subscriptionOpts Subscriptions options that let you configure the subscription.
|
||||
* @param indexFilterValues An object where the keys are indexed args returned by the event and
|
||||
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
|
||||
* @param exchangeContractAddress The hex encoded address of the Exchange contract to use.
|
||||
* @return ContractEventEmitter object
|
||||
*/
|
||||
public async subscribeAsync(eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts,
|
||||
indexFilterValues: IndexedFilterValues):
|
||||
indexFilterValues: IndexedFilterValues, exchangeContractAddress: string):
|
||||
Promise<ContractEventEmitter> {
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
const exchangeContract = await this._getExchangeContractAsync(exchangeContractAddress);
|
||||
let createLogEvent: CreateContractEvent;
|
||||
switch (eventName) {
|
||||
case ExchangeEvents.LogFill:
|
||||
@@ -565,13 +600,21 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
return eventEmitter;
|
||||
}
|
||||
/**
|
||||
* Returns the ethereum address of the current exchange contract
|
||||
* Returns the ethereum addresses of all available exchange contracts
|
||||
* on the network that the provided web3 instance is connected to
|
||||
* @return The ethereum address of the current exchange contract.
|
||||
* @return The ethereum addresses of all available exchange contract.
|
||||
*/
|
||||
public async getContractAddressAsync(): Promise<string> {
|
||||
const exchangeContract = await this._getExchangeContractAsync();
|
||||
return exchangeContract.address;
|
||||
public async getAvailableContractAddressedAsync(): Promise<string[]> {
|
||||
const networkId = await this._web3Wrapper.getNetworkIdIfExistsAsync();
|
||||
if (_.isUndefined(networkId)) {
|
||||
return [];
|
||||
} else {
|
||||
const exchangeAddresses = _.map(
|
||||
_.values(ExchangeArtifactsByName),
|
||||
exchangeArfifact => exchangeArfifact.networks[networkId].address,
|
||||
);
|
||||
return exchangeAddresses;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Stops watching for all exchange events
|
||||
@@ -592,12 +635,13 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
return zeroExEvent;
|
||||
}
|
||||
private async _isValidSignatureUsingContractCallAsync(dataHex: string, ecSignature: ECSignature,
|
||||
signerAddressHex: string): Promise<boolean> {
|
||||
signerAddressHex: string,
|
||||
exchangeContractAddress: string): Promise<boolean> {
|
||||
assert.isHexString('dataHex', dataHex);
|
||||
assert.doesConformToSchema('ecSignature', ecSignature, ecSignatureSchema);
|
||||
assert.isETHAddressHex('signerAddressHex', signerAddressHex);
|
||||
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress);
|
||||
|
||||
const isValidSignature = await exchangeInstance.isValidSignature.call(
|
||||
signerAddressHex,
|
||||
@@ -609,12 +653,12 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
return isValidSignature;
|
||||
}
|
||||
private async _getOrderHashHexAsync(order: Order|SignedOrder): Promise<string> {
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(order.exchangeContractAddress);
|
||||
const orderHashHex = utils.getOrderHashHex(order, exchangeInstance.address);
|
||||
return orderHashHex;
|
||||
}
|
||||
private async _getOrderHashHexUsingContractCallAsync(order: Order|SignedOrder): Promise<string> {
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(order.exchangeContractAddress);
|
||||
const [orderAddresses, orderValues] = ExchangeWrapper._getOrderAddressesAndValues(order);
|
||||
const orderHashHex = await exchangeInstance.getOrderHash.call(orderAddresses, orderValues);
|
||||
return orderHashHex;
|
||||
@@ -632,12 +676,13 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
if (signedOrder.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
|
||||
throw new Error(ExchangeContractErrs.ORDER_FILL_EXPIRED);
|
||||
}
|
||||
const zrxTokenAddress = await this._getZRXTokenAddressAsync();
|
||||
const zrxTokenAddress = await this._getZRXTokenAddressAsync(signedOrder.exchangeContractAddress);
|
||||
await this._validateFillOrderBalancesAndAllowancesAndThrowIfInvalidAsync(signedOrder, fillTakerAmount,
|
||||
senderAddress, zrxTokenAddress);
|
||||
|
||||
const wouldRoundingErrorOccur = await this._isRoundingErrorAsync(
|
||||
signedOrder.takerTokenAmount, fillTakerAmount, signedOrder.makerTokenAmount,
|
||||
signedOrder.exchangeContractAddress,
|
||||
);
|
||||
if (wouldRoundingErrorOccur) {
|
||||
throw new Error(ExchangeContractErrs.ORDER_FILL_ROUNDING_ERROR);
|
||||
@@ -649,7 +694,7 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
throw new Error(ExchangeContractErrs.ORDER_CANCEL_AMOUNT_ZERO);
|
||||
}
|
||||
const orderHash = await this._getOrderHashHexAsync(order);
|
||||
const unavailableAmount = await this.getUnavailableTakerAmountAsync(orderHash);
|
||||
const unavailableAmount = await this.getUnavailableTakerAmountAsync(orderHash, order.exchangeContractAddress);
|
||||
if (order.takerTokenAmount.minus(unavailableAmount).eq(0)) {
|
||||
throw new Error(ExchangeContractErrs.ORDER_ALREADY_CANCELLED_OR_FILLED);
|
||||
}
|
||||
@@ -659,11 +704,11 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
}
|
||||
}
|
||||
private async _validateFillOrKillOrderAndThrowIfInvalidAsync(signedOrder: SignedOrder,
|
||||
exchangeAddress: string,
|
||||
exchangeContractAddress: string,
|
||||
fillTakerAmount: BigNumber.BigNumber) {
|
||||
// Check that fillValue available >= fillTakerAmount
|
||||
const orderHashHex = utils.getOrderHashHex(signedOrder, exchangeAddress);
|
||||
const unavailableTakerAmount = await this.getUnavailableTakerAmountAsync(orderHashHex);
|
||||
const orderHashHex = utils.getOrderHashHex(signedOrder, exchangeContractAddress);
|
||||
const unavailableTakerAmount = await this.getUnavailableTakerAmountAsync(orderHashHex, exchangeContractAddress);
|
||||
const remainingTakerAmount = signedOrder.takerTokenAmount.minus(unavailableTakerAmount);
|
||||
if (remainingTakerAmount < fillTakerAmount) {
|
||||
throw new Error(ExchangeContractErrs.INSUFFICIENT_REMAINING_FILL_AMOUNT);
|
||||
@@ -740,24 +785,38 @@ export class ExchangeWrapper extends ContractWrapper {
|
||||
}
|
||||
private async _isRoundingErrorAsync(takerTokenAmount: BigNumber.BigNumber,
|
||||
fillTakerAmount: BigNumber.BigNumber,
|
||||
makerTokenAmount: BigNumber.BigNumber): Promise<boolean> {
|
||||
makerTokenAmount: BigNumber.BigNumber,
|
||||
exchangeContractAddress: string): Promise<boolean> {
|
||||
await assert.isUserAddressAvailableAsync(this._web3Wrapper);
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress);
|
||||
const isRoundingError = await exchangeInstance.isRoundingError.call(
|
||||
takerTokenAmount, fillTakerAmount, makerTokenAmount,
|
||||
);
|
||||
return isRoundingError;
|
||||
}
|
||||
private async _getExchangeContractAsync(): Promise<ExchangeContract> {
|
||||
if (!_.isUndefined(this._exchangeContractIfExists)) {
|
||||
return this._exchangeContractIfExists;
|
||||
private async _getExchangeContractAsync(exchangeContractAddress: string): Promise<ExchangeContract> {
|
||||
if (!_.isUndefined(this._exchangeContractByAddress[exchangeContractAddress])) {
|
||||
return this._exchangeContractByAddress[exchangeContractAddress];
|
||||
}
|
||||
const ExchangeArtifacts = this._getExchangeArtifactsByAddressOrThrow(exchangeContractAddress);
|
||||
const contractInstance = await this._instantiateContractIfExistsAsync((ExchangeArtifacts as any));
|
||||
this._exchangeContractIfExists = contractInstance as ExchangeContract;
|
||||
return this._exchangeContractIfExists;
|
||||
this._exchangeContractByAddress[exchangeContractAddress] = contractInstance as ExchangeContract;
|
||||
return this._exchangeContractByAddress[exchangeContractAddress];
|
||||
}
|
||||
private async _getZRXTokenAddressAsync(): Promise<string> {
|
||||
const exchangeInstance = await this._getExchangeContractAsync();
|
||||
private _getExchangeArtifactsByAddressOrThrow(exchangeContractAddress: string): ContractArtifact {
|
||||
for (const exchangeArtifact of _.values<ContractArtifact>(ExchangeArtifactsByName)) {
|
||||
const exchangeAddressesInAftifact = _.map(
|
||||
_.values(exchangeArtifact.networks),
|
||||
artifactsByNetwork => artifactsByNetwork.address,
|
||||
);
|
||||
if (_.includes(exchangeAddressesInAftifact, exchangeContractAddress)) {
|
||||
return exchangeArtifact;
|
||||
}
|
||||
}
|
||||
throw new Error(ZeroExError.CONTRACT_DOES_NOT_EXIST);
|
||||
}
|
||||
private async _getZRXTokenAddressAsync(exchangeContractAddress: string): Promise<string> {
|
||||
const exchangeInstance = await this._getExchangeContractAsync(exchangeContractAddress);
|
||||
return exchangeInstance.ZRX.call();
|
||||
}
|
||||
}
|
||||
|
||||
6
src/exchange_artifacts_by_name.ts
Normal file
6
src/exchange_artifacts_by_name.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import {ContractArtifact} from './types';
|
||||
import * as Exchange_v1 from './artifacts/exchange/Exchange.json';
|
||||
|
||||
export const ExchangeArtifactsByName = {
|
||||
Exchange_v1: Exchange_v1 as any as ContractArtifact,
|
||||
};
|
||||
13
src/types.ts
13
src/types.ts
@@ -240,6 +240,7 @@ export interface Order {
|
||||
makerTokenAddress: string;
|
||||
takerTokenAddress: string;
|
||||
salt: BigNumber.BigNumber;
|
||||
exchangeContractAddress: string;
|
||||
feeRecipient: string;
|
||||
expirationUnixTimestampSec: BigNumber.BigNumber;
|
||||
}
|
||||
@@ -325,3 +326,15 @@ export interface ContractEventEmitter {
|
||||
* It is however a `Web3` library type, not a native `0x.js` type.
|
||||
*/
|
||||
export type Web3Provider = Web3.Provider;
|
||||
|
||||
export interface ExchangeContractByAddress {
|
||||
[address: string]: ExchangeContract;
|
||||
}
|
||||
|
||||
export interface ContractArtifact {
|
||||
networks: {
|
||||
[networkId: number]: {
|
||||
address: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,10 +16,11 @@ describe('ZeroEx library', () => {
|
||||
it('overrides provider in nested web3s and invalidates contractInstances', async () => {
|
||||
const web3 = web3Factory.create();
|
||||
const zeroEx = new ZeroEx(web3.currentProvider);
|
||||
const [exchangeContractAddress] = await zeroEx.exchange.getAvailableContractAddressedAsync();
|
||||
// Instantiate the contract instances with the current provider
|
||||
await (zeroEx.exchange as any)._getExchangeContractAsync();
|
||||
await (zeroEx.exchange as any)._getExchangeContractAsync(exchangeContractAddress);
|
||||
await (zeroEx.tokenRegistry as any)._getTokenRegistryContractAsync();
|
||||
expect((zeroEx.exchange as any)._exchangeContractIfExists).to.not.be.undefined();
|
||||
expect((zeroEx.exchange as any)._exchangeContractByAddress[exchangeContractAddress]).to.not.be.undefined();
|
||||
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.not.be.undefined();
|
||||
|
||||
const newProvider = web3Factory.getRpcProvider();
|
||||
@@ -28,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)._exchangeContractIfExists).to.be.undefined();
|
||||
expect((zeroEx.exchange as any)._exchangeContractByAddress[exchangeContractAddress]).to.be.undefined();
|
||||
expect((zeroEx.tokenRegistry as any)._tokenRegistryContractIfExists).to.be.undefined();
|
||||
|
||||
// Check that all nested web3 instances return the updated provider
|
||||
@@ -52,6 +53,10 @@ describe('ZeroEx library', () => {
|
||||
const address = '0x5409ed021d9299bf6814279a6a1411a7e866a631';
|
||||
const web3 = web3Factory.create();
|
||||
const zeroEx = new ZeroEx(web3.currentProvider);
|
||||
let exchangeContractAddress: string;
|
||||
before(async () => {
|
||||
[exchangeContractAddress] = await zeroEx.exchange.getAvailableContractAddressedAsync();
|
||||
});
|
||||
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(
|
||||
@@ -77,7 +82,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);
|
||||
._isValidSignatureUsingContractCallAsync(dataHex, signature, address, exchangeContractAddress);
|
||||
return expect(isValidSignatureOnContract).to.be.true();
|
||||
});
|
||||
});
|
||||
@@ -126,14 +131,15 @@ describe('ZeroEx library', () => {
|
||||
});
|
||||
});
|
||||
describe('#getOrderHashHexAsync', () => {
|
||||
const exchangeContractAddress = constants.NULL_ADDRESS;
|
||||
const expectedOrderHash = '0x103a5e97dab5dbeb8f385636f86a7d1e458a7ccbe1bd194727f0b2f85ab116c7';
|
||||
const expectedOrderHash = '0x39da987067a3c9e5f1617694f1301326ba8c8b0498ebef5df4863bed394e3c83';
|
||||
const exchangeContractAddress = '0xb69e673309512a9d726f87304c6984054f87a93b';
|
||||
const order: Order = {
|
||||
maker: constants.NULL_ADDRESS,
|
||||
taker: constants.NULL_ADDRESS,
|
||||
feeRecipient: constants.NULL_ADDRESS,
|
||||
makerTokenAddress: constants.NULL_ADDRESS,
|
||||
takerTokenAddress: constants.NULL_ADDRESS,
|
||||
exchangeContractAddress,
|
||||
salt: new BigNumber(0),
|
||||
makerFee: new BigNumber(0),
|
||||
takerFee: new BigNumber(0),
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import * as fs from 'fs';
|
||||
import * as chai from 'chai';
|
||||
import {chaiSetup} from './utils/chai_setup';
|
||||
import HDWalletProvider = require('truffle-hdwallet-provider');
|
||||
import {ZeroEx} from '../src';
|
||||
import {web3Factory} from './utils/web3_factory';
|
||||
import {constants} from './utils/constants';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
|
||||
// Those tests are slower cause they're talking to a remote node
|
||||
const TIMEOUT = 10000;
|
||||
|
||||
@@ -22,7 +27,8 @@ describe('Artifacts', () => {
|
||||
await (zeroEx.token as any)._getProxyAddressAsync();
|
||||
}).timeout(TIMEOUT);
|
||||
it('exchange contract is deployed', async () => {
|
||||
await (zeroEx.exchange as any)._getExchangeContractAsync();
|
||||
const exchangeContractAddresses = await zeroEx.exchange.getAvailableContractAddressedAsync();
|
||||
expect(exchangeContractAddresses).to.have.lengthOf.above(0);
|
||||
}).timeout(TIMEOUT);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'mocha';
|
||||
import * as _ from 'lodash';
|
||||
import * as chai from 'chai';
|
||||
import * as Web3 from 'web3';
|
||||
import * as BigNumber from 'bignumber.js';
|
||||
@@ -37,14 +38,16 @@ describe('ExchangeWrapper', () => {
|
||||
let userAddresses: string[];
|
||||
let zrxTokenAddress: string;
|
||||
let fillScenarios: FillScenarios;
|
||||
let exchangeContractAddress: string;
|
||||
before(async () => {
|
||||
web3 = web3Factory.create();
|
||||
zeroEx = new ZeroEx(web3.currentProvider);
|
||||
[exchangeContractAddress] = await zeroEx.exchange.getAvailableContractAddressedAsync();
|
||||
userAddresses = await promisify(web3.eth.getAccounts)();
|
||||
tokens = await zeroEx.tokenRegistry.getTokensAsync();
|
||||
tokenUtils = new TokenUtils(tokens);
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenOrThrow().address;
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress);
|
||||
fillScenarios = new FillScenarios(zeroEx, userAddresses, tokens, zrxTokenAddress, exchangeContractAddress);
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
@@ -413,8 +416,12 @@ describe('ExchangeWrapper', () => {
|
||||
});
|
||||
it('should successfully fill multiple orders', async () => {
|
||||
await zeroEx.exchange.batchFillOrderAsync(orderFillBatch, shouldCheckTransfer, takerAddress);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(
|
||||
signedOrderHashHex, exchangeContractAddress,
|
||||
);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(
|
||||
anotherOrderHashHex, exchangeContractAddress,
|
||||
);
|
||||
expect(filledAmount).to.be.bignumber.equal(fillTakerAmount);
|
||||
expect(anotherFilledAmount).to.be.bignumber.equal(fillTakerAmount);
|
||||
});
|
||||
@@ -446,8 +453,12 @@ describe('ExchangeWrapper', () => {
|
||||
await zeroEx.exchange.fillOrdersUpToAsync(
|
||||
signedOrders, fillUpToAmount, shouldCheckTransfer, takerAddress,
|
||||
);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(signedOrderHashHex);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(anotherOrderHashHex);
|
||||
const filledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(
|
||||
signedOrderHashHex, exchangeContractAddress,
|
||||
);
|
||||
const anotherFilledAmount = await zeroEx.exchange.getFilledTakerAmountAsync(
|
||||
anotherOrderHashHex, exchangeContractAddress,
|
||||
);
|
||||
expect(filledAmount).to.be.bignumber.equal(fillableAmount);
|
||||
const remainingFillAmount = fillableAmount.minus(1);
|
||||
expect(anotherFilledAmount).to.be.bignumber.equal(remainingFillAmount);
|
||||
@@ -507,7 +518,9 @@ describe('ExchangeWrapper', () => {
|
||||
describe('successful cancels', () => {
|
||||
it('should cancel an order', async () => {
|
||||
await zeroEx.exchange.cancelOrderAsync(signedOrder, cancelAmount);
|
||||
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex);
|
||||
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(
|
||||
orderHashHex, exchangeContractAddress,
|
||||
);
|
||||
expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
|
||||
});
|
||||
it('should return cancelled amount', async () => {
|
||||
@@ -553,9 +566,12 @@ describe('ExchangeWrapper', () => {
|
||||
describe('successful batch cancels', () => {
|
||||
it('should cancel a batch of orders', async () => {
|
||||
await zeroEx.exchange.batchCancelOrderAsync(cancelBatch);
|
||||
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(orderHashHex);
|
||||
const cancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(
|
||||
orderHashHex, exchangeContractAddress,
|
||||
);
|
||||
const anotherCancelledAmount = await zeroEx.exchange.getCanceledTakerAmountAsync(
|
||||
anotherOrderHashHex);
|
||||
anotherOrderHashHex, exchangeContractAddress,
|
||||
);
|
||||
expect(cancelledAmount).to.be.bignumber.equal(cancelAmount);
|
||||
expect(anotherCancelledAmount).to.be.bignumber.equal(cancelAmount);
|
||||
});
|
||||
@@ -587,48 +603,68 @@ describe('ExchangeWrapper', () => {
|
||||
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(zeroEx.exchange.getUnavailableTakerAmountAsync(
|
||||
invalidOrderHashHex, exchangeContractAddress,
|
||||
)).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 zeroEx.exchange.getUnavailableTakerAmountAsync(
|
||||
NON_EXISTENT_ORDER_HASH, exchangeContractAddress,
|
||||
);
|
||||
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 zeroEx.exchange.getUnavailableTakerAmountAsync(
|
||||
orderHash, exchangeContractAddress,
|
||||
);
|
||||
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(zeroEx.exchange.getFilledTakerAmountAsync(
|
||||
invalidOrderHashHex, exchangeContractAddress,
|
||||
)).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 zeroEx.exchange.getFilledTakerAmountAsync(
|
||||
NON_EXISTENT_ORDER_HASH, exchangeContractAddress,
|
||||
);
|
||||
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 zeroEx.exchange.getFilledTakerAmountAsync(
|
||||
orderHash, exchangeContractAddress,
|
||||
);
|
||||
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)).to.be.rejected();
|
||||
return expect(zeroEx.exchange.getCanceledTakerAmountAsync(
|
||||
invalidOrderHashHex, exchangeContractAddress,
|
||||
)).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);
|
||||
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(
|
||||
NON_EXISTENT_ORDER_HASH, exchangeContractAddress,
|
||||
);
|
||||
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);
|
||||
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(
|
||||
orderHash, exchangeContractAddress,
|
||||
);
|
||||
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);
|
||||
const cancelledValueT = await zeroEx.exchange.getCanceledTakerAmountAsync(
|
||||
orderHash, exchangeContractAddress,
|
||||
);
|
||||
expect(cancelledValueT).to.be.bignumber.equal(cancelAmount);
|
||||
});
|
||||
});
|
||||
@@ -669,8 +705,9 @@ describe('ExchangeWrapper', () => {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest',
|
||||
};
|
||||
const zeroExEvent = await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogFill, subscriptionOpts,
|
||||
indexFilterValues);
|
||||
const zeroExEvent = await zeroEx.exchange.subscribeAsync(
|
||||
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, exchangeContractAddress,
|
||||
);
|
||||
zeroExEvent.watch((err: Error, event: ContractEvent) => {
|
||||
expect(err).to.be.null();
|
||||
expect(event).to.not.be.undefined();
|
||||
@@ -688,8 +725,9 @@ describe('ExchangeWrapper', () => {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest',
|
||||
};
|
||||
const zeroExEvent = await zeroEx.exchange.subscribeAsync(ExchangeEvents.LogCancel, subscriptionOpts,
|
||||
indexFilterValues);
|
||||
const zeroExEvent = await zeroEx.exchange.subscribeAsync(
|
||||
ExchangeEvents.LogCancel, subscriptionOpts, indexFilterValues, exchangeContractAddress,
|
||||
);
|
||||
zeroExEvent.watch((err: Error, event: ContractEvent) => {
|
||||
expect(err).to.be.null();
|
||||
expect(event).to.not.be.undefined();
|
||||
@@ -706,7 +744,7 @@ describe('ExchangeWrapper', () => {
|
||||
toBlock: 'latest',
|
||||
};
|
||||
const eventSubscriptionToBeCancelled = await zeroEx.exchange.subscribeAsync(
|
||||
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues,
|
||||
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, exchangeContractAddress,
|
||||
);
|
||||
eventSubscriptionToBeCancelled.watch((err: Error, event: ContractEvent) => {
|
||||
done(new Error('Expected this subscription to have been cancelled'));
|
||||
@@ -716,7 +754,7 @@ describe('ExchangeWrapper', () => {
|
||||
await zeroEx.setProviderAsync(newProvider);
|
||||
|
||||
const eventSubscriptionToStay = await zeroEx.exchange.subscribeAsync(
|
||||
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues,
|
||||
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, exchangeContractAddress,
|
||||
);
|
||||
eventSubscriptionToStay.watch((err: Error, event: ContractEvent) => {
|
||||
expect(err).to.be.null();
|
||||
@@ -737,7 +775,7 @@ describe('ExchangeWrapper', () => {
|
||||
toBlock: 'latest',
|
||||
};
|
||||
const eventSubscriptionToBeStopped = await zeroEx.exchange.subscribeAsync(
|
||||
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues,
|
||||
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues, exchangeContractAddress,
|
||||
);
|
||||
eventSubscriptionToBeStopped.watch((err: Error, event: ContractEvent) => {
|
||||
done(new Error('Expected this subscription to have been stopped'));
|
||||
@@ -773,10 +811,12 @@ describe('ExchangeWrapper', () => {
|
||||
expect(orderHash).to.equal(orderHashFromContract);
|
||||
});
|
||||
});
|
||||
describe('#getContractAddressAsync', () => {
|
||||
it('returns the exchange contract address', async () => {
|
||||
const exchangeAddress = await zeroEx.exchange.getContractAddressAsync();
|
||||
assert.isETHAddressHex('exchangeAddress', exchangeAddress);
|
||||
describe('#getAvailableContractAddressedAsync', () => {
|
||||
it('returns the exchange contract addresses', async () => {
|
||||
const exchangeAddresses = await zeroEx.exchange.getAvailableContractAddressedAsync();
|
||||
_.map(exchangeAddresses, exchangeAddress => {
|
||||
assert.isETHAddressHex('exchangeAddress', exchangeAddress);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,12 +9,15 @@ export class FillScenarios {
|
||||
private tokens: Token[];
|
||||
private coinbase: string;
|
||||
private zrxTokenAddress: string;
|
||||
constructor(zeroEx: ZeroEx, userAddresses: string[], tokens: Token[], zrxTokenAddress: string) {
|
||||
private exchangeContractAddress: string;
|
||||
constructor(zeroEx: ZeroEx, userAddresses: string[],
|
||||
tokens: Token[], zrxTokenAddress: string, exchangeContractAddress: string) {
|
||||
this.zeroEx = zeroEx;
|
||||
this.userAddresses = userAddresses;
|
||||
this.tokens = tokens;
|
||||
this.coinbase = userAddresses[0];
|
||||
this.zrxTokenAddress = zrxTokenAddress;
|
||||
this.exchangeContractAddress = exchangeContractAddress;
|
||||
}
|
||||
public async createFillableSignedOrderAsync(makerTokenAddress: string, takerTokenAddress: string,
|
||||
makerAddress: string, takerAddress: string,
|
||||
@@ -103,7 +106,7 @@ export class FillScenarios {
|
||||
const signedOrder = await orderFactory.createSignedOrderAsync(this.zeroEx,
|
||||
makerAddress, takerAddress, makerFee, takerFee,
|
||||
makerFillableAmount, makerTokenAddress, takerFillableAmount, takerTokenAddress,
|
||||
feeRecepient, expirationUnixTimestampSec);
|
||||
this.exchangeContractAddress, feeRecepient, expirationUnixTimestampSec);
|
||||
return signedOrder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ export const orderFactory = {
|
||||
makerTokenAddress: string,
|
||||
takerTokenAmount: BigNumber.BigNumber,
|
||||
takerTokenAddress: string,
|
||||
exchangeContractAddress: string,
|
||||
feeRecipient: string,
|
||||
expirationUnixTimestampSec?: BigNumber.BigNumber): Promise<SignedOrder> {
|
||||
const defaultExpirationUnixTimestampSec = new BigNumber(2524604400); // Close to infinite
|
||||
@@ -29,6 +30,7 @@ export const orderFactory = {
|
||||
makerTokenAddress,
|
||||
takerTokenAddress,
|
||||
salt: ZeroEx.generatePseudoRandomSalt(),
|
||||
exchangeContractAddress,
|
||||
feeRecipient,
|
||||
expirationUnixTimestampSec,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user