Remaining refactors of order-utils components for V2
This commit is contained in:
@@ -3,5 +3,5 @@ import { BigNumber } from '@0xproject/utils';
|
||||
export abstract class AbstractOrderFilledCancelledFetcher {
|
||||
public abstract async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>;
|
||||
public abstract async isOrderCancelledAsync(orderHash: string): Promise<boolean>;
|
||||
public abstract getZRXTokenAddress(): string;
|
||||
public abstract getZRXAssetData(): string;
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ export { generatePseudoRandomSalt } from './salt';
|
||||
export { OrderError, MessagePrefixType, MessagePrefixOpts } from './types';
|
||||
export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
|
||||
export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
|
||||
export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store';
|
||||
export { RemainingFillableCalculator } from './remaining_fillable_calculator';
|
||||
export { OrderStateUtils } from './order_state_utils';
|
||||
export { assetProxyUtils } from './asset_proxy_utils';
|
||||
|
@@ -5,15 +5,15 @@ import * as _ from 'lodash';
|
||||
|
||||
import { OrderError, TradeSide, TransferType } from './types';
|
||||
|
||||
import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
|
||||
import { constants } from './constants';
|
||||
import { ExchangeTransferSimulator } from './exchange_transfer_simulator';
|
||||
import { ExchangeContract } from './generated_contract_wrappers/exchange';
|
||||
import { orderHashUtils } from './order_hash';
|
||||
import { isValidSignatureAsync } from './signature_utils';
|
||||
import { utils } from './utils';
|
||||
|
||||
export class OrderValidationUtils {
|
||||
private _exchangeContract: ExchangeContract;
|
||||
private _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher;
|
||||
public static isRoundingError(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean {
|
||||
// Solidity's mulmod() in JS
|
||||
// Source: https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#mathematical-and-cryptographic-functions
|
||||
@@ -50,12 +50,12 @@ export class OrderValidationUtils {
|
||||
public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
fillTakerAssetAmount: BigNumber,
|
||||
senderAddress: string,
|
||||
zrxTokenAddress: string,
|
||||
zrxAssetData: string,
|
||||
): Promise<void> {
|
||||
const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount(
|
||||
fillTakerTokenAmount,
|
||||
fillTakerAssetAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.makerAssetAmount,
|
||||
);
|
||||
@@ -71,17 +71,17 @@ export class OrderValidationUtils {
|
||||
signedOrder.takerAssetData,
|
||||
senderAddress,
|
||||
signedOrder.makerAddress,
|
||||
fillTakerTokenAmount,
|
||||
fillTakerAssetAmount,
|
||||
TradeSide.Taker,
|
||||
TransferType.Trade,
|
||||
);
|
||||
const makerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||
fillTakerTokenAmount,
|
||||
fillTakerAssetAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.makerFee,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
zrxTokenAddress,
|
||||
zrxAssetData,
|
||||
signedOrder.makerAddress,
|
||||
signedOrder.feeRecipientAddress,
|
||||
makerFeeAmount,
|
||||
@@ -89,12 +89,12 @@ export class OrderValidationUtils {
|
||||
TransferType.Fee,
|
||||
);
|
||||
const takerFeeAmount = OrderValidationUtils._getPartialAmount(
|
||||
fillTakerTokenAmount,
|
||||
fillTakerAssetAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.takerFee,
|
||||
);
|
||||
await exchangeTradeEmulator.transferFromAsync(
|
||||
zrxTokenAddress,
|
||||
zrxAssetData,
|
||||
senderAddress,
|
||||
signedOrder.feeRecipientAddress,
|
||||
takerFeeAmount,
|
||||
@@ -123,43 +123,43 @@ export class OrderValidationUtils {
|
||||
.round(0);
|
||||
return fillMakerTokenAmount;
|
||||
}
|
||||
constructor(exchangeContract: ExchangeContract) {
|
||||
this._exchangeContract = exchangeContract;
|
||||
constructor(orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher) {
|
||||
this._orderFilledCancelledFetcher = orderFilledCancelledFetcher;
|
||||
}
|
||||
public async validateOrderFillableOrThrowAsync(
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||
signedOrder: SignedOrder,
|
||||
zrxTokenAddress: string,
|
||||
zrxAssetData: string,
|
||||
expectedFillTakerTokenAmount?: BigNumber,
|
||||
): Promise<void> {
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const filledTakerTokenAmount = await this._exchangeContract.filled.callAsync(orderHash);
|
||||
const filledTakerTokenAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||
signedOrder.takerAssetAmount,
|
||||
filledTakerTokenAmount,
|
||||
);
|
||||
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds);
|
||||
let fillTakerTokenAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount);
|
||||
let fillTakerAssetAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount);
|
||||
if (!_.isUndefined(expectedFillTakerTokenAmount)) {
|
||||
fillTakerTokenAmount = expectedFillTakerTokenAmount;
|
||||
fillTakerAssetAmount = expectedFillTakerTokenAmount;
|
||||
}
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
fillTakerAssetAmount,
|
||||
signedOrder.takerAddress,
|
||||
zrxTokenAddress,
|
||||
zrxAssetData,
|
||||
);
|
||||
}
|
||||
public async validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||
provider: Provider,
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
fillTakerAssetAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
zrxTokenAddress: string,
|
||||
zrxAssetData: string,
|
||||
): Promise<BigNumber> {
|
||||
if (fillTakerTokenAmount.eq(0)) {
|
||||
if (fillTakerAssetAmount.eq(0)) {
|
||||
throw new Error(ExchangeContractErrs.OrderFillAmountZero);
|
||||
}
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
@@ -172,7 +172,7 @@ export class OrderValidationUtils {
|
||||
if (!isValid) {
|
||||
throw new Error(OrderError.InvalidSignature);
|
||||
}
|
||||
const filledTakerTokenAmount = await this._exchangeContract.filled.callAsync(orderHash);
|
||||
const filledTakerTokenAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash);
|
||||
OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow(
|
||||
signedOrder.takerAssetAmount,
|
||||
filledTakerTokenAmount,
|
||||
@@ -182,19 +182,19 @@ export class OrderValidationUtils {
|
||||
}
|
||||
OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds);
|
||||
const remainingTakerTokenAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount);
|
||||
const desiredFillTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount)
|
||||
const desiredFillTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerAssetAmount)
|
||||
? remainingTakerTokenAmount
|
||||
: fillTakerTokenAmount;
|
||||
: fillTakerAssetAmount;
|
||||
await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator,
|
||||
signedOrder,
|
||||
desiredFillTakerTokenAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
zrxAssetData,
|
||||
);
|
||||
|
||||
const wouldRoundingErrorOccur = OrderValidationUtils.isRoundingError(
|
||||
filledTakerTokenAmount,
|
||||
desiredFillTakerTokenAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.makerAssetAmount,
|
||||
);
|
||||
@@ -207,19 +207,19 @@ export class OrderValidationUtils {
|
||||
exchangeTradeEmulator: ExchangeTransferSimulator,
|
||||
provider: Provider,
|
||||
signedOrder: SignedOrder,
|
||||
fillTakerTokenAmount: BigNumber,
|
||||
fillTakerAssetAmount: BigNumber,
|
||||
takerAddress: string,
|
||||
zrxTokenAddress: string,
|
||||
zrxAssetData: string,
|
||||
): Promise<void> {
|
||||
const filledTakerTokenAmount = await this.validateFillOrderThrowIfInvalidAsync(
|
||||
exchangeTradeEmulator,
|
||||
provider,
|
||||
signedOrder,
|
||||
fillTakerTokenAmount,
|
||||
fillTakerAssetAmount,
|
||||
takerAddress,
|
||||
zrxTokenAddress,
|
||||
zrxAssetData,
|
||||
);
|
||||
if (filledTakerTokenAmount !== fillTakerTokenAmount) {
|
||||
if (filledTakerTokenAmount !== fillTakerAssetAmount) {
|
||||
throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount);
|
||||
}
|
||||
}
|
||||
|
@@ -19,8 +19,8 @@ export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProx
|
||||
[userAddress: string]: BigNumber;
|
||||
};
|
||||
};
|
||||
constructor(token: AbstractBalanceAndProxyAllowanceFetcher) {
|
||||
this._balanceAndProxyAllowanceFetcher = token;
|
||||
constructor(balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher) {
|
||||
this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher;
|
||||
this._balance = {};
|
||||
this._proxyAllowance = {};
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import * as chai from 'chai';
|
||||
import 'make-promises-safe';
|
||||
|
||||
import { artifacts } from '../src/artifacts';
|
||||
import { assetProxyUtils } from '../src/asset_proxy_utils';
|
||||
import { constants } from '../src/constants';
|
||||
import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator';
|
||||
import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_e_r_c20_token';
|
||||
@@ -28,7 +29,7 @@ describe('ExchangeTransferSimulator', async () => {
|
||||
let coinbase: string;
|
||||
let sender: string;
|
||||
let recipient: string;
|
||||
let exampleTokenAddress: string;
|
||||
let exampleAssetData: string;
|
||||
let exchangeTransferSimulator: ExchangeTransferSimulator;
|
||||
let txHash: string;
|
||||
let erc20ProxyAddress: string;
|
||||
@@ -66,7 +67,7 @@ describe('ExchangeTransferSimulator', async () => {
|
||||
totalSupply,
|
||||
);
|
||||
|
||||
exampleTokenAddress = dummyERC20Token.address;
|
||||
exampleAssetData = assetProxyUtils.encodeERC20AssetData(dummyERC20Token.address);
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
@@ -92,7 +93,7 @@ describe('ExchangeTransferSimulator', async () => {
|
||||
it("throws if the user doesn't have enough allowance", async () => {
|
||||
return expect(
|
||||
exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress,
|
||||
exampleAssetData,
|
||||
sender,
|
||||
recipient,
|
||||
transferAmount,
|
||||
@@ -108,7 +109,7 @@ describe('ExchangeTransferSimulator', async () => {
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
return expect(
|
||||
exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress,
|
||||
exampleAssetData,
|
||||
sender,
|
||||
recipient,
|
||||
transferAmount,
|
||||
@@ -129,7 +130,7 @@ describe('ExchangeTransferSimulator', async () => {
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
|
||||
await exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress,
|
||||
exampleAssetData,
|
||||
sender,
|
||||
recipient,
|
||||
transferAmount,
|
||||
@@ -137,9 +138,9 @@ describe('ExchangeTransferSimulator', async () => {
|
||||
TransferType.Trade,
|
||||
);
|
||||
const store = (exchangeTransferSimulator as any)._store;
|
||||
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
||||
const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
|
||||
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
|
||||
const senderBalance = await store.getBalanceAsync(exampleAssetData, sender);
|
||||
const recipientBalance = await store.getBalanceAsync(exampleAssetData, recipient);
|
||||
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleAssetData, sender);
|
||||
expect(senderBalance).to.be.bignumber.equal(0);
|
||||
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
|
||||
expect(senderProxyAllowance).to.be.bignumber.equal(0);
|
||||
@@ -158,7 +159,7 @@ describe('ExchangeTransferSimulator', async () => {
|
||||
);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
await exchangeTransferSimulator.transferFromAsync(
|
||||
exampleTokenAddress,
|
||||
exampleAssetData,
|
||||
sender,
|
||||
recipient,
|
||||
transferAmount,
|
||||
@@ -166,9 +167,9 @@ describe('ExchangeTransferSimulator', async () => {
|
||||
TransferType.Trade,
|
||||
);
|
||||
const store = (exchangeTransferSimulator as any)._store;
|
||||
const senderBalance = await store.getBalanceAsync(exampleTokenAddress, sender);
|
||||
const recipientBalance = await store.getBalanceAsync(exampleTokenAddress, recipient);
|
||||
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleTokenAddress, sender);
|
||||
const senderBalance = await store.getBalanceAsync(exampleAssetData, sender);
|
||||
const recipientBalance = await store.getBalanceAsync(exampleAssetData, recipient);
|
||||
const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleAssetData, sender);
|
||||
expect(senderBalance).to.be.bignumber.equal(0);
|
||||
expect(recipientBalance).to.be.bignumber.equal(transferAmount);
|
||||
expect(senderProxyAllowance).to.be.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
|
Reference in New Issue
Block a user