From b36587fac833f4fa35aaed49e4ee05f6ce347a02 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Mon, 30 Apr 2018 18:05:45 +1000 Subject: Execute taker side in trade simulation Fill if the taker address is open --- .../0x.js/src/utils/exchange_transfer_simulator.ts | 6 ++++++ packages/0x.js/src/utils/order_validation_utils.ts | 25 +++------------------- 2 files changed, 9 insertions(+), 22 deletions(-) (limited to 'packages/0x.js/src') diff --git a/packages/0x.js/src/utils/exchange_transfer_simulator.ts b/packages/0x.js/src/utils/exchange_transfer_simulator.ts index 9a920c643..ccefea930 100644 --- a/packages/0x.js/src/utils/exchange_transfer_simulator.ts +++ b/packages/0x.js/src/utils/exchange_transfer_simulator.ts @@ -5,6 +5,7 @@ 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', @@ -66,6 +67,11 @@ export class ExchangeTransferSimulator { tradeSide: TradeSide, transferType: TransferType, ): Promise { + // If we are simulating an open order then 0x0 will have no balance or allowance + 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)) { diff --git a/packages/0x.js/src/utils/order_validation_utils.ts b/packages/0x.js/src/utils/order_validation_utils.ts index f32bf43d0..b320a3e92 100644 --- a/packages/0x.js/src/utils/order_validation_utils.ts +++ b/packages/0x.js/src/utils/order_validation_utils.ts @@ -124,31 +124,12 @@ export class OrderValidationUtils { if (!_.isUndefined(expectedFillTakerTokenAmount)) { fillTakerTokenAmount = expectedFillTakerTokenAmount; } - const fillMakerTokenAmount = OrderValidationUtils._getPartialAmount( + await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync( + exchangeTradeEmulator, + signedOrder, fillTakerTokenAmount, - signedOrder.takerTokenAmount, - signedOrder.makerTokenAmount, - ); - await exchangeTradeEmulator.transferFromAsync( - signedOrder.makerTokenAddress, - signedOrder.maker, signedOrder.taker, - fillMakerTokenAmount, - TradeSide.Maker, - TransferType.Trade, - ); - const makerFeeAmount = OrderValidationUtils._getPartialAmount( - fillTakerTokenAmount, - signedOrder.takerTokenAmount, - signedOrder.makerFee, - ); - await exchangeTradeEmulator.transferFromAsync( zrxTokenAddress, - signedOrder.maker, - signedOrder.feeRecipient, - makerFeeAmount, - TradeSide.Maker, - TransferType.Fee, ); } public async validateFillOrderThrowIfInvalidAsync( -- cgit v1.2.3 From 8e7937bdb61887ea3df66a602a275f5643e6585c Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Tue, 1 May 2018 19:06:17 +1000 Subject: Update comment to be more descriptive of null address in exchange simulator --- packages/0x.js/src/utils/exchange_transfer_simulator.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'packages/0x.js/src') diff --git a/packages/0x.js/src/utils/exchange_transfer_simulator.ts b/packages/0x.js/src/utils/exchange_transfer_simulator.ts index ccefea930..f8301f5c2 100644 --- a/packages/0x.js/src/utils/exchange_transfer_simulator.ts +++ b/packages/0x.js/src/utils/exchange_transfer_simulator.ts @@ -67,7 +67,9 @@ export class ExchangeTransferSimulator { tradeSide: TradeSide, transferType: TransferType, ): Promise { - // If we are simulating an open order then 0x0 will have no balance or allowance + // 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; -- cgit v1.2.3 From 0499541e114e6dd36565428f4f914e0dbdece2b8 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Tue, 24 Apr 2018 16:36:35 +0200 Subject: Move order utils to @0xproject/order-utils --- packages/0x.js/src/0x.ts | 144 +++++++-------------- .../src/contract_wrappers/ether_token_wrapper.ts | 2 +- .../src/contract_wrappers/exchange_wrapper.ts | 8 +- .../contract_wrappers/token_registry_wrapper.ts | 2 +- .../token_transfer_proxy_wrapper.ts | 2 +- .../0x.js/src/contract_wrappers/token_wrapper.ts | 2 +- packages/0x.js/src/order_watcher/event_watcher.ts | 2 +- .../0x.js/src/order_watcher/order_state_watcher.ts | 2 +- packages/0x.js/src/types.ts | 1 - packages/0x.js/src/utils/assert.ts | 35 ----- packages/0x.js/src/utils/constants.ts | 1 - packages/0x.js/src/utils/order_validation_utils.ts | 7 +- packages/0x.js/src/utils/signature_utils.ts | 45 ------- packages/0x.js/src/utils/utils.ts | 50 ------- 14 files changed, 64 insertions(+), 239 deletions(-) delete mode 100644 packages/0x.js/src/utils/assert.ts delete mode 100644 packages/0x.js/src/utils/signature_utils.ts (limited to 'packages/0x.js/src') diff --git a/packages/0x.js/src/0x.ts b/packages/0x.js/src/0x.ts index 94d97c23e..780d1b52a 100644 --- a/packages/0x.js/src/0x.ts +++ b/packages/0x.js/src/0x.ts @@ -1,4 +1,12 @@ import { schemas, SchemaValidator } from '@0xproject/json-schemas'; +import { + assert, + generatePseudoRandomSalt, + getOrderHashHex, + isValidOrderHash, + isValidSignature, + signOrderHashAsync, +} from '@0xproject/order-utils'; import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types'; import { AbiDecoder, BigNumber, intervalUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -16,10 +24,8 @@ import { zeroExConfigSchema } from './schemas/zero_ex_config_schema'; import { zeroExPrivateNetworkConfigSchema } from './schemas/zero_ex_private_network_config_schema'; import { zeroExPublicNetworkConfigSchema } from './schemas/zero_ex_public_network_config_schema'; import { OrderStateWatcherConfig, ZeroExConfig, ZeroExError } from './types'; -import { assert } from './utils/assert'; import { constants } from './utils/constants'; import { decorators } from './utils/decorators'; -import { signatureUtils } from './utils/signature_utils'; import { utils } from './utils/utils'; /** @@ -33,6 +39,36 @@ export class ZeroEx { * this constant for your convenience. */ public static NULL_ADDRESS = constants.NULL_ADDRESS; + /** + * Generates a pseudo-random 256-bit salt. + * The salt can be included in a 0x order, ensuring that the order generates a unique orderHash + * and will not collide with other outstanding orders that are identical in all other parameters. + * @return A pseudo-random 256-bit number that can be used as a salt. + */ + public static generatePseudoRandomSalt = generatePseudoRandomSalt; + /** + * Verifies that the elliptic curve signature `signature` was generated + * by signing `data` with the private key corresponding to the `signerAddress` address. + * @param data The hex encoded data signed by the supplied signature. + * @param signature An object containing the elliptic curve signature parameters. + * @param signerAddress The hex encoded address that signed the data, producing the supplied signature. + * @return Whether the signature is valid for the supplied signerAddress and data. + */ + public static isValidSignature = isValidSignature; + /** + * Computes the orderHash for a supplied order. + * @param order An object that conforms to the Order or SignedOrder interface definitions. + * @return The resulting orderHash from hashing the supplied order. + */ + public static getOrderHashHex = getOrderHashHex; + /** + * Checks if the supplied hex encoded order hash is valid. + * Note: Valid means it has the expected format, not that an order with the orderHash exists. + * Use this method when processing orderHashes submitted as user input. + * @param orderHash Hex encoded orderHash. + * @return Whether the supplied orderHash has the expected format. + */ + public static isValidOrderHash = isValidOrderHash; /** * An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract. @@ -58,52 +94,6 @@ export class ZeroEx { */ public proxy: TokenTransferProxyWrapper; private _web3Wrapper: Web3Wrapper; - /** - * Verifies that the elliptic curve signature `signature` was generated - * by signing `data` with the private key corresponding to the `signerAddress` address. - * @param data The hex encoded data signed by the supplied signature. - * @param signature An object containing the elliptic curve signature parameters. - * @param signerAddress The hex encoded address that signed the data, producing the supplied signature. - * @return Whether the signature is valid for the supplied signerAddress and data. - */ - public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean { - assert.isHexString('data', data); - assert.doesConformToSchema('signature', signature, schemas.ecSignatureSchema); - assert.isETHAddressHex('signerAddress', signerAddress); - const normalizedSignerAddress = signerAddress.toLowerCase(); - - const isValidSignature = signatureUtils.isValidSignature(data, signature, normalizedSignerAddress); - return isValidSignature; - } - /** - * Generates a pseudo-random 256-bit salt. - * The salt can be included in a 0x order, ensuring that the order generates a unique orderHash - * and will not collide with other outstanding orders that are identical in all other parameters. - * @return A pseudo-random 256-bit number that can be used as a salt. - */ - public static generatePseudoRandomSalt(): BigNumber { - // BigNumber.random returns a pseudo-random number between 0 & 1 with a passed in number of decimal places. - // Source: https://mikemcl.github.io/bignumber.js/#random - const randomNumber = BigNumber.random(constants.MAX_DIGITS_IN_UNSIGNED_256_INT); - const factor = new BigNumber(10).pow(constants.MAX_DIGITS_IN_UNSIGNED_256_INT - 1); - const salt = randomNumber.times(factor).round(); - return salt; - } - /** - * Checks if the supplied hex encoded order hash is valid. - * Note: Valid means it has the expected format, not that an order with the orderHash exists. - * Use this method when processing orderHashes submitted as user input. - * @param orderHash Hex encoded orderHash. - * @return Whether the supplied orderHash has the expected format. - */ - public static isValidOrderHash(orderHash: string): boolean { - // Since this method can be called to check if any arbitrary string conforms to an orderHash's - // format, we only assert that we were indeed passed a string. - assert.isString('orderHash', orderHash); - const schemaValidator = new SchemaValidator(); - const isValidOrderHash = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid; - return isValidOrderHash; - } /** * A unit amount is defined as the amount of a token above the specified decimal places (integer part). * E.g: If a currency has 18 decimal places, 1e18 or one quintillion of the currency is equivalent @@ -132,17 +122,6 @@ export class ZeroEx { const baseUnitAmount = Web3Wrapper.toBaseUnitAmount(amount, decimals); return baseUnitAmount; } - /** - * Computes the orderHash for a supplied order. - * @param order An object that conforms to the Order or SignedOrder interface definitions. - * @return The resulting orderHash from hashing the supplied order. - */ - @decorators.syncZeroExErrorHandler - public static getOrderHashHex(order: Order | SignedOrder): string { - assert.doesConformToSchema('order', order, schemas.orderSchema); - const orderHashHex = utils.getOrderHashHex(order); - return orderHashHex; - } /** * Instantiates a new ZeroEx instance that provides the public interface to the 0x.js library. * @param provider The Provider instance you would like the 0x.js library to use for interacting with @@ -204,6 +183,12 @@ export class ZeroEx { (this.etherToken as any)._invalidateContractInstance(); (this.etherToken as any)._setNetworkId(networkId); } + /** + * Get the provider instance currently used by 0x.js + */ + public getProvider(): Provider { + return this._web3Wrapper.getProvider(); + } /** * Get user Ethereum addresses available through the supplied web3 provider available for sending transactions. * @return An array of available user Ethereum addresses. @@ -229,41 +214,12 @@ export class ZeroEx { signerAddress: string, shouldAddPersonalMessagePrefix: boolean, ): Promise { - assert.isHexString('orderHash', orderHash); - await assert.isSenderAddressAsync('signerAddress', signerAddress, this._web3Wrapper); - const normalizedSignerAddress = signerAddress.toLowerCase(); - - let msgHashHex = orderHash; - if (shouldAddPersonalMessagePrefix) { - const orderHashBuff = ethUtil.toBuffer(orderHash); - const msgHashBuff = ethUtil.hashPersonalMessage(orderHashBuff); - msgHashHex = ethUtil.bufferToHex(msgHashBuff); - } - - const signature = await this._web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex); - - // HACK: There is no consensus on whether the signatureHex string should be formatted as - // v + r + s OR r + s + v, and different clients (even different versions of the same client) - // return the signature params in different orders. In order to support all client implementations, - // we parse the signature in both ways, and evaluate if either one is a valid signature. - const validVParamValues = [27, 28]; - const ecSignatureVRS = signatureUtils.parseSignatureHexAsVRS(signature); - if (_.includes(validVParamValues, ecSignatureVRS.v)) { - const isValidVRSSignature = ZeroEx.isValidSignature(orderHash, ecSignatureVRS, normalizedSignerAddress); - if (isValidVRSSignature) { - return ecSignatureVRS; - } - } - - const ecSignatureRSV = signatureUtils.parseSignatureHexAsRSV(signature); - if (_.includes(validVParamValues, ecSignatureRSV.v)) { - const isValidRSVSignature = ZeroEx.isValidSignature(orderHash, ecSignatureRSV, normalizedSignerAddress); - if (isValidRSVSignature) { - return ecSignatureRSV; - } - } - - throw new Error(ZeroExError.InvalidSignature); + return signOrderHashAsync( + this._web3Wrapper.getProvider(), + orderHash, + signerAddress, + shouldAddPersonalMessagePrefix, + ); } /** * Waits for a transaction to be mined and returns the transaction receipt. diff --git a/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts b/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts index fd39de34b..8a8caa4dc 100644 --- a/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts @@ -1,4 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; +import { assert } from '@0xproject/order-utils'; import { LogWithDecodedArgs } from '@0xproject/types'; import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -6,7 +7,6 @@ import * as _ from 'lodash'; import { artifacts } from '../artifacts'; import { BlockRange, EventCallback, IndexedFilterValues, TransactionOpts, ZeroExError } from '../types'; -import { assert } from '../utils/assert'; import { ContractWrapper } from './contract_wrapper'; import { EtherTokenContract, EtherTokenContractEventArgs, EtherTokenEvents } from './generated/ether_token'; diff --git a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts index 7cda70f16..5dca61ab3 100644 --- a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts @@ -1,4 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; +import { assert, getOrderHashHex } from '@0xproject/order-utils'; import { BlockParamLiteral, DecodedLogArgs, @@ -30,7 +31,6 @@ import { OrderValues, ValidateOrderFillableOpts, } from '../types'; -import { assert } from '../utils/assert'; import { decorators } from '../utils/decorators'; import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator'; import { OrderStateUtils } from '../utils/order_state_utils'; @@ -570,7 +570,7 @@ export class ExchangeWrapper extends ContractWrapper { ? SHOULD_VALIDATE_BY_DEFAULT : orderTransactionOpts.shouldValidate; if (shouldValidate) { - const orderHash = utils.getOrderHashHex(order); + const orderHash = getOrderHashHex(order); const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); OrderValidationUtils.validateCancelOrderThrowIfInvalid( order, @@ -629,7 +629,7 @@ export class ExchangeWrapper extends ContractWrapper { : orderTransactionOpts.shouldValidate; if (shouldValidate) { for (const orderCancellationRequest of orderCancellationRequests) { - const orderHash = utils.getOrderHashHex(orderCancellationRequest.order); + const orderHash = getOrderHashHex(orderCancellationRequest.order); const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); OrderValidationUtils.validateCancelOrderThrowIfInvalid( orderCancellationRequest.order, @@ -801,7 +801,7 @@ export class ExchangeWrapper extends ContractWrapper { ): Promise { assert.doesConformToSchema('order', order, schemas.orderSchema); assert.isValidBaseUnitAmount('cancelTakerTokenAmount', cancelTakerTokenAmount); - const orderHash = utils.getOrderHashHex(order); + const orderHash = getOrderHashHex(order); const unavailableTakerTokenAmount = await this.getUnavailableTakerAmountAsync(orderHash); OrderValidationUtils.validateCancelOrderThrowIfInvalid( order, 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 c4a193264..a1ec91757 100644 --- a/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts @@ -1,9 +1,9 @@ +import { assert } from '@0xproject/order-utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { artifacts } from '../artifacts'; import { Token, TokenMetadata } from '../types'; -import { assert } from '../utils/assert'; import { constants } from '../utils/constants'; import { ContractWrapper } from './contract_wrapper'; diff --git a/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts b/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts index be558b5be..495923ecc 100644 --- a/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts @@ -1,8 +1,8 @@ +import { assert } from '@0xproject/order-utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { artifacts } from '../artifacts'; -import { assert } from '../utils/assert'; import { ContractWrapper } from './contract_wrapper'; import { TokenTransferProxyContract } from './generated/token_transfer_proxy'; diff --git a/packages/0x.js/src/contract_wrappers/token_wrapper.ts b/packages/0x.js/src/contract_wrappers/token_wrapper.ts index 194cfb5aa..6751f46b3 100644 --- a/packages/0x.js/src/contract_wrappers/token_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/token_wrapper.ts @@ -1,4 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; +import { assert } from '@0xproject/order-utils'; import { LogWithDecodedArgs } from '@0xproject/types'; import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -6,7 +7,6 @@ import * as _ from 'lodash'; import { artifacts } from '../artifacts'; import { BlockRange, EventCallback, IndexedFilterValues, MethodOpts, TransactionOpts, ZeroExError } from '../types'; -import { assert } from '../utils/assert'; import { constants } from '../utils/constants'; import { ContractWrapper } from './contract_wrapper'; diff --git a/packages/0x.js/src/order_watcher/event_watcher.ts b/packages/0x.js/src/order_watcher/event_watcher.ts index de5a99a46..545b352a4 100644 --- a/packages/0x.js/src/order_watcher/event_watcher.ts +++ b/packages/0x.js/src/order_watcher/event_watcher.ts @@ -1,10 +1,10 @@ +import { assert } from '@0xproject/order-utils'; import { BlockParamLiteral, LogEntry } from '@0xproject/types'; import { intervalUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { EventWatcherCallback, ZeroExError } from '../types'; -import { assert } from '../utils/assert'; const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200; 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 a9df8ac9d..008db6bc4 100644 --- a/packages/0x.js/src/order_watcher/order_state_watcher.ts +++ b/packages/0x.js/src/order_watcher/order_state_watcher.ts @@ -1,4 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; +import { assert } from '@0xproject/order-utils'; import { BlockParamLiteral, LogWithDecodedArgs, SignedOrder } from '@0xproject/types'; import { AbiDecoder, intervalUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -33,7 +34,6 @@ import { OrderStateWatcherConfig, ZeroExError, } from '../types'; -import { assert } from '../utils/assert'; import { OrderStateUtils } from '../utils/order_state_utils'; import { utils } from '../utils/utils'; diff --git a/packages/0x.js/src/types.ts b/packages/0x.js/src/types.ts index 151204928..ae9f98c5f 100644 --- a/packages/0x.js/src/types.ts +++ b/packages/0x.js/src/types.ts @@ -27,7 +27,6 @@ export enum ZeroExError { TokenContractDoesNotExist = 'TOKEN_CONTRACT_DOES_NOT_EXIST', UnhandledError = 'UNHANDLED_ERROR', UserHasNoAssociatedAddress = 'USER_HAS_NO_ASSOCIATED_ADDRESSES', - InvalidSignature = 'INVALID_SIGNATURE', ContractNotDeployedOnNetwork = 'CONTRACT_NOT_DEPLOYED_ON_NETWORK', InsufficientAllowanceForTransfer = 'INSUFFICIENT_ALLOWANCE_FOR_TRANSFER', InsufficientBalanceForTransfer = 'INSUFFICIENT_BALANCE_FOR_TRANSFER', diff --git a/packages/0x.js/src/utils/assert.ts b/packages/0x.js/src/utils/assert.ts deleted file mode 100644 index 5e8004cd0..000000000 --- a/packages/0x.js/src/utils/assert.ts +++ /dev/null @@ -1,35 +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 { signatureUtils } from '../utils/signature_utils'; - -export const assert = { - ...sharedAssert, - isValidSignature(orderHash: string, ecSignature: ECSignature, signerAddress: string) { - const isValidSignature = signatureUtils.isValidSignature(orderHash, ecSignature, signerAddress); - this.assert(isValidSignature, `Expected order with hash '${orderHash}' to have a valid signature`); - }, - async isSenderAddressAsync( - variableName: string, - senderAddressHex: string, - web3Wrapper: Web3Wrapper, - ): Promise { - sharedAssert.isETHAddressHex(variableName, senderAddressHex); - const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex); - sharedAssert.assert( - isSenderAddressAvailable, - `Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`, - ); - }, - async isUserAddressAvailableAsync(web3Wrapper: Web3Wrapper): Promise { - const availableAddresses = await web3Wrapper.getAvailableAddressesAsync(); - this.assert(!_.isEmpty(availableAddresses), 'No addresses were available on the provided web3 provider'); - }, -}; diff --git a/packages/0x.js/src/utils/constants.ts b/packages/0x.js/src/utils/constants.ts index 06beec8e2..07da6745d 100644 --- a/packages/0x.js/src/utils/constants.ts +++ b/packages/0x.js/src/utils/constants.ts @@ -3,7 +3,6 @@ import { BigNumber } from '@0xproject/utils'; export const constants = { NULL_ADDRESS: '0x0000000000000000000000000000000000000000', TESTRPC_NETWORK_ID: 50, - MAX_DIGITS_IN_UNSIGNED_256_INT: 78, 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', diff --git a/packages/0x.js/src/utils/order_validation_utils.ts b/packages/0x.js/src/utils/order_validation_utils.ts index b320a3e92..a13c3dc04 100644 --- a/packages/0x.js/src/utils/order_validation_utils.ts +++ b/packages/0x.js/src/utils/order_validation_utils.ts @@ -1,3 +1,4 @@ +import { getOrderHashHex, OrderError } from '@0xproject/order-utils'; import { Order, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; @@ -113,7 +114,7 @@ export class OrderValidationUtils { zrxTokenAddress: string, expectedFillTakerTokenAmount?: BigNumber, ): Promise { - const orderHash = utils.getOrderHashHex(signedOrder); + const orderHash = getOrderHashHex(signedOrder); const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow( signedOrder.takerTokenAmount, @@ -142,9 +143,9 @@ export class OrderValidationUtils { if (fillTakerTokenAmount.eq(0)) { throw new Error(ExchangeContractErrs.OrderFillAmountZero); } - const orderHash = utils.getOrderHashHex(signedOrder); + const orderHash = getOrderHashHex(signedOrder); if (!ZeroEx.isValidSignature(orderHash, signedOrder.ecSignature, signedOrder.maker)) { - throw new Error(ZeroExError.InvalidSignature); + throw new Error(OrderError.InvalidSignature); } const unavailableTakerTokenAmount = await this._exchangeWrapper.getUnavailableTakerAmountAsync(orderHash); OrderValidationUtils._validateRemainingFillAmountNotZeroOrThrow( diff --git a/packages/0x.js/src/utils/signature_utils.ts b/packages/0x.js/src/utils/signature_utils.ts deleted file mode 100644 index 46f167339..000000000 --- a/packages/0x.js/src/utils/signature_utils.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { ECSignature } from '@0xproject/types'; -import * as ethUtil from 'ethereumjs-util'; - -export const signatureUtils = { - isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean { - const dataBuff = ethUtil.toBuffer(data); - const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff); - try { - const pubKey = ethUtil.ecrecover( - msgHashBuff, - signature.v, - ethUtil.toBuffer(signature.r), - ethUtil.toBuffer(signature.s), - ); - const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey)); - return retrievedAddress === signerAddress; - } catch (err) { - return false; - } - }, - parseSignatureHexAsVRS(signatureHex: string): ECSignature { - const signatureBuffer = ethUtil.toBuffer(signatureHex); - let v = signatureBuffer[0]; - if (v < 27) { - v += 27; - } - const r = signatureBuffer.slice(1, 33); - const s = signatureBuffer.slice(33, 65); - const ecSignature: ECSignature = { - v, - r: ethUtil.bufferToHex(r), - s: ethUtil.bufferToHex(s), - }; - return ecSignature; - }, - parseSignatureHexAsRSV(signatureHex: string): ECSignature { - const { v, r, s } = ethUtil.fromRpcSig(signatureHex); - const ecSignature: ECSignature = { - v, - r: ethUtil.bufferToHex(r), - s: ethUtil.bufferToHex(s), - }; - return ecSignature; - }, -}; diff --git a/packages/0x.js/src/utils/utils.ts b/packages/0x.js/src/utils/utils.ts index c8bcd907e..af1125632 100644 --- a/packages/0x.js/src/utils/utils.ts +++ b/packages/0x.js/src/utils/utils.ts @@ -1,59 +1,9 @@ -import { Order, SignedOrder, SolidityTypes } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; -import BN = require('bn.js'); -import * as ethABI from 'ethereumjs-abi'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; export const utils = { - /** - * Converts BigNumber instance to BN - * The only reason we convert to BN is to remain compatible with `ethABI. soliditySHA3` that - * expects values of Solidity type `uint` to be passed as type `BN`. - * We do not use BN anywhere else in the codebase. - */ - bigNumberToBN(value: BigNumber) { - return new BN(value.toString(), 10); - }, spawnSwitchErr(name: string, value: any): Error { return new Error(`Unexpected switch value: ${value} encountered for ${name}`); }, - getOrderHashHex(order: Order | SignedOrder): string { - const orderParts = [ - { value: order.exchangeContractAddress, type: SolidityTypes.Address }, - { value: order.maker, type: SolidityTypes.Address }, - { value: order.taker, type: SolidityTypes.Address }, - { value: order.makerTokenAddress, type: SolidityTypes.Address }, - { value: order.takerTokenAddress, type: SolidityTypes.Address }, - { value: order.feeRecipient, type: SolidityTypes.Address }, - { - value: utils.bigNumberToBN(order.makerTokenAmount), - type: SolidityTypes.Uint256, - }, - { - value: utils.bigNumberToBN(order.takerTokenAmount), - type: SolidityTypes.Uint256, - }, - { - value: utils.bigNumberToBN(order.makerFee), - type: SolidityTypes.Uint256, - }, - { - value: utils.bigNumberToBN(order.takerFee), - type: SolidityTypes.Uint256, - }, - { - value: utils.bigNumberToBN(order.expirationUnixTimestampSec), - type: SolidityTypes.Uint256, - }, - { value: utils.bigNumberToBN(order.salt), type: SolidityTypes.Uint256 }, - ]; - const types = _.map(orderParts, o => o.type); - const values = _.map(orderParts, o => o.value); - const hashBuff = ethABI.soliditySHA3(types, values); - const hashHex = ethUtil.bufferToHex(hashBuff); - return hashHex; - }, getCurrentUnixTimestampSec(): BigNumber { return new BigNumber(Date.now() / 1000).round(); }, -- cgit v1.2.3 From adaff92c9243e7e13737f92cf4b6ade77ebd6e43 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 2 May 2018 15:25:30 +0300 Subject: Create wrapper functions so that docs render properly --- packages/0x.js/src/0x.ts | 66 +++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 29 deletions(-) (limited to 'packages/0x.js/src') diff --git a/packages/0x.js/src/0x.ts b/packages/0x.js/src/0x.ts index 780d1b52a..bf776cd95 100644 --- a/packages/0x.js/src/0x.ts +++ b/packages/0x.js/src/0x.ts @@ -39,13 +39,39 @@ export class ZeroEx { * this constant for your convenience. */ public static NULL_ADDRESS = constants.NULL_ADDRESS; + /** + * An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract. + */ + public exchange: ExchangeWrapper; + /** + * An instance of the TokenRegistryWrapper class containing methods for interacting with the 0x + * TokenRegistry smart contract. + */ + public tokenRegistry: TokenRegistryWrapper; + /** + * An instance of the TokenWrapper class containing methods for interacting with any ERC20 token smart contract. + */ + public token: TokenWrapper; + /** + * An instance of the EtherTokenWrapper class containing methods for interacting with the + * wrapped ETH ERC20 token smart contract. + */ + public etherToken: EtherTokenWrapper; + /** + * An instance of the TokenTransferProxyWrapper class containing methods for interacting with the + * tokenTransferProxy smart contract. + */ + public proxy: TokenTransferProxyWrapper; + private _web3Wrapper: Web3Wrapper; /** * Generates a pseudo-random 256-bit salt. * The salt can be included in a 0x order, ensuring that the order generates a unique orderHash * and will not collide with other outstanding orders that are identical in all other parameters. * @return A pseudo-random 256-bit number that can be used as a salt. */ - public static generatePseudoRandomSalt = generatePseudoRandomSalt; + public static generatePseudoRandomSalt(): BigNumber { + return generatePseudoRandomSalt(); + } /** * Verifies that the elliptic curve signature `signature` was generated * by signing `data` with the private key corresponding to the `signerAddress` address. @@ -54,13 +80,17 @@ export class ZeroEx { * @param signerAddress The hex encoded address that signed the data, producing the supplied signature. * @return Whether the signature is valid for the supplied signerAddress and data. */ - public static isValidSignature = isValidSignature; + public static isValidSignature(data: string, signature: ECSignature, signerAddress: string): boolean { + return isValidSignature(data, signature, signerAddress); + } /** * Computes the orderHash for a supplied order. * @param order An object that conforms to the Order or SignedOrder interface definitions. * @return The resulting orderHash from hashing the supplied order. */ - public static getOrderHashHex = getOrderHashHex; + public static getOrderHashHex(order: Order | SignedOrder): string { + return getOrderHashHex(order); + } /** * Checks if the supplied hex encoded order hash is valid. * Note: Valid means it has the expected format, not that an order with the orderHash exists. @@ -68,32 +98,9 @@ export class ZeroEx { * @param orderHash Hex encoded orderHash. * @return Whether the supplied orderHash has the expected format. */ - public static isValidOrderHash = isValidOrderHash; - - /** - * An instance of the ExchangeWrapper class containing methods for interacting with the 0x Exchange smart contract. - */ - public exchange: ExchangeWrapper; - /** - * An instance of the TokenRegistryWrapper class containing methods for interacting with the 0x - * TokenRegistry smart contract. - */ - public tokenRegistry: TokenRegistryWrapper; - /** - * An instance of the TokenWrapper class containing methods for interacting with any ERC20 token smart contract. - */ - public token: TokenWrapper; - /** - * An instance of the EtherTokenWrapper class containing methods for interacting with the - * wrapped ETH ERC20 token smart contract. - */ - public etherToken: EtherTokenWrapper; - /** - * An instance of the TokenTransferProxyWrapper class containing methods for interacting with the - * tokenTransferProxy smart contract. - */ - public proxy: TokenTransferProxyWrapper; - private _web3Wrapper: Web3Wrapper; + public static isValidOrderHash(orderHash: string): boolean { + return isValidOrderHash(orderHash); + } /** * A unit amount is defined as the amount of a token above the specified decimal places (integer part). * E.g: If a currency has 18 decimal places, 1e18 or one quintillion of the currency is equivalent @@ -185,6 +192,7 @@ export class ZeroEx { } /** * Get the provider instance currently used by 0x.js + * @return Web3 provider instance */ public getProvider(): Provider { return this._web3Wrapper.getProvider(); -- cgit v1.2.3 From a6046af0240d9257a9e9dd80dc4dc5f533df8799 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Wed, 2 May 2018 18:38:38 +0300 Subject: Stop exporting assertions from order-utils --- packages/0x.js/src/0x.ts | 2 +- .../src/contract_wrappers/ether_token_wrapper.ts | 2 +- .../src/contract_wrappers/exchange_wrapper.ts | 3 ++- .../contract_wrappers/token_registry_wrapper.ts | 2 +- .../token_transfer_proxy_wrapper.ts | 2 +- .../0x.js/src/contract_wrappers/token_wrapper.ts | 2 +- packages/0x.js/src/order_watcher/event_watcher.ts | 2 +- .../0x.js/src/order_watcher/order_state_watcher.ts | 2 +- packages/0x.js/src/utils/assert.ts | 31 ++++++++++++++++++++++ 9 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 packages/0x.js/src/utils/assert.ts (limited to 'packages/0x.js/src') diff --git a/packages/0x.js/src/0x.ts b/packages/0x.js/src/0x.ts index bf776cd95..78f9f6beb 100644 --- a/packages/0x.js/src/0x.ts +++ b/packages/0x.js/src/0x.ts @@ -1,6 +1,5 @@ import { schemas, SchemaValidator } from '@0xproject/json-schemas'; import { - assert, generatePseudoRandomSalt, getOrderHashHex, isValidOrderHash, @@ -24,6 +23,7 @@ import { zeroExConfigSchema } from './schemas/zero_ex_config_schema'; import { zeroExPrivateNetworkConfigSchema } from './schemas/zero_ex_private_network_config_schema'; import { zeroExPublicNetworkConfigSchema } from './schemas/zero_ex_public_network_config_schema'; import { OrderStateWatcherConfig, ZeroExConfig, ZeroExError } from './types'; +import { assert } from './utils/assert'; import { constants } from './utils/constants'; import { decorators } from './utils/decorators'; import { utils } from './utils/utils'; diff --git a/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts b/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts index 8a8caa4dc..fd39de34b 100644 --- a/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/ether_token_wrapper.ts @@ -1,5 +1,4 @@ import { schemas } from '@0xproject/json-schemas'; -import { assert } from '@0xproject/order-utils'; import { LogWithDecodedArgs } from '@0xproject/types'; import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -7,6 +6,7 @@ import * as _ from 'lodash'; import { artifacts } from '../artifacts'; import { BlockRange, EventCallback, IndexedFilterValues, TransactionOpts, ZeroExError } from '../types'; +import { assert } from '../utils/assert'; import { ContractWrapper } from './contract_wrapper'; import { EtherTokenContract, EtherTokenContractEventArgs, EtherTokenEvents } from './generated/ether_token'; diff --git a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts index 5dca61ab3..6ddaaaf4f 100644 --- a/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/exchange_wrapper.ts @@ -1,5 +1,5 @@ import { schemas } from '@0xproject/json-schemas'; -import { assert, getOrderHashHex } from '@0xproject/order-utils'; +import { getOrderHashHex } from '@0xproject/order-utils'; import { BlockParamLiteral, DecodedLogArgs, @@ -31,6 +31,7 @@ import { OrderValues, ValidateOrderFillableOpts, } from '../types'; +import { assert } from '../utils/assert'; import { decorators } from '../utils/decorators'; import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator'; import { OrderStateUtils } from '../utils/order_state_utils'; 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 a1ec91757..c4a193264 100644 --- a/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/token_registry_wrapper.ts @@ -1,9 +1,9 @@ -import { assert } from '@0xproject/order-utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { artifacts } from '../artifacts'; import { Token, TokenMetadata } from '../types'; +import { assert } from '../utils/assert'; import { constants } from '../utils/constants'; import { ContractWrapper } from './contract_wrapper'; diff --git a/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts b/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts index 495923ecc..be558b5be 100644 --- a/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/token_transfer_proxy_wrapper.ts @@ -1,8 +1,8 @@ -import { assert } from '@0xproject/order-utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { artifacts } from '../artifacts'; +import { assert } from '../utils/assert'; import { ContractWrapper } from './contract_wrapper'; import { TokenTransferProxyContract } from './generated/token_transfer_proxy'; diff --git a/packages/0x.js/src/contract_wrappers/token_wrapper.ts b/packages/0x.js/src/contract_wrappers/token_wrapper.ts index 6751f46b3..194cfb5aa 100644 --- a/packages/0x.js/src/contract_wrappers/token_wrapper.ts +++ b/packages/0x.js/src/contract_wrappers/token_wrapper.ts @@ -1,5 +1,4 @@ import { schemas } from '@0xproject/json-schemas'; -import { assert } from '@0xproject/order-utils'; import { LogWithDecodedArgs } from '@0xproject/types'; import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -7,6 +6,7 @@ import * as _ from 'lodash'; import { artifacts } from '../artifacts'; import { BlockRange, EventCallback, IndexedFilterValues, MethodOpts, TransactionOpts, ZeroExError } from '../types'; +import { assert } from '../utils/assert'; import { constants } from '../utils/constants'; import { ContractWrapper } from './contract_wrapper'; diff --git a/packages/0x.js/src/order_watcher/event_watcher.ts b/packages/0x.js/src/order_watcher/event_watcher.ts index 545b352a4..de5a99a46 100644 --- a/packages/0x.js/src/order_watcher/event_watcher.ts +++ b/packages/0x.js/src/order_watcher/event_watcher.ts @@ -1,10 +1,10 @@ -import { assert } from '@0xproject/order-utils'; import { BlockParamLiteral, LogEntry } from '@0xproject/types'; import { intervalUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import { EventWatcherCallback, ZeroExError } from '../types'; +import { assert } from '../utils/assert'; const DEFAULT_EVENT_POLLING_INTERVAL_MS = 200; 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 008db6bc4..a9df8ac9d 100644 --- a/packages/0x.js/src/order_watcher/order_state_watcher.ts +++ b/packages/0x.js/src/order_watcher/order_state_watcher.ts @@ -1,5 +1,4 @@ import { schemas } from '@0xproject/json-schemas'; -import { assert } from '@0xproject/order-utils'; import { BlockParamLiteral, LogWithDecodedArgs, SignedOrder } from '@0xproject/types'; import { AbiDecoder, intervalUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -34,6 +33,7 @@ import { OrderStateWatcherConfig, ZeroExError, } from '../types'; +import { assert } from '../utils/assert'; import { OrderStateUtils } from '../utils/order_state_utils'; import { utils } from '../utils/utils'; diff --git a/packages/0x.js/src/utils/assert.ts b/packages/0x.js/src/utils/assert.ts new file mode 100644 index 000000000..2588a4d09 --- /dev/null +++ b/packages/0x.js/src/utils/assert.ts @@ -0,0 +1,31 @@ +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 { + sharedAssert.isETHAddressHex(variableName, senderAddressHex); + const isSenderAddressAvailable = await web3Wrapper.isSenderAddressAvailableAsync(senderAddressHex); + sharedAssert.assert( + isSenderAddressAvailable, + `Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`, + ); + }, +}; -- cgit v1.2.3