diff options
author | Fabio Berger <me@fabioberger.com> | 2018-07-19 23:48:06 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-07-19 23:48:06 +0800 |
commit | d8898cf9a30cc349868afcf2b78e6369e57aa726 (patch) | |
tree | f96d1aa76c7e5aa9e3311d5cdbd0d31c8ec8d7fb /packages/order-utils | |
parent | 1aaf633df883f62fad890b2d87a2dc89067821c5 (diff) | |
parent | 3de88d5345c7a4549bc69e2ca28f0601f5d42189 (diff) | |
download | dexon-sol-tools-d8898cf9a30cc349868afcf2b78e6369e57aa726.tar dexon-sol-tools-d8898cf9a30cc349868afcf2b78e6369e57aa726.tar.gz dexon-sol-tools-d8898cf9a30cc349868afcf2b78e6369e57aa726.tar.bz2 dexon-sol-tools-d8898cf9a30cc349868afcf2b78e6369e57aa726.tar.lz dexon-sol-tools-d8898cf9a30cc349868afcf2b78e6369e57aa726.tar.xz dexon-sol-tools-d8898cf9a30cc349868afcf2b78e6369e57aa726.tar.zst dexon-sol-tools-d8898cf9a30cc349868afcf2b78e6369e57aa726.zip |
merge v2-prototype
Diffstat (limited to 'packages/order-utils')
18 files changed, 212 insertions, 90 deletions
diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json index 715d58a43..e61033c53 100644 --- a/packages/order-utils/CHANGELOG.json +++ b/packages/order-utils/CHANGELOG.json @@ -9,6 +9,19 @@ { "note": "Export parseECSignature method", "pr": 684 + }, + { + "note": "Handle Typed Arrays when hashing data", + "pr": 894 + } + ] + }, + { + "timestamp": 1531919263, + "version": "0.0.9", + "changes": [ + { + "note": "Dependencies updated" } ] }, diff --git a/packages/order-utils/CHANGELOG.md b/packages/order-utils/CHANGELOG.md index 672affc19..17464a966 100644 --- a/packages/order-utils/CHANGELOG.md +++ b/packages/order-utils/CHANGELOG.md @@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only. CHANGELOG +## v0.0.9 - _July 18, 2018_ + + * Dependencies updated + ## v0.0.8 - _July 9, 2018_ * Dependencies updated diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index 8f5041609..1ac2804d7 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -51,10 +51,9 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/packages/order-utils/README.md", "devDependencies": { - "@0xproject/dev-utils": "^0.4.5", + "@0xproject/dev-utils": "^0.4.6", "@0xproject/monorepo-scripts": "^0.2.2", "@0xproject/tslint-config": "^0.4.21", - "@types/ethereumjs-abi": "^0.6.0", "@types/bn.js": "^4.11.0", "@types/lodash": "4.14.104", "chai": "^4.0.1", @@ -67,19 +66,19 @@ "npm-run-all": "^4.1.2", "shx": "^0.2.2", "sinon": "^4.0.0", - "tslint": "5.8.0", + "tslint": "5.11.0", "typedoc": "0xProject/typedoc", "typescript": "2.7.1" }, "dependencies": { "@0xproject/assert": "^0.3.0", - "@0xproject/base-contract": "^0.3.5", + "@0xproject/base-contract": "^0.3.6", "@0xproject/json-schemas": "1.0.0", - "@0xproject/sol-compiler": "^0.5.3", + "@0xproject/sol-compiler": "^0.5.4", "@0xproject/types": "^1.0.0", - "@0xproject/typescript-typings": "^0.4.2", - "@0xproject/utils": "^0.7.2", - "@0xproject/web3-wrapper": "^0.7.2", + "@0xproject/typescript-typings": "^0.4.3", + "@0xproject/utils": "^0.7.3", + "@0xproject/web3-wrapper": "^0.7.3", "@types/node": "^8.0.53", "bn.js": "^4.11.8", "ethereum-types": "^0.0.2", diff --git a/packages/order-utils/src/abstract/abstract_order_filled_cancelled_lazy_store.ts b/packages/order-utils/src/abstract/abstract_order_filled_cancelled_lazy_store.ts new file mode 100644 index 000000000..617bcb224 --- /dev/null +++ b/packages/order-utils/src/abstract/abstract_order_filled_cancelled_lazy_store.ts @@ -0,0 +1,12 @@ +import { BigNumber } from '@0xproject/utils'; + +export abstract class AbstractOrderFilledCancelledLazyStore { + public abstract async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber>; + public abstract async getIsCancelledAsync(orderHash: string): Promise<boolean>; + public abstract setFilledTakerAmount(orderHash: string, balance: BigNumber): void; + public abstract deleteFilledTakerAmount(orderHash: string): void; + public abstract setIsCancelled(orderHash: string, isCancelled: boolean): void; + public abstract deleteIsCancelled(orderHash: string): void; + public abstract deleteAll(): void; + public abstract getZRXAssetData(): string; +} diff --git a/packages/order-utils/src/assert.ts b/packages/order-utils/src/assert.ts index b4b57d02a..f8db7ac63 100644 --- a/packages/order-utils/src/assert.ts +++ b/packages/order-utils/src/assert.ts @@ -1,5 +1,5 @@ import { assert as sharedAssert } from '@0xproject/assert'; -// We need those two unused imports because they're actually used by sharedAssert which gets injected here +// HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here // tslint:disable:no-unused-variable import { Schema } from '@0xproject/json-schemas'; import { ECSignature, SignatureType } from '@0xproject/types'; diff --git a/packages/order-utils/src/asset_proxy_utils.ts b/packages/order-utils/src/asset_data_utils.ts index 8140ad89d..a9601e9ea 100644 --- a/packages/order-utils/src/asset_proxy_utils.ts +++ b/packages/order-utils/src/asset_data_utils.ts @@ -1,64 +1,25 @@ import { AssetProxyId, ERC20AssetData, ERC721AssetData } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; -import BN = require('bn.js'); +import ethAbi = require('ethereumjs-abi'); import ethUtil = require('ethereumjs-util'); import { constants } from './constants'; -// TODO: Push upstream to DefinitelyTyped -interface EthAbi { - simpleEncode(signature: string, ...args: any[]): Buffer; - rawDecode(signature: string[], data: Buffer): any[]; -} -// tslint:disable:no-var-requires -const ethAbi = require('ethereumjs-abi') as EthAbi; - -export const assetProxyUtils = { - encodeAssetProxyId(assetProxyId: AssetProxyId): Buffer { - return ethUtil.toBuffer(assetProxyId); - }, - decodeAssetProxyId(encodedAssetProxyId: Buffer): AssetProxyId { - const hexString = ethUtil.bufferToHex(encodedAssetProxyId); - if (hexString === AssetProxyId.ERC20) { - return AssetProxyId.ERC20; - } - if (hexString === AssetProxyId.ERC721) { - return AssetProxyId.ERC721; - } - throw new Error(`Invalid ProxyId: ${hexString}`); - }, - encodeAddress(address: string): Buffer { - if (!ethUtil.isValidAddress(address)) { - throw new Error(`Invalid Address: ${address}`); - } - const encodedAddress = ethUtil.toBuffer(address); - const padded = ethUtil.setLengthLeft(encodedAddress, constants.WORD_LENGTH); - return padded; - }, - decodeAddress(encodedAddress: Buffer): string { - const unpadded = ethUtil.setLengthLeft(encodedAddress, constants.ADDRESS_LENGTH); - const address = ethUtil.bufferToHex(unpadded); - if (!ethUtil.isValidAddress(address)) { - throw new Error(`Invalid Address: ${address}`); - } - return address; - }, - encodeUint256(value: BigNumber): Buffer { - const base = 10; - const formattedValue = new BN(value.toString(base)); - const encodedValue = ethUtil.toBuffer(formattedValue); - // tslint:disable-next-line:custom-no-magic-numbers - const paddedValue = ethUtil.setLengthLeft(encodedValue, constants.WORD_LENGTH); - return paddedValue; - }, - decodeUint256(encodedValue: Buffer): BigNumber { - const formattedValue = ethUtil.bufferToHex(encodedValue); - const value = new BigNumber(formattedValue, constants.BASE_16); - return value; - }, +export const assetDataUtils = { + /** + * Encodes an ERC20 token address into a hex encoded assetData string, usable in the makerAssetData or + * takerAssetData fields in a 0x order. + * @param tokenAddress The ERC20 token address to encode + * @return The hex encoded assetData string + */ encodeERC20AssetData(tokenAddress: string): string { return ethUtil.bufferToHex(ethAbi.simpleEncode('ERC20Token(address)', tokenAddress)); }, + /** + * Decodes an ERC20 assetData hex string into it's corresponding ERC20 tokenAddress & assetProxyId + * @param assetData Hex encoded assetData string to decode + * @return An object containing the decoded tokenAddress & assetProxyId + */ decodeERC20AssetData(assetData: string): ERC20AssetData { const data = ethUtil.toBuffer(assetData); if (data.byteLength < constants.ERC20_ASSET_DATA_BYTE_LENGTH) { @@ -82,6 +43,13 @@ export const assetProxyUtils = { tokenAddress: ethUtil.addHexPrefix(tokenAddress), }; }, + /** + * Encodes an ERC721 token address into a hex encoded assetData string, usable in the makerAssetData or + * takerAssetData fields in a 0x order. + * @param tokenAddress The ERC721 token address to encode + * @param tokenId The ERC721 tokenId to encode + * @return The hex encoded assetData string + */ encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber, receiverData?: string): string { // TODO: Pass `tokendId` as a BigNumber. return ethUtil.bufferToHex( @@ -93,6 +61,11 @@ export const assetProxyUtils = { ), ); }, + /** + * Decodes an ERC721 assetData hex string into it's corresponding ERC721 tokenAddress, tokenId & assetProxyId + * @param assetData Hex encoded assetData string to decode + * @return An object containing the decoded tokenAddress, tokenId & assetProxyId + */ decodeERC721AssetData(assetData: string): ERC721AssetData { const data = ethUtil.toBuffer(assetData); if (data.byteLength < constants.ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH) { @@ -121,30 +94,51 @@ export const assetProxyUtils = { receiverData: ethUtil.bufferToHex(receiverData), }; }, - decodeAssetDataId(assetData: string): AssetProxyId { + /** + * Decode and return the assetProxyId from the assetData + * @param assetData Hex encoded assetData string to decode + * @return The assetProxyId + */ + decodeAssetProxyId(assetData: string): AssetProxyId { const encodedAssetData = ethUtil.toBuffer(assetData); if (encodedAssetData.byteLength < constants.SELECTOR_LENGTH) { throw new Error( - `Could not decode Proxy Data. Expected length of encoded data to be at least 4. Got ${ + `Could not decode assetData. Expected length of encoded data to be at least 4. Got ${ encodedAssetData.byteLength }`, ); } const encodedAssetProxyId = encodedAssetData.slice(0, constants.SELECTOR_LENGTH); - const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId); + const assetProxyId = decodeAssetProxyId(encodedAssetProxyId); return assetProxyId; }, - decodeAssetData(assetData: string): ERC20AssetData | ERC721AssetData { - const assetProxyId = assetProxyUtils.decodeAssetDataId(assetData); + /** + * Decode any assetData into it's corresponding assetData object + * @param assetData Hex encoded assetData string to decode + * @return Either a ERC20 or ERC721 assetData object + */ + decodeAssetDataOrThrow(assetData: string): ERC20AssetData | ERC721AssetData { + const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); switch (assetProxyId) { case AssetProxyId.ERC20: - const erc20AssetData = assetProxyUtils.decodeERC20AssetData(assetData); + const erc20AssetData = assetDataUtils.decodeERC20AssetData(assetData); return erc20AssetData; case AssetProxyId.ERC721: - const erc721AssetData = assetProxyUtils.decodeERC721AssetData(assetData); + const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData); return erc721AssetData; default: throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`); } }, }; + +function decodeAssetProxyId(encodedAssetProxyId: Buffer): AssetProxyId { + const hexString = ethUtil.bufferToHex(encodedAssetProxyId); + if (hexString === AssetProxyId.ERC20) { + return AssetProxyId.ERC20; + } + if (hexString === AssetProxyId.ERC721) { + return AssetProxyId.ERC721; + } + throw new Error(`Invalid ProxyId: ${hexString}`); +} diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts index 383a657b8..bb7482184 100644 --- a/packages/order-utils/src/constants.ts +++ b/packages/order-utils/src/constants.ts @@ -6,7 +6,6 @@ export const constants = { UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), TESTRPC_NETWORK_ID: 50, ADDRESS_LENGTH: 20, - WORD_LENGTH: 32, ERC20_ASSET_DATA_BYTE_LENGTH: 36, ERC721_ASSET_DATA_MINIMUM_BYTE_LENGTH: 53, SELECTOR_LENGTH: 4, diff --git a/packages/order-utils/src/crypto.ts b/packages/order-utils/src/crypto.ts index 517ca2840..0f1504a72 100644 --- a/packages/order-utils/src/crypto.ts +++ b/packages/order-utils/src/crypto.ts @@ -32,7 +32,7 @@ export const crypto = { argTypes.push('address'); } else if (_.isString(arg)) { argTypes.push('string'); - } else if (_.isBuffer(arg)) { + } else if (_.isBuffer(arg) || _.isTypedArray(arg)) { argTypes.push('bytes'); } else if (_.isBoolean(arg)) { argTypes.push('bool'); diff --git a/packages/order-utils/src/exchange_transfer_simulator.ts b/packages/order-utils/src/exchange_transfer_simulator.ts index 72ed85406..c3a4f9c2a 100644 --- a/packages/order-utils/src/exchange_transfer_simulator.ts +++ b/packages/order-utils/src/exchange_transfer_simulator.ts @@ -34,7 +34,7 @@ const ERR_MSG_MAPPING = { }; export class ExchangeTransferSimulator { - private _store: AbstractBalanceAndProxyAllowanceLazyStore; + private readonly _store: AbstractBalanceAndProxyAllowanceLazyStore; private static _throwValidationError( failureReason: FailureReason, tradeSide: TradeSide, diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts index b4a7a6b67..76be63bb8 100644 --- a/packages/order-utils/src/index.ts +++ b/packages/order-utils/src/index.ts @@ -17,9 +17,10 @@ export { OrderError, MessagePrefixType, MessagePrefixOpts, EIP712Parameter, EIP7 export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher'; export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher'; export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store'; +export { OrderFilledCancelledLazyStore } from './store/order_filled_cancelled_lazy_store'; export { RemainingFillableCalculator } from './remaining_fillable_calculator'; export { OrderStateUtils } from './order_state_utils'; -export { assetProxyUtils } from './asset_proxy_utils'; +export { assetDataUtils } from './asset_data_utils'; export { EIP712Utils } from './eip712_utils'; export { OrderValidationUtils } from './order_validation_utils'; export { ExchangeTransferSimulator } from './exchange_transfer_simulator'; diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts index dd45a1298..189bf4180 100644 --- a/packages/order-utils/src/order_state_utils.ts +++ b/packages/order-utils/src/order_state_utils.ts @@ -27,8 +27,8 @@ interface SidedOrderRelevantState { const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001; export class OrderStateUtils { - private _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; - private _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; + private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; + private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; private static _validateIfOrderIsValid( signedOrder: SignedOrder, sidedOrderRelevantState: SidedOrderRelevantState, diff --git a/packages/order-utils/src/order_validation_utils.ts b/packages/order-utils/src/order_validation_utils.ts index 94df3ef82..67d747081 100644 --- a/packages/order-utils/src/order_validation_utils.ts +++ b/packages/order-utils/src/order_validation_utils.ts @@ -13,7 +13,7 @@ import { isValidSignatureAsync } from './signature_utils'; import { utils } from './utils'; export class OrderValidationUtils { - private _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; + private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; public static isRoundingError(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean { // Solidity's mulmod() in JS // Source: https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#mathematical-and-cryptographic-functions diff --git a/packages/order-utils/src/remaining_fillable_calculator.ts b/packages/order-utils/src/remaining_fillable_calculator.ts index 29e19e5ab..7022aa979 100644 --- a/packages/order-utils/src/remaining_fillable_calculator.ts +++ b/packages/order-utils/src/remaining_fillable_calculator.ts @@ -1,14 +1,14 @@ import { BigNumber } from '@0xproject/utils'; export class RemainingFillableCalculator { - private _isTraderAssetZRX: boolean; + private readonly _isTraderAssetZRX: boolean; // Transferrable Amount is the minimum of Approval and Balance - private _transferrableAssetAmount: BigNumber; - private _transferrableFeeAmount: BigNumber; - private _remainingOrderAssetAmount: BigNumber; - private _remainingOrderFeeAmount: BigNumber; - private _orderFee: BigNumber; - private _orderAssetAmount: BigNumber; + private readonly _transferrableAssetAmount: BigNumber; + private readonly _transferrableFeeAmount: BigNumber; + private readonly _remainingOrderAssetAmount: BigNumber; + private readonly _remainingOrderFeeAmount: BigNumber; + private readonly _orderFee: BigNumber; + private readonly _orderAssetAmount: BigNumber; constructor( orderFee: BigNumber, orderAssetAmount: BigNumber, diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts index d8703bfda..26fb24705 100644 --- a/packages/order-utils/src/signature_utils.ts +++ b/packages/order-utils/src/signature_utils.ts @@ -27,6 +27,10 @@ export async function isValidSignatureAsync( signature: string, signerAddress: string, ): Promise<boolean> { + assert.isWeb3Provider('provider', provider); + assert.isHexString('data', data); + assert.isHexString('signature', signature); + assert.isETHAddressHex('signerAddress', signerAddress); const signatureTypeIndexIfExists = utils.getSignatureTypeIndexIfExists(signature); if (_.isUndefined(signatureTypeIndexIfExists)) { throw new Error(`Unrecognized signatureType in signature: ${signature}`); @@ -90,6 +94,9 @@ export async function isValidPresignedSignatureAsync( data: string, signerAddress: string, ): Promise<boolean> { + assert.isWeb3Provider('provider', provider); + assert.isHexString('data', data); + assert.isETHAddressHex('signerAddress', signerAddress); const exchangeContract = new ExchangeContract(artifacts.Exchange.compilerOutput.abi, signerAddress, provider); const isValid = await exchangeContract.preSigned.callAsync(data, signerAddress); return isValid; @@ -108,6 +115,10 @@ export async function isValidWalletSignatureAsync( signature: string, signerAddress: string, ): Promise<boolean> { + assert.isWeb3Provider('provider', provider); + assert.isHexString('data', data); + assert.isHexString('signature', signature); + assert.isETHAddressHex('signerAddress', signerAddress); // tslint:disable-next-line:custom-no-magic-numbers const signatureWithoutType = signature.slice(-2); const walletContract = new IWalletContract(artifacts.IWallet.compilerOutput.abi, signerAddress, provider); @@ -128,6 +139,10 @@ export async function isValidValidatorSignatureAsync( signature: string, signerAddress: string, ): Promise<boolean> { + assert.isWeb3Provider('provider', provider); + assert.isHexString('data', data); + assert.isHexString('signature', signature); + assert.isETHAddressHex('signerAddress', signerAddress); const validatorSignature = parseValidatorSignature(signature); const exchangeContract = new ExchangeContract(artifacts.Exchange.compilerOutput.abi, signerAddress, provider); const isValidatorApproved = await exchangeContract.allowedValidators.callAsync( @@ -192,7 +207,9 @@ export async function ecSignOrderHashAsync( signerAddress: string, messagePrefixOpts: MessagePrefixOpts, ): Promise<ECSignature> { + assert.isWeb3Provider('provider', provider); assert.isHexString('orderHash', orderHash); + assert.isETHAddressHex('signerAddress', signerAddress); const web3Wrapper = new Web3Wrapper(provider); await assert.isSenderAddressAsync('signerAddress', signerAddress, web3Wrapper); const normalizedSignerAddress = signerAddress.toLowerCase(); @@ -237,6 +254,8 @@ export async function ecSignOrderHashAsync( * @return Prefixed message */ export function addSignedMessagePrefix(message: string, messagePrefixType: MessagePrefixType): string { + assert.isString('message', message); + assert.doesBelongToStringEnum('messagePrefixType', messagePrefixType, MessagePrefixType); switch (messagePrefixType) { case MessagePrefixType.None: return message; @@ -266,6 +285,7 @@ export function addSignedMessagePrefix(message: string, messagePrefixType: Messa * @return An ECSignature object with r,s,v parameters */ export function parseECSignature(signature: string): ECSignature { + assert.isHexString('signature', signature); const ecSignatureTypes = [SignatureType.EthSign, SignatureType.EIP712, SignatureType.Trezor]; assert.isOneOfExpectedSignatureTypes(signature, ecSignatureTypes); diff --git a/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts b/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts index e7352119d..5a2c1d7ff 100644 --- a/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts +++ b/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts @@ -1,14 +1,16 @@ +import { AssetProxyId } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import { AbstractBalanceAndProxyAllowanceFetcher } from '../abstract/abstract_balance_and_proxy_allowance_fetcher'; import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store'; +import { assetDataUtils } from '../asset_data_utils'; /** * Copy on read store for balances/proxyAllowances of tokens/accounts */ export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProxyAllowanceLazyStore { - private _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; + private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; private _balance: { [assetData: string]: { [userAddress: string]: BigNumber; @@ -74,6 +76,20 @@ export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProx } } } + public deleteAllERC721ProxyAllowance(tokenAddress: string, userAddress: string): void { + for (const assetData in this._proxyAllowance) { + if (this._proxyAllowance.hasOwnProperty(assetData)) { + const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); + if ( + decodedAssetData.assetProxyId === AssetProxyId.ERC721 && + decodedAssetData.tokenAddress === tokenAddress && + !_.isUndefined(this._proxyAllowance[assetData][userAddress]) + ) { + delete this._proxyAllowance[assetData][userAddress]; + } + } + } + } public deleteAll(): void { this._balance = {}; this._proxyAllowance = {}; diff --git a/packages/order-utils/src/store/order_filled_cancelled_lazy_store.ts b/packages/order-utils/src/store/order_filled_cancelled_lazy_store.ts new file mode 100644 index 000000000..336c6d0ba --- /dev/null +++ b/packages/order-utils/src/store/order_filled_cancelled_lazy_store.ts @@ -0,0 +1,65 @@ +import { BigNumber } from '@0xproject/utils'; +import * as _ from 'lodash'; + +import { AbstractOrderFilledCancelledFetcher } from '../abstract/abstract_order_filled_cancelled_fetcher'; +import { AbstractOrderFilledCancelledLazyStore } from '../abstract/abstract_order_filled_cancelled_lazy_store'; + +/** + * Copy on read store for balances/proxyAllowances of tokens/accounts + */ +export class OrderFilledCancelledLazyStore implements AbstractOrderFilledCancelledLazyStore { + private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; + private _filledTakerAmount: { + [orderHash: string]: BigNumber; + }; + private _isCancelled: { + [orderHash: string]: boolean; + }; + constructor(orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher) { + this._orderFilledCancelledFetcher = orderFilledCancelledFetcher; + this._filledTakerAmount = {}; + this._isCancelled = {}; + } + public async getFilledTakerAmountAsync(orderHash: string): Promise<BigNumber> { + if (_.isUndefined(this._filledTakerAmount[orderHash])) { + const filledTakerAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash); + this.setFilledTakerAmount(orderHash, filledTakerAmount); + } + const cachedFilledTakerAmount = this._filledTakerAmount[orderHash]; + return cachedFilledTakerAmount; + } + public setFilledTakerAmount(orderHash: string, filledTakerAmount: BigNumber): void { + this._filledTakerAmount[orderHash] = filledTakerAmount; + } + public deleteFilledTakerAmount(orderHash: string): void { + delete this._filledTakerAmount[orderHash]; + } + public async getIsCancelledAsync(orderHash: string): Promise<boolean> { + if (_.isUndefined(this._isCancelled[orderHash])) { + const isCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(orderHash); + this.setIsCancelled(orderHash, isCancelled); + } + const cachedIsCancelled = this._isCancelled[orderHash]; // tslint:disable-line:boolean-naming + return cachedIsCancelled; + } + public setIsCancelled(orderHash: string, isCancelled: boolean): void { + this._isCancelled[orderHash] = isCancelled; + } + public deleteIsCancelled(orderHash: string): void { + delete this._isCancelled[orderHash]; + } + public deleteAll(): void { + this.deleteAllFilled(); + this.deleteAllIsCancelled(); + } + public deleteAllIsCancelled(): void { + this._isCancelled = {}; + } + public deleteAllFilled(): void { + this._filledTakerAmount = {}; + } + public getZRXAssetData(): string { + const zrxAssetData = this._orderFilledCancelledFetcher.getZRXAssetData(); + return zrxAssetData; + } +} diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts index 37b2bd712..f5c18cdb9 100644 --- a/packages/order-utils/test/exchange_transfer_simulator_test.ts +++ b/packages/order-utils/test/exchange_transfer_simulator_test.ts @@ -4,7 +4,7 @@ import { BigNumber } from '@0xproject/utils'; import * as chai from 'chai'; import { artifacts } from '../src/artifacts'; -import { assetProxyUtils } from '../src/asset_proxy_utils'; +import { assetDataUtils } from '../src/asset_data_utils'; import { constants } from '../src/constants'; import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator'; import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_erc20_token'; @@ -34,7 +34,7 @@ describe('ExchangeTransferSimulator', async () => { let erc20ProxyAddress: string; before(async function(): Promise<void> { const mochaTestTimeoutMs = 20000; - this.timeout(mochaTestTimeoutMs); + this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this userAddresses = await web3Wrapper.getAvailableAddressesAsync(); [coinbase, sender, recipient] = userAddresses; @@ -66,7 +66,7 @@ describe('ExchangeTransferSimulator', async () => { totalSupply, ); - exampleAssetData = assetProxyUtils.encodeERC20AssetData(dummyERC20Token.address); + exampleAssetData = assetDataUtils.encodeERC20AssetData(dummyERC20Token.address); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -77,8 +77,7 @@ describe('ExchangeTransferSimulator', async () => { describe('#transferFromAsync', function(): void { // HACK: For some reason these tests need a slightly longer timeout const mochaTestTimeoutMs = 3000; - this.timeout(mochaTestTimeoutMs); - + this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this beforeEach(() => { const simpleERC20BalanceAndProxyAllowanceFetcher = new SimpleERC20BalanceAndProxyAllowanceFetcher( (dummyERC20Token as any) as ERC20TokenContract, diff --git a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts index 68f6a164c..279a5c0db 100644 --- a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts +++ b/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts @@ -5,8 +5,8 @@ import { AbstractBalanceAndProxyAllowanceFetcher } from '../../src/abstract/abst import { ERC20TokenContract } from '../../src/generated_contract_wrappers/erc20_token'; export class SimpleERC20BalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher { - private _erc20TokenContract: ERC20TokenContract; - private _erc20ProxyAddress: string; + private readonly _erc20TokenContract: ERC20TokenContract; + private readonly _erc20ProxyAddress: string; constructor(erc20TokenWrapper: ERC20TokenContract, erc20ProxyAddress: string) { this._erc20TokenContract = erc20TokenWrapper; this._erc20ProxyAddress = erc20ProxyAddress; |