Navigation Menu

Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

Add getOrdersInfo function #857

Merged
merged 3 commits into from Jul 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -154,6 +154,9 @@ contract MixinExchangeCore is
// Compute the order hash
orderInfo.orderHash = getOrderHash(order);

// Fetch filled amount
orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash];

// If order.makerAssetAmount is zero, we also reject the order.
// While the Exchange contract handles them correctly, they create
// edge cases in the supporting infrastructure because they have
Expand All @@ -172,6 +175,12 @@ contract MixinExchangeCore is
return orderInfo;
}

// Validate order availability
if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) {
orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED);
return orderInfo;
}

// Validate order expiration
// solhint-disable-next-line not-rely-on-time
if (block.timestamp >= order.expirationTimeSeconds) {
Expand All @@ -189,13 +198,6 @@ contract MixinExchangeCore is
return orderInfo;
}

// Fetch filled amount and validate order availability
orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash];
if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) {
orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED);
return orderInfo;
}

// All other statuses are ruled out: order is Fillable
orderInfo.orderStatus = uint8(OrderStatus.FILLABLE);
return orderInfo;
Expand Down
Expand Up @@ -529,4 +529,20 @@ contract MixinWrapperFunctions is
cancelOrder(orders[i]);
}
}

/// @dev Fetches information for all passed in orders.
/// @param orders Array of order specifications.
/// @return Array of OrderInfo instances that correspond to each order.
function getOrdersInfo(LibOrder.Order[] memory orders)
public
view
returns (LibOrder.OrderInfo[] memory)
{
uint256 length = orders.length;
LibOrder.OrderInfo[] memory ordersInfo = new LibOrder.OrderInfo[](length);
for (uint256 i = 0; i < length; i++) {
ordersInfo[i] = getOrderInfo(orders[i]);
}
return ordersInfo;
}
}
Expand Up @@ -149,4 +149,12 @@ contract IWrapperFunctions {
/// @param orders Array of order specifications.
function batchCancelOrders(LibOrder.Order[] memory orders)
public;

/// @dev Fetches information for all passed in orders
/// @param orders Array of order specifications.
/// @return Array of OrderInfo instances that correspond to each order.
function getOrdersInfo(LibOrder.Order[] memory orders)
public
view
returns (LibOrder.OrderInfo[] memory);
}
122 changes: 120 additions & 2 deletions packages/contracts/test/exchange/core.ts
Expand Up @@ -15,14 +15,14 @@ import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_pr
import { ExchangeCancelEventArgs, ExchangeContract } from '../../generated_contract_wrappers/exchange';
import { artifacts } from '../utils/artifacts';
import { expectTransactionFailedAsync } from '../utils/assertions';
import { getLatestBlockTimestampAsync } from '../utils/block_timestamp';
import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp';
import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { OrderFactory } from '../utils/order_factory';
import { ERC20BalancesByOwner } from '../utils/types';
import { ERC20BalancesByOwner, OrderStatus } from '../utils/types';
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';

chaiSetup.configure();
Expand Down Expand Up @@ -483,6 +483,124 @@ describe('Exchange core', () => {
);
});
});

describe('getOrderInfo', () => {
beforeEach(async () => {
signedOrder = await orderFactory.newSignedOrderAsync();
});
it('should return the correct orderInfo for an unfilled valid order', async () => {
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.FILLABLE;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for a fully filled order', async () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount;
const expectedOrderStatus = OrderStatus.FULLY_FILLED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for a partially filled order', async () => {
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = takerAssetFillAmount;
const expectedOrderStatus = OrderStatus.FILLABLE;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for a cancelled and unfilled order', async () => {
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.CANCELLED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for a cancelled and partially filled order', async () => {
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = takerAssetFillAmount;
const expectedOrderStatus = OrderStatus.CANCELLED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an expired and unfilled order', async () => {
const currentTimestamp = await getLatestBlockTimestampAsync();
const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber();
await increaseTimeAndMineBlockAsync(timeUntilExpiration);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.EXPIRED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an expired and partially filled order', async () => {
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
const currentTimestamp = await getLatestBlockTimestampAsync();
const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber();
await increaseTimeAndMineBlockAsync(timeUntilExpiration);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = takerAssetFillAmount;
const expectedOrderStatus = OrderStatus.EXPIRED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an expired and fully filled order', async () => {
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
const currentTimestamp = await getLatestBlockTimestampAsync();
const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber();
await increaseTimeAndMineBlockAsync(timeUntilExpiration);
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount;
// FULLY_FILLED takes precedence over EXPIRED
const expectedOrderStatus = OrderStatus.FULLY_FILLED;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an order with a makerAssetAmount of 0', async () => {
signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(0) });
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.INVALID_MAKER_ASSET_AMOUNT;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
it('should return the correct orderInfo for an order with a takerAssetAmount of 0', async () => {
signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(0) });
const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder);
const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
const expectedTakerAssetFilledAmount = new BigNumber(0);
const expectedOrderStatus = OrderStatus.INVALID_TAKER_ASSET_AMOUNT;
expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
});
});
});
// tslint:disable:max-file-line-count
// tslint:enable:no-unnecessary-type-assertion