diff options
author | Fabio Berger <me@fabioberger.com> | 2018-05-10 02:36:28 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-05-10 02:36:28 +0800 |
commit | 209266dbed9d7d038c90c2da8d9b99acab77c80c (patch) | |
tree | cfefd5ab15bc237716b15687629e0f41362a8e86 /packages/0x.js/src/utils | |
parent | 69a6166b6a1d39afc24b8dd950ec5d8539a03420 (diff) | |
download | dexon-sol-tools-209266dbed9d7d038c90c2da8d9b99acab77c80c.tar dexon-sol-tools-209266dbed9d7d038c90c2da8d9b99acab77c80c.tar.gz dexon-sol-tools-209266dbed9d7d038c90c2da8d9b99acab77c80c.tar.bz2 dexon-sol-tools-209266dbed9d7d038c90c2da8d9b99acab77c80c.tar.lz dexon-sol-tools-209266dbed9d7d038c90c2da8d9b99acab77c80c.tar.xz dexon-sol-tools-209266dbed9d7d038c90c2da8d9b99acab77c80c.tar.zst dexon-sol-tools-209266dbed9d7d038c90c2da8d9b99acab77c80c.zip |
Split 0x.js into contract-wrappers, order-watcher but keep 0x.js as a unifying library with the same interface
Diffstat (limited to 'packages/0x.js/src/utils')
-rw-r--r-- | packages/0x.js/src/utils/assert.ts | 31 | ||||
-rw-r--r-- | packages/0x.js/src/utils/constants.ts | 5 | ||||
-rw-r--r-- | packages/0x.js/src/utils/decorators.ts | 91 | ||||
-rw-r--r-- | packages/0x.js/src/utils/exchange_transfer_simulator.ts | 115 | ||||
-rw-r--r-- | packages/0x.js/src/utils/filter_utils.ts | 95 | ||||
-rw-r--r-- | packages/0x.js/src/utils/order_state_utils.ts | 138 | ||||
-rw-r--r-- | packages/0x.js/src/utils/order_validation_utils.ts | 199 | ||||
-rw-r--r-- | packages/0x.js/src/utils/utils.ts | 13 |
8 files changed, 0 insertions, 687 deletions
diff --git a/packages/0x.js/src/utils/assert.ts b/packages/0x.js/src/utils/assert.ts deleted file mode 100644 index 2588a4d09..000000000 --- a/packages/0x.js/src/utils/assert.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { assert as sharedAssert } from '@0xproject/assert'; -// We need those two unused imports because they're actually used by sharedAssert which gets injected here -// tslint:disable-next-line:no-unused-variable -import { Schema } from '@0xproject/json-schemas'; -// tslint:disable-next-line:no-unused-variable -import { ECSignature } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; -import * as _ from 'lodash'; - -import { isValidSignature } from '@0xproject/order-utils'; - -export const assert = { - ...sharedAssert, - isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string) { - const isValid = isValidSignature(orderHash, ecSignature, signerAddress); - this.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`); - }, - async isSenderAddressAsync( - variableName: string, - senderAddressHex: string, - web3Wrapper: Web3Wrapper, - ): Promise<void> { - sharedAssert.isETHAddressHex(variableName, senderAddressHex); - const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex); - sharedAssert.assert( - isSenderAddressAvailable, - `Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`, - ); - }, -}; diff --git a/packages/0x.js/src/utils/constants.ts b/packages/0x.js/src/utils/constants.ts index 07da6745d..7cd5eb574 100644 --- a/packages/0x.js/src/utils/constants.ts +++ b/packages/0x.js/src/utils/constants.ts @@ -3,9 +3,4 @@ import { BigNumber } from '@0xproject/utils'; export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', TESTRPC_NETWORK_ID: 50, - INVALID_JUMP_PATTERN: 'invalid JUMP at', - OUT_OF_GAS_PATTERN: 'out of gas', - INVALID_TAKER_FORMAT: 'instance.taker is not of a type(s) string', - UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), - DEFAULT_BLOCK_POLLING_INTERVAL: 1000, }; diff --git a/packages/0x.js/src/utils/decorators.ts b/packages/0x.js/src/utils/decorators.ts deleted file mode 100644 index f774d734e..000000000 --- a/packages/0x.js/src/utils/decorators.ts +++ /dev/null @@ -1,91 +0,0 @@ -import * as _ from 'lodash'; - -import { AsyncMethod, SyncMethod, ZeroExError } from '../types'; - -import { constants } from './constants'; - -type ErrorTransformer = (err: Error) => Error; - -const contractCallErrorTransformer = (error: Error) => { - if (_.includes(error.message, constants.INVALID_JUMP_PATTERN)) { - return new Error(ZeroExError.InvalidJump); - } - if (_.includes(error.message, constants.OUT_OF_GAS_PATTERN)) { - return new Error(ZeroExError.OutOfGas); - } - return error; -}; - -const schemaErrorTransformer = (error: Error) => { - if (_.includes(error.message, constants.INVALID_TAKER_FORMAT)) { - const errMsg = - 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS'; - return new Error(errMsg); - } - return error; -}; - -/** - * Source: https://stackoverflow.com/a/29837695/3546986 - */ -const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => { - const asyncErrorHandlingDecorator = ( - target: object, - key: string | symbol, - descriptor: TypedPropertyDescriptor<AsyncMethod>, - ) => { - const originalMethod = descriptor.value as AsyncMethod; - - // Do not use arrow syntax here. Use a function expression in - // order to use the correct value of `this` in this method - // tslint:disable-next-line:only-arrow-functions - descriptor.value = async function(...args: any[]) { - try { - const result = await originalMethod.apply(this, args); - return result; - } catch (error) { - const transformedError = errorTransformer(error); - throw transformedError; - } - }; - - return descriptor; - }; - - return asyncErrorHandlingDecorator; -}; - -const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => { - const syncErrorHandlingDecorator = ( - target: object, - key: string | symbol, - descriptor: TypedPropertyDescriptor<SyncMethod>, - ) => { - const originalMethod = descriptor.value as SyncMethod; - - // Do not use arrow syntax here. Use a function expression in - // order to use the correct value of `this` in this method - // tslint:disable-next-line:only-arrow-functions - descriptor.value = function(...args: any[]) { - try { - const result = originalMethod.apply(this, args); - return result; - } catch (error) { - const transformedError = errorTransformer(error); - throw transformedError; - } - }; - - return descriptor; - }; - - return syncErrorHandlingDecorator; -}; - -// _.flow(f, g) = f ∘ g -const zeroExErrorTransformer = _.flow(schemaErrorTransformer, contractCallErrorTransformer); - -export const decorators = { - asyncZeroExErrorHandler: asyncErrorHandlerFactory(zeroExErrorTransformer), - syncZeroExErrorHandler: syncErrorHandlerFactory(zeroExErrorTransformer), -}; diff --git a/packages/0x.js/src/utils/exchange_transfer_simulator.ts b/packages/0x.js/src/utils/exchange_transfer_simulator.ts deleted file mode 100644 index f8301f5c2..000000000 --- a/packages/0x.js/src/utils/exchange_transfer_simulator.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { BlockParamLiteral } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import * as _ from 'lodash'; - -import { TokenWrapper } from '../contract_wrappers/token_wrapper'; -import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store'; -import { ExchangeContractErrs, TradeSide, TransferType } from '../types'; -import { constants } from '../utils/constants'; - -enum FailureReason { - Balance = 'balance', - ProxyAllowance = 'proxyAllowance', -} - -const ERR_MSG_MAPPING = { - [FailureReason.Balance]: { - [TradeSide.Maker]: { - [TransferType.Trade]: ExchangeContractErrs.InsufficientMakerBalance, - [TransferType.Fee]: ExchangeContractErrs.InsufficientMakerFeeBalance, - }, - [TradeSide.Taker]: { - [TransferType.Trade]: ExchangeContractErrs.InsufficientTakerBalance, - [TransferType.Fee]: ExchangeContractErrs.InsufficientTakerFeeBalance, - }, - }, - [FailureReason.ProxyAllowance]: { - [TradeSide.Maker]: { - [TransferType.Trade]: ExchangeContractErrs.InsufficientMakerAllowance, - [TransferType.Fee]: ExchangeContractErrs.InsufficientMakerFeeAllowance, - }, - [TradeSide.Taker]: { - [TransferType.Trade]: ExchangeContractErrs.InsufficientTakerAllowance, - [TransferType.Fee]: ExchangeContractErrs.InsufficientTakerFeeAllowance, - }, - }, -}; - -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, defaultBlock: BlockParamLiteral) { - this._store = new BalanceAndProxyAllowanceLazyStore(token, defaultBlock); - this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS = token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; - } - /** - * Simulates transferFrom call performed by a proxy - * @param tokenAddress Address of the token to be transferred - * @param from Owner of the transferred tokens - * @param to Recipient of the transferred tokens - * @param amountInBaseUnits The amount of tokens being transferred - * @param tradeSide Is Maker/Taker transferring - * @param transferType Is it a fee payment or a value transfer - */ - public async transferFromAsync( - tokenAddress: string, - from: string, - to: string, - amountInBaseUnits: BigNumber, - tradeSide: TradeSide, - transferType: TransferType, - ): Promise<void> { - // HACK: When simulating an open order (e.g taker is NULL_ADDRESS), we don't want to adjust balances/ - // allowances for the taker. We do however, want to increase the balance of the maker since the maker - // might be relying on those funds to fill subsequent orders or pay the order's fees. - if (from === constants.NULL_ADDRESS && tradeSide === TradeSide.Taker) { - await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits); - return; - } - const balance = await this._store.getBalanceAsync(tokenAddress, from); - const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, from); - if (proxyAllowance.lessThan(amountInBaseUnits)) { - ExchangeTransferSimulator._throwValidationError(FailureReason.ProxyAllowance, tradeSide, transferType); - } - if (balance.lessThan(amountInBaseUnits)) { - ExchangeTransferSimulator._throwValidationError(FailureReason.Balance, tradeSide, transferType); - } - await this._decreaseProxyAllowanceAsync(tokenAddress, from, amountInBaseUnits); - await this._decreaseBalanceAsync(tokenAddress, from, amountInBaseUnits); - await this._increaseBalanceAsync(tokenAddress, to, amountInBaseUnits); - } - private async _decreaseProxyAllowanceAsync( - tokenAddress: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise<void> { - const proxyAllowance = await this._store.getProxyAllowanceAsync(tokenAddress, userAddress); - if (!proxyAllowance.eq(this._UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { - this._store.setProxyAllowance(tokenAddress, userAddress, proxyAllowance.minus(amountInBaseUnits)); - } - } - private async _increaseBalanceAsync( - tokenAddress: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise<void> { - const balance = await this._store.getBalanceAsync(tokenAddress, userAddress); - this._store.setBalance(tokenAddress, userAddress, balance.plus(amountInBaseUnits)); - } - private async _decreaseBalanceAsync( - tokenAddress: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise<void> { - const balance = await this._store.getBalanceAsync(tokenAddress, userAddress); - this._store.setBalance(tokenAddress, userAddress, balance.minus(amountInBaseUnits)); - } -} diff --git a/packages/0x.js/src/utils/filter_utils.ts b/packages/0x.js/src/utils/filter_utils.ts deleted file mode 100644 index c5df7321e..000000000 --- a/packages/0x.js/src/utils/filter_utils.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { - ConstructorAbi, - ContractAbi, - EventAbi, - FallbackAbi, - FilterObject, - LogEntry, - MethodAbi, -} from '@0xproject/types'; -import * as ethUtil from 'ethereumjs-util'; -import * as jsSHA3 from 'js-sha3'; -import * as _ from 'lodash'; -import * as uuid from 'uuid/v4'; - -import { BlockRange, ContractEvents, IndexedFilterValues } from '../types'; - -const TOPIC_LENGTH = 32; - -export const filterUtils = { - generateUUID(): string { - return uuid(); - }, - getFilter( - address: string, - eventName: ContractEvents, - indexFilterValues: IndexedFilterValues, - abi: ContractAbi, - blockRange?: BlockRange, - ): FilterObject { - const eventAbi = _.find(abi, { name: eventName }) as EventAbi; - const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi, eventName); - const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature)); - const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues); - const topics = [topicForEventSignature, ...topicsForIndexedArgs]; - let filter: FilterObject = { - address, - topics, - }; - if (!_.isUndefined(blockRange)) { - filter = { - ...blockRange, - ...filter, - }; - } - return filter; - }, - getEventSignatureFromAbiByName(eventAbi: EventAbi, eventName: ContractEvents): string { - const types = _.map(eventAbi.inputs, 'type'); - const signature = `${eventAbi.name}(${types.join(',')})`; - return signature; - }, - getTopicsForIndexedArgs(abi: EventAbi, indexFilterValues: IndexedFilterValues): Array<string | null> { - const topics: Array<string | null> = []; - for (const eventInput of abi.inputs) { - if (!eventInput.indexed) { - continue; - } - if (_.isUndefined(indexFilterValues[eventInput.name])) { - // Null is a wildcard topic in a JSON-RPC call - topics.push(null); - } else { - const value = indexFilterValues[eventInput.name] as string; - const buffer = ethUtil.toBuffer(value); - const paddedBuffer = ethUtil.setLengthLeft(buffer, TOPIC_LENGTH); - const topic = ethUtil.bufferToHex(paddedBuffer); - topics.push(topic); - } - } - return topics; - }, - matchesFilter(log: LogEntry, filter: FilterObject): boolean { - if (!_.isUndefined(filter.address) && log.address !== filter.address) { - return false; - } - if (!_.isUndefined(filter.topics)) { - return filterUtils.matchesTopics(log.topics, filter.topics); - } - return true; - }, - matchesTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean { - const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils)); - const matchesTopics = _.every(matchesTopic); - return matchesTopics; - }, - matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean { - if (_.isArray(filterTopic)) { - return _.includes(filterTopic, logTopic); - } - if (_.isString(filterTopic)) { - return filterTopic === logTopic; - } - // null topic is a wildcard - return true; - }, -}; diff --git a/packages/0x.js/src/utils/order_state_utils.ts b/packages/0x.js/src/utils/order_state_utils.ts deleted file mode 100644 index b0310d8a8..000000000 --- a/packages/0x.js/src/utils/order_state_utils.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import * as _ from 'lodash'; - -import { ZeroEx } from '../0x'; -import { BalanceAndProxyAllowanceFetcher } from '../abstract/balance_and_proxy_allowance_fetcher'; -import { OrderFilledCancelledFetcher } from '../abstract/order_filled_cancelled_fetcher'; -import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; -import { RemainingFillableCalculator } from '../order_watcher/remaining_fillable_calculator'; -import { ExchangeContractErrs, OrderRelevantState, OrderState, OrderStateInvalid, OrderStateValid } from '../types'; - -const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001; - -export class OrderStateUtils { - private _balanceAndProxyAllowanceFetcher: BalanceAndProxyAllowanceFetcher; - private _orderFilledCancelledFetcher: OrderFilledCancelledFetcher; - 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); - } - } - constructor( - balanceAndProxyAllowanceFetcher: BalanceAndProxyAllowanceFetcher, - orderFilledCancelledFetcher: OrderFilledCancelledFetcher, - ) { - this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher; - this._orderFilledCancelledFetcher = orderFilledCancelledFetcher; - } - public async getOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> { - const orderRelevantState = await this.getOrderRelevantStateAsync(signedOrder); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - try { - OrderStateUtils._validateIfOrderIsValid(signedOrder, orderRelevantState); - const orderState: OrderStateValid = { - isValid: true, - orderHash, - orderRelevantState, - }; - return orderState; - } catch (err) { - const orderState: OrderStateInvalid = { - isValid: false, - orderHash, - error: err.message, - }; - return orderState; - } - } - public async getOrderRelevantStateAsync(signedOrder: SignedOrder): Promise<OrderRelevantState> { - // HACK: We access the private property here but otherwise the interface will be less nice. - // If we pass it from the instantiator - there is no opportunity to get it there - // because JS doesn't support async constructors. - // Moreover - it's cached under the hood so it's equivalent to an async constructor. - const exchange = (this._orderFilledCancelledFetcher as any)._exchangeWrapper as ExchangeWrapper; - const zrxTokenAddress = exchange.getZRXTokenAddress(); - const orderHash = ZeroEx.getOrderHashHex(signedOrder); - const makerBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync( - signedOrder.makerTokenAddress, - signedOrder.maker, - ); - const makerProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync( - signedOrder.makerTokenAddress, - signedOrder.maker, - ); - const makerFeeBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync( - zrxTokenAddress, - signedOrder.maker, - ); - const makerFeeProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync( - zrxTokenAddress, - signedOrder.maker, - ); - const filledTakerTokenAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash); - const cancelledTakerTokenAmount = await this._orderFilledCancelledFetcher.getCancelledTakerAmountAsync( - orderHash, - ); - const unavailableTakerTokenAmount = await exchange.getUnavailableTakerAmountAsync(orderHash); - const totalMakerTokenAmount = signedOrder.makerTokenAmount; - const totalTakerTokenAmount = signedOrder.takerTokenAmount; - const remainingTakerTokenAmount = totalTakerTokenAmount.minus(unavailableTakerTokenAmount); - const remainingMakerTokenAmount = remainingTakerTokenAmount - .times(totalMakerTokenAmount) - .dividedToIntegerBy(totalTakerTokenAmount); - const transferrableMakerTokenAmount = BigNumber.min([makerProxyAllowance, makerBalance]); - const transferrableFeeTokenAmount = BigNumber.min([makerFeeProxyAllowance, makerFeeBalance]); - - const isMakerTokenZRX = signedOrder.makerTokenAddress === zrxTokenAddress; - const remainingFillableCalculator = new RemainingFillableCalculator( - signedOrder, - isMakerTokenZRX, - transferrableMakerTokenAmount, - transferrableFeeTokenAmount, - remainingMakerTokenAmount, - ); - const remainingFillableMakerTokenAmount = remainingFillableCalculator.computeRemainingMakerFillable(); - const remainingFillableTakerTokenAmount = remainingFillableCalculator.computeRemainingTakerFillable(); - const orderRelevantState = { - makerBalance, - makerProxyAllowance, - makerFeeBalance, - makerFeeProxyAllowance, - filledTakerTokenAmount, - cancelledTakerTokenAmount, - remainingFillableMakerTokenAmount, - remainingFillableTakerTokenAmount, - }; - return orderRelevantState; - } -} diff --git a/packages/0x.js/src/utils/order_validation_utils.ts b/packages/0x.js/src/utils/order_validation_utils.ts deleted file mode 100644 index a13c3dc04..000000000 --- a/packages/0x.js/src/utils/order_validation_utils.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { getOrderHashHex, OrderError } from '@0xproject/order-utils'; -import { Order, SignedOrder } from '@0xproject/types'; -import { BigNumber } from '@0xproject/utils'; -import * as _ from 'lodash'; - -import { ZeroEx } from '../0x'; -import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; -import { ExchangeContractErrs, TradeSide, TransferType, ZeroExError } from '../types'; -import { constants } from '../utils/constants'; -import { utils } from '../utils/utils'; - -import { ExchangeTransferSimulator } from './exchange_transfer_simulator'; - -export class OrderValidationUtils { - 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(exchangeWrapper: ExchangeWrapper) { - this._exchangeWrapper = exchangeWrapper; - } - public async validateOrderFillableOrThrowAsync( - exchangeTradeEmulator: ExchangeTransferSimulator, - signedOrder: SignedOrder, - zrxTokenAddress: string, - expectedFillTakerTokenAmount?: BigNumber, - ): Promise<void> { - const orderHash = getOrderHashHex(signedOrder); - const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); - OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow( - signedOrder.takerTokenAmount, - unavailableTakerTokenAmount, - ); - OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec); - let fillTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount); - if (!_.isUndefined(expectedFillTakerTokenAmount)) { - fillTakerTokenAmount = expectedFillTakerTokenAmount; - } - await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - fillTakerTokenAmount, - signedOrder.taker, - zrxTokenAddress, - ); - } - public async validateFillOrderThrowIfInvalidAsync( - exchangeTradeEmulator: ExchangeTransferSimulator, - signedOrder: SignedOrder, - fillTakerTokenAmount: BigNumber, - takerAddress: string, - zrxTokenAddress: string, - ): Promise<BigNumber> { - if (fillTakerTokenAmount.eq(0)) { - throw new Error(ExchangeContractErrs.OrderFillAmountZero); - } - const orderHash = getOrderHashHex(signedOrder); - if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) { - throw new Error(OrderError.InvalidSignature); - } - const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); - OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow( - signedOrder.takerTokenAmount, - unavailableTakerTokenAmount, - ); - if (signedOrder.taker !== constants.NULL_ADDRESS && signedOrder.taker !== takerAddress) { - throw new Error(ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker); - } - OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationUnixTimestampSec); - const remainingTakerTokenAmount = signedOrder.takerTokenAmount.minus(unavailableTakerTokenAmount); - const filledTakerTokenAmount = remainingTakerTokenAmount.lessThan(fillTakerTokenAmount) - ? remainingTakerTokenAmount - : fillTakerTokenAmount; - await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - filledTakerTokenAmount, - takerAddress, - zrxTokenAddress, - ); - - const wouldRoundingErrorOccur = await this._exchangeWrapper.isRoundingErrorAsync( - filledTakerTokenAmount, - signedOrder.takerTokenAmount, - signedOrder.makerTokenAmount, - ); - if (wouldRoundingErrorOccur) { - throw new Error(ExchangeContractErrs.OrderFillRoundingError); - } - return filledTakerTokenAmount; - } - public async validateFillOrKillOrderThrowIfInvalidAsync( - exchangeTradeEmulator: ExchangeTransferSimulator, - signedOrder: SignedOrder, - fillTakerTokenAmount: BigNumber, - takerAddress: string, - zrxTokenAddress: string, - ): Promise<void> { - const filledTakerTokenAmount = await this.validateFillOrderThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - fillTakerTokenAmount, - takerAddress, - zrxTokenAddress, - ); - if (filledTakerTokenAmount !== fillTakerTokenAmount) { - throw new Error(ExchangeContractErrs.InsufficientRemainingFillAmount); - } - } -} diff --git a/packages/0x.js/src/utils/utils.ts b/packages/0x.js/src/utils/utils.ts deleted file mode 100644 index af1125632..000000000 --- a/packages/0x.js/src/utils/utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { BigNumber } from '@0xproject/utils'; - -export const utils = { - spawnSwitchErr(name: string, value: any): Error { - return new Error(`Unexpected switch value: ${value} encountered for ${name}`); - }, - getCurrentUnixTimestampSec(): BigNumber { - return new BigNumber(Date.now() / 1000).round(); - }, - getCurrentUnixTimestampMs(): BigNumber { - return new BigNumber(Date.now()); - }, -}; |