aboutsummaryrefslogtreecommitdiffstats
path: root/packages/0x.js
diff options
context:
space:
mode:
authorLeonid Logvinov <logvinov.leon@gmail.com>2017-11-23 05:43:17 +0800
committerLeonid Logvinov <logvinov.leon@gmail.com>2017-11-24 05:13:37 +0800
commitdb2917b01caa49d74c9ebcae2d36e9c3946b94d8 (patch)
tree88aa341cb4dc02f1bfbc7d0d00d21966e1bbde20 /packages/0x.js
parent87d34f9c7f3ccf22e01798c27c4a4d5d4f943816 (diff)
downloaddexon-sol-tools-db2917b01caa49d74c9ebcae2d36e9c3946b94d8.tar.gz
dexon-sol-tools-db2917b01caa49d74c9ebcae2d36e9c3946b94d8.tar.zst
dexon-sol-tools-db2917b01caa49d74c9ebcae2d36e9c3946b94d8.zip
Enable some new linter rules and fix the issues
Diffstat (limited to 'packages/0x.js')
-rw-r--r--packages/0x.js/src/contract_wrappers/exchange_wrapper.ts8
-rw-r--r--packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts30
-rw-r--r--packages/0x.js/src/order_watcher/order_state_watcher.ts2
-rw-r--r--packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts8
-rw-r--r--packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts4
-rw-r--r--packages/0x.js/src/subproviders/empty_wallet_subprovider.ts2
-rw-r--r--packages/0x.js/src/utils/abi_decoder.ts20
-rw-r--r--packages/0x.js/src/utils/exchange_transfer_simulator.ts14
-rw-r--r--packages/0x.js/src/utils/order_state_utils.ts68
-rw-r--r--packages/0x.js/src/utils/order_validation_utils.ts155
-rw-r--r--packages/0x.js/test/order_validation_test.ts10
11 files changed, 162 insertions, 159 deletions
diff --git a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts
index 97ea54362..b35219b24 100644
--- a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts
+++ b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts
@@ -559,7 +559,7 @@ export class ExchangeWrapper extends ContractWrapper {
if (shouldValidate) {
const orderHash = utils.getOrderHashHex(order);
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
- this._orderValidationUtils.validateCancelOrderThrowIfInvalid(
+ OrderValidationUtils.validateCancelOrderThrowIfInvalid(
order, cancelTakerTokenAmount, unavailableTakerTokenAmount);
}
@@ -613,7 +613,7 @@ export class ExchangeWrapper extends ContractWrapper {
for (const orderCancellationRequest of orderCancellationRequests) {
const orderHash = utils.getOrderHashHex(orderCancellationRequest.order);
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
- this._orderValidationUtils.validateCancelOrderThrowIfInvalid(
+ OrderValidationUtils.validateCancelOrderThrowIfInvalid(
orderCancellationRequest.order, orderCancellationRequest.takerTokenCancelAmount,
unavailableTakerTokenAmount,
);
@@ -767,7 +767,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount);
const orderHash = utils.getOrderHashHex(order);
const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash);
- this._orderValidationUtils.validateCancelOrderThrowIfInvalid(
+ OrderValidationUtils.validateCancelOrderThrowIfInvalid(
order, cancelTakerTokenAmount, unavailableTakerTokenAmount);
}
/**
@@ -884,4 +884,4 @@ export class ExchangeWrapper extends ContractWrapper {
const tokenTransferProxyAddressLowerCase = tokenTransferProxyAddress.toLowerCase();
return tokenTransferProxyAddressLowerCase;
}
-}
+} // tslint:disable:max-file-line-count
diff --git a/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts b/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts
index 60fe7f33a..468e58350 100644
--- a/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts
+++ b/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts
@@ -14,6 +14,18 @@ import {ContractWrapper} from './contract_wrapper';
export class TokenRegistryWrapper extends ContractWrapper {
private _tokenRegistryContractIfExists?: TokenRegistryContract;
private _contractAddressIfExists?: string;
+ private static _createTokenFromMetadata(metadata: TokenMetadata): Token|undefined {
+ if (metadata[0] === constants.NULL_ADDRESS) {
+ return undefined;
+ }
+ const token = {
+ address: metadata[0],
+ name: metadata[1],
+ symbol: metadata[2],
+ decimals: metadata[3].toNumber(),
+ };
+ return token;
+ }
constructor(web3Wrapper: Web3Wrapper, contractAddressIfExists?: string) {
super(web3Wrapper);
this._contractAddressIfExists = contractAddressIfExists;
@@ -51,7 +63,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const metadata = await tokenRegistryContract.getTokenMetaData.callAsync(address);
- const token = this._createTokenFromMetadata(metadata);
+ const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
return token;
}
public async getTokenAddressBySymbolIfExistsAsync(symbol: string): Promise<string|undefined> {
@@ -76,14 +88,14 @@ export class TokenRegistryWrapper extends ContractWrapper {
assert.isString('symbol', symbol);
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const metadata = await tokenRegistryContract.getTokenBySymbol.callAsync(symbol);
- const token = this._createTokenFromMetadata(metadata);
+ const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
return token;
}
public async getTokenByNameIfExistsAsync(name: string): Promise<Token|undefined> {
assert.isString('name', name);
const tokenRegistryContract = await this._getTokenRegistryContractAsync();
const metadata = await tokenRegistryContract.getTokenByName.callAsync(name);
- const token = this._createTokenFromMetadata(metadata);
+ const token = TokenRegistryWrapper._createTokenFromMetadata(metadata);
return token;
}
/**
@@ -103,18 +115,6 @@ export class TokenRegistryWrapper extends ContractWrapper {
return this._contractAddressIfExists;
}
}
- private _createTokenFromMetadata(metadata: TokenMetadata): Token|undefined {
- if (metadata[0] === constants.NULL_ADDRESS) {
- return undefined;
- }
- const token = {
- address: metadata[0],
- name: metadata[1],
- symbol: metadata[2],
- decimals: metadata[3].toNumber(),
- };
- return token;
- }
private _invalidateContractInstance(): void {
delete this._tokenRegistryContractIfExists;
}
diff --git a/packages/0x.js/src/order_watcher/order_state_watcher.ts b/packages/0x.js/src/order_watcher/order_state_watcher.ts
index 4d57935a1..919a58df7 100644
--- a/packages/0x.js/src/order_watcher/order_state_watcher.ts
+++ b/packages/0x.js/src/order_watcher/order_state_watcher.ts
@@ -38,7 +38,7 @@ import {ExpirationWatcher} from './expiration_watcher';
interface DependentOrderHashes {
[makerAddress: string]: {
- [makerToken: string]: Set<string>,
+ [makerToken: string]: Set<string>;
};
}
diff --git a/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts b/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts
index 293f75db9..afc40b86d 100644
--- a/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts
+++ b/packages/0x.js/src/stores/balance_proxy_allowance_lazy_store.ts
@@ -12,13 +12,13 @@ export class BalanceAndProxyAllowanceLazyStore {
private token: TokenWrapper;
private balance: {
[tokenAddress: string]: {
- [userAddress: string]: BigNumber,
- },
+ [userAddress: string]: BigNumber;
+ };
};
private proxyAllowance: {
[tokenAddress: string]: {
- [userAddress: string]: BigNumber,
- },
+ [userAddress: string]: BigNumber;
+ };
};
constructor(token: TokenWrapper) {
this.token = token;
diff --git a/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts b/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts
index 59c1bb7a7..28b32f9e2 100644
--- a/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts
+++ b/packages/0x.js/src/stores/order_filled_cancelled_lazy_store.ts
@@ -11,10 +11,10 @@ import {BlockParamLiteral} from '../types';
export class OrderFilledCancelledLazyStore {
private exchange: ExchangeWrapper;
private filledTakerAmount: {
- [orderHash: string]: BigNumber,
+ [orderHash: string]: BigNumber;
};
private cancelledTakerAmount: {
- [orderHash: string]: BigNumber,
+ [orderHash: string]: BigNumber;
};
constructor(exchange: ExchangeWrapper) {
this.exchange = exchange;
diff --git a/packages/0x.js/src/subproviders/empty_wallet_subprovider.ts b/packages/0x.js/src/subproviders/empty_wallet_subprovider.ts
index 2f260217c..d707d5652 100644
--- a/packages/0x.js/src/subproviders/empty_wallet_subprovider.ts
+++ b/packages/0x.js/src/subproviders/empty_wallet_subprovider.ts
@@ -6,6 +6,7 @@ import {JSONRPCPayload} from '../types';
* Source: https://github.com/MetaMask/provider-engine/blob/master/subproviders/subprovider.js
*/
export class EmptyWalletSubProvider {
+ // tslint:disable-next-line:prefer-function-over-method
public handleRequest(payload: JSONRPCPayload, next: () => void, end: (err: Error|null, result: any) => void) {
switch (payload.method) {
case 'eth_accounts':
@@ -18,6 +19,7 @@ export class EmptyWalletSubProvider {
}
}
// Required to implement this method despite not needing it for this subprovider
+ // tslint:disable-next-line:prefer-function-over-method
public setEngine(engine: any) {
// noop
}
diff --git a/packages/0x.js/src/utils/abi_decoder.ts b/packages/0x.js/src/utils/abi_decoder.ts
index f027026da..f26b057f0 100644
--- a/packages/0x.js/src/utils/abi_decoder.ts
+++ b/packages/0x.js/src/utils/abi_decoder.ts
@@ -8,6 +8,15 @@ import {AbiType, ContractEventArgs, DecodedLogArgs, LogWithDecodedArgs, RawLog,
export class AbiDecoder {
private savedABIs: Web3.AbiDefinition[] = [];
private methodIds: {[signatureHash: string]: Web3.EventAbi} = {};
+ private static padZeros(address: string) {
+ let formatted = address;
+ if (_.startsWith(formatted, '0x')) {
+ formatted = formatted.slice(2);
+ }
+
+ formatted = _.padStart(formatted, 40, '0');
+ return `0x${formatted}`;
+ }
constructor(abiArrays: Web3.AbiDefinition[][]) {
_.map(abiArrays, this.addABI.bind(this));
}
@@ -32,7 +41,7 @@ export class AbiDecoder {
// Indexed parameters are stored in topics. Non-indexed ones in decodedData
let value = param.indexed ? log.topics[topicsIndex++] : decodedData[dataIndex++];
if (param.type === SolidityTypes.Address) {
- value = this.padZeros(new BigNumber(value).toString(16));
+ value = AbiDecoder.padZeros(new BigNumber(value).toString(16));
} else if (param.type === SolidityTypes.Uint256 ||
param.type === SolidityTypes.Uint8 ||
param.type === SolidityTypes.Uint) {
@@ -57,13 +66,4 @@ export class AbiDecoder {
});
this.savedABIs = this.savedABIs.concat(abiArray);
}
- private padZeros(address: string) {
- let formatted = address;
- if (_.startsWith(formatted, '0x')) {
- formatted = formatted.slice(2);
- }
-
- formatted = _.padStart(formatted, 40, '0');
- return `0x${formatted}`;
- }
}
diff --git a/packages/0x.js/src/utils/exchange_transfer_simulator.ts b/packages/0x.js/src/utils/exchange_transfer_simulator.ts
index c3a2d1585..00a0efd3f 100644
--- a/packages/0x.js/src/utils/exchange_transfer_simulator.ts
+++ b/packages/0x.js/src/utils/exchange_transfer_simulator.ts
@@ -36,6 +36,11 @@ const ERR_MSG_MAPPING = {
export class ExchangeTransferSimulator {
private store: BalanceAndProxyAllowanceLazyStore;
private UNLIMITED_ALLOWANCE_IN_BASE_UNITS: BigNumber;
+ private static throwValidationError(failureReason: FailureReason, tradeSide: TradeSide,
+ transferType: TransferType): never {
+ const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType];
+ throw new Error(errMsg);
+ }
constructor(token: TokenWrapper) {
this.store = new BalanceAndProxyAllowanceLazyStore(token);
this.UNLIMITED_ALLOWANCE_IN_BASE_UNITS = token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
@@ -55,10 +60,10 @@ export class ExchangeTransferSimulator {
const balance = await this.store.getBalanceAsync(tokenAddress, from);
const proxyAllowance = await this.store.getProxyAllowanceAsync(tokenAddress, from);
if (proxyAllowance.lessThan(amountInBaseUnits)) {
- this.throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType);
+ ExchangeTransferSimulator.throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType);
}
if (balance.lessThan(amountInBaseUnits)) {
- this.throwValidationError(FailureReason.Balance, tradeSide, transferType);
+ ExchangeTransferSimulator.throwValidationError(FailureReason.Balance, tradeSide, transferType);
}
await this.decreaseProxyAllowanceAsync(tokenAddress, from, amountInBaseUnits);
await this.decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits);
@@ -81,9 +86,4 @@ export class ExchangeTransferSimulator {
const balance = await this.store.getBalanceAsync(tokenAddress, userAddress);
this.store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits));
}
- private throwValidationError(failureReason: FailureReason, tradeSide: TradeSide,
- transferType: TransferType): never {
- const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType];
- throw new Error(errMsg);
- }
}
diff --git a/packages/0x.js/src/utils/order_state_utils.ts b/packages/0x.js/src/utils/order_state_utils.ts
index 6654b9ae1..7dee89914 100644
--- a/packages/0x.js/src/utils/order_state_utils.ts
+++ b/packages/0x.js/src/utils/order_state_utils.ts
@@ -25,6 +25,39 @@ const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
export class OrderStateUtils {
private balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore;
private orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore;
+ private static validateIfOrderIsValid(signedOrder: SignedOrder, orderRelevantState: OrderRelevantState): void {
+ const unavailableTakerTokenAmount = orderRelevantState.cancelledTakerTokenAmount.add(
+ orderRelevantState.filledTakerTokenAmount,
+ );
+ const availableTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
+ if (availableTakerTokenAmount.eq(0)) {
+ throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
+ }
+
+ if (orderRelevantState.makerBalance.eq(0)) {
+ throw new Error(ExchangeContractErrs.InsufficientMakerBalance);
+ }
+ if (orderRelevantState.makerProxyAllowance.eq(0)) {
+ throw new Error(ExchangeContractErrs.InsufficientMakerAllowance);
+ }
+ if (!signedOrder.makerFee.eq(0)) {
+ if (orderRelevantState.makerFeeBalance.eq(0)) {
+ throw new Error(ExchangeContractErrs.InsufficientMakerFeeBalance);
+ }
+ if (orderRelevantState.makerFeeProxyAllowance.eq(0)) {
+ throw new Error(ExchangeContractErrs.InsufficientMakerFeeAllowance);
+ }
+ }
+ const minFillableTakerTokenAmountWithinNoRoundingErrorRange = signedOrder.takerTokenAmount
+ .dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
+ .dividedBy(signedOrder.makerTokenAmount);
+ if (orderRelevantState.remainingFillableTakerTokenAmount
+ .lessThan(minFillableTakerTokenAmountWithinNoRoundingErrorRange)) {
+ throw new Error(ExchangeContractErrs.OrderFillRoundingError);
+ }
+ // TODO Add linear function solver when maker token is ZRX #badass
+ // Return the max amount that's fillable
+ }
constructor(balanceAndProxyAllowanceLazyStore: BalanceAndProxyAllowanceLazyStore,
orderFilledCancelledLazyStore: OrderFilledCancelledLazyStore) {
this.balanceAndProxyAllowanceLazyStore = balanceAndProxyAllowanceLazyStore;
@@ -34,7 +67,7 @@ export class OrderStateUtils {
const orderRelevantState = await this.getOrderRelevantStateAsync(signedOrder);
const orderHash = ZeroEx.getOrderHashHex(signedOrder);
try {
- this.validateIfOrderIsValid(signedOrder, orderRelevantState);
+ OrderStateUtils.validateIfOrderIsValid(signedOrder, orderRelevantState);
const orderState: OrderStateValid = {
isValid: true,
orderHash,
@@ -103,37 +136,4 @@ export class OrderStateUtils {
};
return orderRelevantState;
}
- private validateIfOrderIsValid(signedOrder: SignedOrder, orderRelevantState: OrderRelevantState): void {
- const unavailableTakerTokenAmount = orderRelevantState.cancelledTakerTokenAmount.add(
- orderRelevantState.filledTakerTokenAmount,
- );
- const availableTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
- if (availableTakerTokenAmount.eq(0)) {
- throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
- }
-
- if (orderRelevantState.makerBalance.eq(0)) {
- throw new Error(ExchangeContractErrs.InsufficientMakerBalance);
- }
- if (orderRelevantState.makerProxyAllowance.eq(0)) {
- throw new Error(ExchangeContractErrs.InsufficientMakerAllowance);
- }
- if (!signedOrder.makerFee.eq(0)) {
- if (orderRelevantState.makerFeeBalance.eq(0)) {
- throw new Error(ExchangeContractErrs.InsufficientMakerFeeBalance);
- }
- if (orderRelevantState.makerFeeProxyAllowance.eq(0)) {
- throw new Error(ExchangeContractErrs.InsufficientMakerFeeAllowance);
- }
- }
- const minFillableTakerTokenAmountWithinNoRoundingErrorRange = signedOrder.takerTokenAmount
- .dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
- .dividedBy(signedOrder.makerTokenAmount);
- if (orderRelevantState.remainingFillableTakerTokenAmount
- .lessThan(minFillableTakerTokenAmountWithinNoRoundingErrorRange)) {
- throw new Error(ExchangeContractErrs.OrderFillRoundingError);
- }
- // TODO Add linear function solver when maker token is ZRX #badass
- // Return the max amount that's fillable
- }
}
diff --git a/packages/0x.js/src/utils/order_validation_utils.ts b/packages/0x.js/src/utils/order_validation_utils.ts
index 06cfca7bd..d514483e0 100644
--- a/packages/0x.js/src/utils/order_validation_utils.ts
+++ b/packages/0x.js/src/utils/order_validation_utils.ts
@@ -13,6 +13,77 @@ import {ExchangeTransferSimulator} from './exchange_transfer_simulator';
export class OrderValidationUtils {
private tokenWrapper: TokenWrapper;
private exchangeWrapper: ExchangeWrapper;
+ public static validateCancelOrderThrowIfInvalid(
+ order: Order, cancelTakerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
+ ): void {
+ if (cancelTakerTokenAmount.eq(0)) {
+ throw new Error(ExchangeContractErrs.OrderCancelAmountZero);
+ }
+ if (order.takerTokenAmount.eq(unavailableTakerTokenAmount)) {
+ throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
+ }
+ const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
+ if (order.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
+ throw new Error(ExchangeContractErrs.OrderCancelExpired);
+ }
+ }
+ public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
+ exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
+ fillTakerTokenAmount: BigNumber, senderAddress: string, zrxTokenAddress: string,
+ ): Promise<void> {
+ const fillMakerTokenAmount = OrderValidationUtils.getPartialAmount(
+ fillTakerTokenAmount,
+ signedOrder.takerTokenAmount,
+ signedOrder.makerTokenAmount,
+ );
+ await exchangeTradeEmulator.transferFromAsync(
+ signedOrder.makerTokenAddress, signedOrder.maker, senderAddress, fillMakerTokenAmount,
+ TradeSide.Maker, TransferType.Trade,
+ );
+ await exchangeTradeEmulator.transferFromAsync(
+ signedOrder.takerTokenAddress, senderAddress, signedOrder.maker, fillTakerTokenAmount,
+ TradeSide.Taker, TransferType.Trade,
+ );
+ const makerFeeAmount = OrderValidationUtils.getPartialAmount(
+ fillTakerTokenAmount,
+ signedOrder.takerTokenAmount,
+ signedOrder.makerFee,
+ );
+ await exchangeTradeEmulator.transferFromAsync(
+ zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount, TradeSide.Maker,
+ TransferType.Fee,
+ );
+ const takerFeeAmount = OrderValidationUtils.getPartialAmount(
+ fillTakerTokenAmount,
+ signedOrder.takerTokenAmount,
+ signedOrder.takerFee,
+ );
+ await exchangeTradeEmulator.transferFromAsync(
+ zrxTokenAddress, senderAddress, signedOrder.feeRecipient, takerFeeAmount, TradeSide.Taker,
+ TransferType.Fee,
+ );
+ }
+ private static validateRemainingFillAmountNotZeroOrThrow(
+ takerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
+ ) {
+ if (takerTokenAmount.eq(unavailableTakerTokenAmount)) {
+ throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
+ }
+ }
+ private static validateOrderNotExpiredOrThrow(expirationUnixTimestampSec: BigNumber) {
+ const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
+ if (expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
+ throw new Error(ExchangeContractErrs.OrderFillExpired);
+ }
+ }
+ private static getPartialAmount(numerator: BigNumber, denominator: BigNumber,
+ target: BigNumber): BigNumber {
+ const fillMakerTokenAmount = numerator
+ .mul(target)
+ .div(denominator)
+ .round(0);
+ return fillMakerTokenAmount;
+ }
constructor(tokenWrapper: TokenWrapper, exchangeWrapper: ExchangeWrapper) {
this.tokenWrapper = tokenWrapper;
this.exchangeWrapper = exchangeWrapper;
@@ -22,15 +93,15 @@ export class OrderValidationUtils {
expectedFillTakerTokenAmount?: BigNumber): Promise<void> {
const orderHash = utils.getOrderHashHex(signedOrder);
const unavailableTakerTokenAmount = await this.exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
- this.validateRemainingFillAmountNotZeroOrThrow(
+ OrderValidationUtils.validateRemainingFillAmountNotZeroOrThrow(
signedOrder.takerTokenAmount, unavailableTakerTokenAmount,
);
- this.validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
+ OrderValidationUtils.validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
let fillTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
if (!_.isUndefined(expectedFillTakerTokenAmount)) {
fillTakerTokenAmount = expectedFillTakerTokenAmount;
}
- const fillMakerTokenAmount = this.getPartialAmount(
+ const fillMakerTokenAmount = OrderValidationUtils.getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerTokenAmount,
@@ -39,7 +110,7 @@ export class OrderValidationUtils {
signedOrder.makerTokenAddress, signedOrder.maker, signedOrder.taker, fillMakerTokenAmount,
TradeSide.Maker, TransferType.Trade,
);
- const makerFeeAmount = this.getPartialAmount(
+ const makerFeeAmount = OrderValidationUtils.getPartialAmount(
fillTakerTokenAmount,
signedOrder.takerTokenAmount,
signedOrder.makerFee,
@@ -61,18 +132,18 @@ export class OrderValidationUtils {
throw new Error(ZeroExError.InvalidSignature);
}
const unavailableTakerTokenAmount = await this.exchangeWrapper.getUnavailableTakerAmountAsync(orderHash);
- this.validateRemainingFillAmountNotZeroOrThrow(
+ OrderValidationUtils.validateRemainingFillAmountNotZeroOrThrow(
signedOrder.takerTokenAmount, unavailableTakerTokenAmount,
);
if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== takerAddress) {
throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker);
}
- this.validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
+ OrderValidationUtils.validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec);
const remainingTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount);
const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount) ?
remainingTakerTokenAmount :
fillTakerTokenAmount;
- await this.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
+ await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTradeEmulator, signedOrder, filledTakerTokenAmount, takerAddress, zrxTokenAddress,
);
@@ -94,74 +165,4 @@ export class OrderValidationUtils {
throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount);
}
}
- public validateCancelOrderThrowIfInvalid(
- order: Order, cancelTakerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
- ): void {
- if (cancelTakerTokenAmount.eq(0)) {
- throw new Error(ExchangeContractErrs.OrderCancelAmountZero);
- }
- if (order.takerTokenAmount.eq(unavailableTakerTokenAmount)) {
- throw new Error(ExchangeContractErrs.OrderAlreadyCancelledOrFilled);
- }
- const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
- if (order.expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
- throw new Error(ExchangeContractErrs.OrderCancelExpired);
- }
- }
- public async validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
- exchangeTradeEmulator: ExchangeTransferSimulator, signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber, senderAddress: string, zrxTokenAddress: string): Promise<void> {
- const fillMakerTokenAmount = this.getPartialAmount(
- fillTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerTokenAmount,
- );
- await exchangeTradeEmulator.transferFromAsync(
- signedOrder.makerTokenAddress, signedOrder.maker, senderAddress, fillMakerTokenAmount,
- TradeSide.Maker, TransferType.Trade,
- );
- await exchangeTradeEmulator.transferFromAsync(
- signedOrder.takerTokenAddress, senderAddress, signedOrder.maker, fillTakerTokenAmount,
- TradeSide.Taker, TransferType.Trade,
- );
- const makerFeeAmount = this.getPartialAmount(
- fillTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.makerFee,
- );
- await exchangeTradeEmulator.transferFromAsync(
- zrxTokenAddress, signedOrder.maker, signedOrder.feeRecipient, makerFeeAmount, TradeSide.Maker,
- TransferType.Fee,
- );
- const takerFeeAmount = this.getPartialAmount(
- fillTakerTokenAmount,
- signedOrder.takerTokenAmount,
- signedOrder.takerFee,
- );
- await exchangeTradeEmulator.transferFromAsync(
- zrxTokenAddress, senderAddress, signedOrder.feeRecipient, takerFeeAmount, TradeSide.Taker,
- TransferType.Fee,
- );
- }
- private validateRemainingFillAmountNotZeroOrThrow(
- takerTokenAmount: BigNumber, unavailableTakerTokenAmount: BigNumber,
- ) {
- if (takerTokenAmount.eq(unavailableTakerTokenAmount)) {
- throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
- }
- }
- private validateOrderNotExpiredOrThrow(expirationUnixTimestampSec: BigNumber) {
- const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec();
- if (expirationUnixTimestampSec.lessThan(currentUnixTimestampSec)) {
- throw new Error(ExchangeContractErrs.OrderFillExpired);
- }
- }
- private getPartialAmount(numerator: BigNumber, denominator: BigNumber,
- target: BigNumber): BigNumber {
- const fillMakerTokenAmount = numerator
- .mul(target)
- .div(denominator)
- .round(0);
- return fillMakerTokenAmount;
- }
}
diff --git a/packages/0x.js/test/order_validation_test.ts b/packages/0x.js/test/order_validation_test.ts
index 811cd48c4..3282ebb3e 100644
--- a/packages/0x.js/test/order_validation_test.ts
+++ b/packages/0x.js/test/order_validation_test.ts
@@ -114,7 +114,7 @@ describe('OrderValidation', () => {
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, fillableAmount,
);
// 27 <--> 28
- signedOrder.ecSignature.v = 27 + (28 - signedOrder.ecSignature.v);
+ signedOrder.ecSignature.v = (28 - signedOrder.ecSignature.v) + 27;
return expect(zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
signedOrder, fillableAmount, takerAddress,
)).to.be.rejectedWith(ZeroExError.InvalidSignature);
@@ -230,7 +230,7 @@ describe('OrderValidation', () => {
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
makerAddress, takerAddress, fillableAmount, feeRecipient,
);
- await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
+ await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
);
expect(transferFromAsync.callCount).to.be.equal(4);
@@ -266,7 +266,7 @@ describe('OrderValidation', () => {
makerTokenAddress, takerTokenAddress, makerFee, takerFee,
makerAddress, ZeroEx.NULL_ADDRESS, fillableAmount, feeRecipient,
);
- await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
+ await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTransferSimulator, signedOrder, fillableAmount, takerAddress, zrxTokenAddress,
);
expect(transferFromAsync.callCount).to.be.equal(4);
@@ -301,7 +301,7 @@ describe('OrderValidation', () => {
const signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
makerTokenAddress, takerTokenAddress, makerAddress, takerAddress, makerTokenAmount, takerTokenAmount,
);
- await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
+ await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTransferSimulator, signedOrder, takerTokenAmount, takerAddress, zrxTokenAddress,
);
expect(transferFromAsync.callCount).to.be.equal(4);
@@ -316,7 +316,7 @@ describe('OrderValidation', () => {
fillableAmount, ZeroEx.NULL_ADDRESS,
);
const fillTakerTokenAmount = fillableAmount.div(2).round(0);
- await orderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
+ await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync(
exchangeTransferSimulator, signedOrder, fillTakerTokenAmount, takerAddress, zrxTokenAddress,
);
const makerPartialFee = makerFee.div(2);