From 7ae38906926dc09bc10670c361af0d2bf0050426 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Sat, 19 Jan 2019 18:42:04 +0800 Subject: Update dependency packages --- packages/order-utils/.npmignore | 7 - packages/order-utils/CHANGELOG.json | 424 --------------------- packages/order-utils/CHANGELOG.md | 172 --------- packages/order-utils/README.md | 65 ---- packages/order-utils/coverage/.gitkeep | 0 packages/order-utils/package.json | 76 ---- ...abstract_balance_and_proxy_allowance_fetcher.ts | 23 -- ...tract_balance_and_proxy_allowance_lazy_store.ts | 11 - .../abstract_order_filled_cancelled_fetcher.ts | 23 -- .../abstract_order_filled_cancelled_lazy_store.ts | 13 - packages/order-utils/src/assert.ts | 37 -- packages/order-utils/src/asset_data_utils.ts | 308 --------------- packages/order-utils/src/constants.ts | 109 ------ packages/order-utils/src/crypto.ts | 47 --- packages/order-utils/src/eip712_utils.ts | 83 ---- .../order-utils/src/exchange_transfer_simulator.ts | 153 -------- packages/order-utils/src/index.ts | 63 --- packages/order-utils/src/market_utils.ts | 162 -------- packages/order-utils/src/order_factory.ts | 122 ------ packages/order-utils/src/order_hash.ts | 58 --- packages/order-utils/src/order_state_utils.ts | 346 ----------------- packages/order-utils/src/order_validation_utils.ts | 257 ------------- packages/order-utils/src/parsing_utils.ts | 27 -- packages/order-utils/src/rate_utils.ts | 48 --- .../src/remaining_fillable_calculator.ts | 86 ----- packages/order-utils/src/salt.ts | 18 - packages/order-utils/src/signature_utils.ts | 417 -------------------- packages/order-utils/src/sorting_utils.ts | 54 --- .../balance_and_proxy_allowance_lazy_store.ts | 140 ------- .../src/store/order_filled_cancelled_lazy_store.ts | 113 ------ packages/order-utils/src/types.ts | 66 ---- packages/order-utils/src/utils.ts | 22 -- packages/order-utils/test/assert_test.ts | 34 -- packages/order-utils/test/asset_data_utils_test.ts | 110 ------ packages/order-utils/test/eip712_utils_test.ts | 44 --- .../test/exchange_transfer_simulator_test.ts | 174 --------- packages/order-utils/test/market_utils_test.ts | 267 ------------- packages/order-utils/test/order_hash_test.ts | 77 ---- .../order-utils/test/order_state_utils_test.ts | 145 ------- .../test/order_validation_utils_test.ts | 70 ---- packages/order-utils/test/rate_utils_test.ts | 55 --- .../test/remaining_fillable_calculator_test.ts | 246 ------------ packages/order-utils/test/signature_utils_test.ts | 324 ---------------- packages/order-utils/test/sorting_utils_test.ts | 67 ---- packages/order-utils/test/utils/chai_setup.ts | 13 - ...le_erc20_balance_and_proxy_allowance_fetcher.ts | 25 -- .../order-utils/test/utils/test_order_factory.ts | 33 -- packages/order-utils/test/utils/web3_wrapper.ts | 8 - packages/order-utils/tsconfig.json | 8 - packages/order-utils/tslint.json | 3 - packages/order-utils/typedoc-tsconfig.json | 7 - 51 files changed, 5260 deletions(-) delete mode 100644 packages/order-utils/.npmignore delete mode 100644 packages/order-utils/CHANGELOG.json delete mode 100644 packages/order-utils/CHANGELOG.md delete mode 100644 packages/order-utils/README.md delete mode 100644 packages/order-utils/coverage/.gitkeep delete mode 100644 packages/order-utils/package.json delete mode 100644 packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts delete mode 100644 packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts delete mode 100644 packages/order-utils/src/abstract/abstract_order_filled_cancelled_fetcher.ts delete mode 100644 packages/order-utils/src/abstract/abstract_order_filled_cancelled_lazy_store.ts delete mode 100644 packages/order-utils/src/assert.ts delete mode 100644 packages/order-utils/src/asset_data_utils.ts delete mode 100644 packages/order-utils/src/constants.ts delete mode 100644 packages/order-utils/src/crypto.ts delete mode 100644 packages/order-utils/src/eip712_utils.ts delete mode 100644 packages/order-utils/src/exchange_transfer_simulator.ts delete mode 100644 packages/order-utils/src/index.ts delete mode 100644 packages/order-utils/src/market_utils.ts delete mode 100644 packages/order-utils/src/order_factory.ts delete mode 100644 packages/order-utils/src/order_hash.ts delete mode 100644 packages/order-utils/src/order_state_utils.ts delete mode 100644 packages/order-utils/src/order_validation_utils.ts delete mode 100644 packages/order-utils/src/parsing_utils.ts delete mode 100644 packages/order-utils/src/rate_utils.ts delete mode 100644 packages/order-utils/src/remaining_fillable_calculator.ts delete mode 100644 packages/order-utils/src/salt.ts delete mode 100644 packages/order-utils/src/signature_utils.ts delete mode 100644 packages/order-utils/src/sorting_utils.ts delete mode 100644 packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts delete mode 100644 packages/order-utils/src/store/order_filled_cancelled_lazy_store.ts delete mode 100644 packages/order-utils/src/types.ts delete mode 100644 packages/order-utils/src/utils.ts delete mode 100644 packages/order-utils/test/assert_test.ts delete mode 100644 packages/order-utils/test/asset_data_utils_test.ts delete mode 100644 packages/order-utils/test/eip712_utils_test.ts delete mode 100644 packages/order-utils/test/exchange_transfer_simulator_test.ts delete mode 100644 packages/order-utils/test/market_utils_test.ts delete mode 100644 packages/order-utils/test/order_hash_test.ts delete mode 100644 packages/order-utils/test/order_state_utils_test.ts delete mode 100644 packages/order-utils/test/order_validation_utils_test.ts delete mode 100644 packages/order-utils/test/rate_utils_test.ts delete mode 100644 packages/order-utils/test/remaining_fillable_calculator_test.ts delete mode 100644 packages/order-utils/test/signature_utils_test.ts delete mode 100644 packages/order-utils/test/sorting_utils_test.ts delete mode 100644 packages/order-utils/test/utils/chai_setup.ts delete mode 100644 packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts delete mode 100644 packages/order-utils/test/utils/test_order_factory.ts delete mode 100644 packages/order-utils/test/utils/web3_wrapper.ts delete mode 100644 packages/order-utils/tsconfig.json delete mode 100644 packages/order-utils/tslint.json delete mode 100644 packages/order-utils/typedoc-tsconfig.json (limited to 'packages/order-utils') diff --git a/packages/order-utils/.npmignore b/packages/order-utils/.npmignore deleted file mode 100644 index 89302c908..000000000 --- a/packages/order-utils/.npmignore +++ /dev/null @@ -1,7 +0,0 @@ -.* -yarn-error.log -/scripts/ -/generated_docs/ -/src/ -tsconfig.json -/lib/monorepo_scripts/ diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json deleted file mode 100644 index 08d88da5b..000000000 --- a/packages/order-utils/CHANGELOG.json +++ /dev/null @@ -1,424 +0,0 @@ -[ - { - "version": "4.0.0", - "changes": [ - { - "note": "Upgrade the bignumber.js to v8.0.2", - "pr": 1517 - } - ] - }, - { - "timestamp": 1547561734, - "version": "3.1.2", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1547225310, - "version": "3.1.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "3.1.0", - "changes": [ - { - "note": "Use new ABI encoder, add encoding/decoding logic for MultiAsset assetData, and add information to return values in orderStateUtils", - "pr": 1363 - } - ], - "timestamp": 1547040760 - }, - { - "version": "3.0.7", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1544739608 - }, - { - "version": "3.0.6", - "changes": [ - { - "note": "Fix bug in wallet signature type verification", - "pr": 1414 - } - ], - "timestamp": 1544570656 - }, - { - "timestamp": 1544482891, - "version": "3.0.5", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1543401373, - "version": "3.0.4", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1542821676, - "version": "3.0.3", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1542208198, - "version": "3.0.2", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1542134075, - "version": "3.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "3.0.0", - "changes": [ - { - "note": "Add signature validation, regular cancellation and `cancelledUpTo` checks to `validateOrderFillableOrThrowAsync`", - "pr": 1235 - }, - { - "note": "Improved the errors thrown by `validateOrderFillableOrThrowAsync` by making them more descriptive", - "pr": 1235 - }, - { - "note": "Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218)", - "pr": 1235 - }, - { - "note": "Modified the `AbstractOrderFilledCancelledFetcher` interface slightly such that `isOrderCancelledAsync` accepts a `signedOrder` instead of an `orderHash` param", - "pr": 1235 - } - ], - "timestamp": 1542028948 - }, - { - "version": "2.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1541740904 - }, - { - "version": "2.0.0", - "changes": [ - { - "note": "Added `ecSignOrderAsync` to first sign an order using `eth_signTypedData` and fallback to `eth_sign`.", - "pr": 1102 - }, - { - "note": "Added `ecSignTypedDataOrderAsync` to sign an order exclusively using `eth_signTypedData`.", - "pr": 1102 - }, - { - "note": "Rename `ecSignOrderHashAsync` to `ecSignHashAsync` removing `SignerType` parameter.", - "pr": 1102 - }, - { - "note": "Use `AssetData` union type for function return values.", - "pr": 1131 - } - ], - "timestamp": 1539871071 - }, - { - "version": "1.0.7", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1538693146 - }, - { - "version": "1.0.6", - "changes": [ - { - "note": "Add signerAddress normalization to `isValidECSignature` to avoid `invalid address recovery` error if caller supplies a checksummed address", - "pr": 1096 - } - ], - "timestamp": 1538157789 - }, - { - "timestamp": 1537907159, - "version": "1.0.5", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1537875740, - "version": "1.0.4", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1537541580, - "version": "1.0.3", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "1.0.2", - "changes": [ - { - "note": "Drastically reduce the bundle size by removing unused parts of included contract artifacts." - } - ], - "timestamp": 1537369748 - }, - { - "version": "1.0.1", - "changes": [ - { - "note": "Export `orderParsingUtils`", - "pr": 1044 - } - ], - "timestamp": 1536142250 - }, - { - "version": "1.0.1-rc.6", - "changes": [ - { - "note": "Fix missing `BlockParamLiteral` type import issue" - } - ], - "timestamp": 1535377027 - }, - { - "version": "1.0.1-rc.5", - "changes": [ - { - "note": "Remove Caller and Trezor SignatureTypes", - "pr": 1015 - } - ] - }, - { - "version": "1.0.1-rc.4", - "changes": [ - { - "note": "Remove rounding error being thrown when maker amount is very small", - "pr": 959 - }, - { - "note": "Added rateUtils and sortingUtils", - "pr": 953 - }, - { - "note": "Update marketUtils api such that all optional parameters are bundled into one optional param and more defaults are provided", - "pr": 954 - }, - { - "note": "Instead of exporting signature util methods individually, they are now exported as `signatureUtils`", - "pr": 924 - }, - { - "note": "Export types: `SignedOrder`, `Order`, `OrderRelevantState`, `OrderState`, `ECSignature`, `ERC20AssetData`, `ERC721AssetData`, `AssetProxyId`, `SignerType`, `SignatureType`, `OrderStateValid`, `OrderStateInvalid`, `ExchangeContractErrs`, `TradeSide`, `TransferType`, `FindFeeOrdersThatCoverFeesForTargetOrdersOpts`, `FindOrdersThatCoverMakerAssetFillAmountOpts`, `FeeOrdersAndRemainingFeeAmount`, `OrdersAndRemainingFillAmount`, `Provider`, `JSONRPCRequestPayload`, `JSONRPCErrorCallback` and `JSONRPCResponsePayload`", - "pr": 924 - }, - { - "note": "Rename `resultOrders` to `resultFeeOrders` for object returned by `findFeeOrdersThatCoverFeesForTargetOrders` in `marketUtils` api", - "pr": 997 - }, - { - "note": "Make `sortFeeOrdersByFeeAdjustedRate` in `sortingUtils` generic", - "pr": 997 - }, - { - "note": "Update `findFeeOrdersThatCoverFeesForTargetOrders` to round the the nearest integer when calculating required fees", - "pr": 997 - } - ], - "timestamp": 1535133899 - }, - { - "version": "1.0.1-rc.3", - "changes": [ - { - "pr": 914, - "note": "Update ecSignOrderHashAsync to return signature string with signature type byte. Removes messagePrefixOpts." - }, - { - "note": "Added a synchronous `createOrder` method in `orderFactory`, updated public interfaces to support some optional parameters", - "pr": 936 - }, - { - "note": "Added marketUtils", - "pr": 937 - }, - { - "note": "Dependencies updated" - } - ], - "timestamp": 1534210131 - }, - { - "version": "1.0.1-rc.2", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1532619515 - }, - { - "version": "1.0.1-rc.1", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1532605697 - }, - { - "version": "1.0.0", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1532357734 - }, - { - "version": "1.0.0-rc.2", - "changes": [ - { - "note": "Upgrade ethereumjs-abi dep including a fix so that addresses starting with 0 are properly decoded by `decodeERC20AssetData`" - } - ], - "timestamp": 1532357734 - }, - { - "timestamp": 1532043000, - "version": "1.0.0-rc.1", - "changes": [ - { - "note": "Refactor to work with V2 of 0x protocol", - "pr": 636 - }, - { - "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" - } - ] - }, - { - "timestamp": 1531149657, - "version": "0.0.8", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1529397769, - "version": "0.0.7", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1527616612, - "version": "0.0.6", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "0.0.5", - "changes": [ - { - "note": "Add orderStateUtils, a module for computing order state needed to decide if an order is still valid" - } - ], - "timestamp": 1527008794 - }, - { - "timestamp": 1525477860, - "version": "0.0.4", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1525453812, - "version": "0.0.3", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1525428773, - "version": "0.0.2", - "changes": [ - { - "note": "Dependencies updated" - } - ] - } -] diff --git a/packages/order-utils/CHANGELOG.md b/packages/order-utils/CHANGELOG.md deleted file mode 100644 index c82458f2e..000000000 --- a/packages/order-utils/CHANGELOG.md +++ /dev/null @@ -1,172 +0,0 @@ - - -CHANGELOG - -## v3.1.2 - _January 15, 2019_ - - * Dependencies updated - -## v3.1.1 - _January 11, 2019_ - - * Dependencies updated - -## v3.1.0 - _January 9, 2019_ - - * Use new ABI encoder, add encoding/decoding logic for MultiAsset assetData, and add information to return values in orderStateUtils (#1363) - -## v3.0.7 - _December 13, 2018_ - - * Dependencies updated - -## v3.0.6 - _December 11, 2018_ - - * Fix bug in wallet signature type verification (#1414) - -## v3.0.5 - _December 10, 2018_ - - * Dependencies updated - -## v3.0.4 - _November 28, 2018_ - - * Dependencies updated - -## v3.0.3 - _November 21, 2018_ - - * Dependencies updated - -## v3.0.2 - _November 14, 2018_ - - * Dependencies updated - -## v3.0.1 - _November 13, 2018_ - - * Dependencies updated - -## v3.0.0 - _November 12, 2018_ - - * Add signature validation, regular cancellation and `cancelledUpTo` checks to `validateOrderFillableOrThrowAsync` (#1235) - * Improved the errors thrown by `validateOrderFillableOrThrowAsync` by making them more descriptive (#1235) - * Throw previously swallowed network errors when calling `validateOrderFillableOrThrowAsync` (see issue: #1218) (#1235) - * Modified the `AbstractOrderFilledCancelledFetcher` interface slightly such that `isOrderCancelledAsync` accepts a `signedOrder` instead of an `orderHash` param (#1235) - -## v2.0.1 - _November 9, 2018_ - - * Dependencies updated - -## v2.0.0 - _October 18, 2018_ - - * Added `ecSignOrderAsync` to first sign an order using `eth_signTypedData` and fallback to `eth_sign`. (#1102) - * Added `ecSignTypedDataOrderAsync` to sign an order exclusively using `eth_signTypedData`. (#1102) - * Rename `ecSignOrderHashAsync` to `ecSignHashAsync` removing `SignerType` parameter. (#1102) - * Use `AssetData` union type for function return values. (#1131) - -## v1.0.7 - _October 4, 2018_ - - * Dependencies updated - -## v1.0.6 - _September 28, 2018_ - - * Add signerAddress normalization to `isValidECSignature` to avoid `invalid address recovery` error if caller supplies a checksummed address (#1096) - -## v1.0.5 - _September 25, 2018_ - - * Dependencies updated - -## v1.0.4 - _September 25, 2018_ - - * Dependencies updated - -## v1.0.3 - _September 21, 2018_ - - * Dependencies updated - -## v1.0.2 - _September 19, 2018_ - - * Drastically reduce the bundle size by removing unused parts of included contract artifacts. - -## v1.0.1 - _September 5, 2018_ - - * Export `orderParsingUtils` (#1044) - -## v1.0.1-rc.6 - _August 27, 2018_ - - * Fix missing `BlockParamLiteral` type import issue - -## v1.0.1-rc.5 - _Invalid date_ - - * Remove Caller and Trezor SignatureTypes (#1015) - -## v1.0.1-rc.4 - _August 24, 2018_ - - * Remove rounding error being thrown when maker amount is very small (#959) - * Added rateUtils and sortingUtils (#953) - * Update marketUtils api such that all optional parameters are bundled into one optional param and more defaults are provided (#954) - * Instead of exporting signature util methods individually, they are now exported as `signatureUtils` (#924) - * Export types: `SignedOrder`, `Order`, `OrderRelevantState`, `OrderState`, `ECSignature`, `ERC20AssetData`, `ERC721AssetData`, `AssetProxyId`, `SignerType`, `SignatureType`, `OrderStateValid`, `OrderStateInvalid`, `ExchangeContractErrs`, `TradeSide`, `TransferType`, `FindFeeOrdersThatCoverFeesForTargetOrdersOpts`, `FindOrdersThatCoverMakerAssetFillAmountOpts`, `FeeOrdersAndRemainingFeeAmount`, `OrdersAndRemainingFillAmount`, `Provider`, `JSONRPCRequestPayload`, `JSONRPCErrorCallback` and `JSONRPCResponsePayload` (#924) - * Rename `resultOrders` to `resultFeeOrders` for object returned by `findFeeOrdersThatCoverFeesForTargetOrders` in `marketUtils` api (#997) - * Make `sortFeeOrdersByFeeAdjustedRate` in `sortingUtils` generic (#997) - * Update `findFeeOrdersThatCoverFeesForTargetOrders` to round the the nearest integer when calculating required fees (#997) - -## v1.0.1-rc.3 - _August 14, 2018_ - - * Update ecSignOrderHashAsync to return signature string with signature type byte. Removes messagePrefixOpts. (#914) - * Added a synchronous `createOrder` method in `orderFactory`, updated public interfaces to support some optional parameters (#936) - * Added marketUtils (#937) - * Dependencies updated - -## v1.0.1-rc.2 - _July 26, 2018_ - - * Dependencies updated - -## v1.0.1-rc.1 - _July 26, 2018_ - - * Dependencies updated - -## v1.0.0 - _July 23, 2018_ - - * Dependencies updated - -## v1.0.0-rc.2 - _July 23, 2018_ - - * Upgrade ethereumjs-abi dep including a fix so that addresses starting with 0 are properly decoded by `decodeERC20AssetData` - -## v1.0.0-rc.1 - _July 19, 2018_ - - * Refactor to work with V2 of 0x protocol (#636) - * Export parseECSignature method (#684) - * Handle Typed Arrays when hashing data (#894) - -## v0.0.9 - _July 18, 2018_ - - * Dependencies updated - -## v0.0.8 - _July 9, 2018_ - - * Dependencies updated - -## v0.0.7 - _June 19, 2018_ - - * Dependencies updated - -## v0.0.6 - _May 29, 2018_ - - * Dependencies updated - -## v0.0.5 - _May 22, 2018_ - - * Add orderStateUtils, a module for computing order state needed to decide if an order is still valid - -## v0.0.4 - _May 4, 2018_ - - * Dependencies updated - -## v0.0.3 - _May 4, 2018_ - - * Dependencies updated - -## v0.0.2 - _May 4, 2018_ - - * Dependencies updated diff --git a/packages/order-utils/README.md b/packages/order-utils/README.md deleted file mode 100644 index 4a8287098..000000000 --- a/packages/order-utils/README.md +++ /dev/null @@ -1,65 +0,0 @@ -## @0x/order-utils - -0x order-related utilities for those developing on top of 0x protocol. - -### Read the [Documentation](https://0xproject.com/docs/order-utils). - -## Installation - -```bash -yarn add @0x/order-utils -``` - -If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: - -```json -"compilerOptions": { - "typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"], -} -``` - -## Contributing - -We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository. - -Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. - -### Install dependencies - -If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: - -```bash -yarn config set workspaces-experimental true -``` - -Then install dependencies - -```bash -yarn install -``` - -### Build - -To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory: - -```bash -PKG=@0x/order-utils yarn build -``` - -Or continuously rebuild on change: - -```bash -PKG=@0x/order-utils yarn watch -``` - -### Clean - -```bash -yarn clean -``` - -### Lint - -```bash -yarn lint -``` diff --git a/packages/order-utils/coverage/.gitkeep b/packages/order-utils/coverage/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json deleted file mode 100644 index 7a4d4aa84..000000000 --- a/packages/order-utils/package.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "@0x/order-utils", - "version": "3.1.2", - "engines": { - "node": ">=6.12" - }, - "description": "0x order utils", - "main": "lib/src/index.js", - "types": "lib/src/index.d.ts", - "scripts": { - "build": "yarn tsc -b", - "build:ci": "yarn build", - "test": "yarn run_mocha", - "rebuild_and_test": "run-s build test", - "test:circleci": "yarn test:coverage", - "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit", - "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", - "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", - "clean": "shx rm -rf lib generated_docs", - "lint": "tslint --format stylish --project .", - "docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" - }, - "config": { - "postpublish": { - "assets": [] - } - }, - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/0xProject/0x-monorepo.git" - }, - "bugs": { - "url": "https://github.com/0xProject/0x-monorepo/issues" - }, - "homepage": "https://github.com/0xProject/0x-monorepo/packages/order-utils/README.md", - "devDependencies": { - "@0x/dev-utils": "^1.0.24", - "@0x/tslint-config": "^2.0.2", - "@types/bn.js": "^4.11.0", - "@types/lodash": "4.14.104", - "chai": "^4.0.1", - "chai-as-promised": "^7.1.0", - "chai-bignumber": "^3.0.0", - "dirty-chai": "^2.0.1", - "make-promises-safe": "^1.1.0", - "mocha": "^4.1.0", - "npm-run-all": "^4.1.2", - "shx": "^0.2.2", - "sinon": "^4.0.0", - "tslint": "5.11.0", - "typedoc": "0.13.0", - "typescript": "3.0.1" - }, - "dependencies": { - "@0x/abi-gen-wrappers": "^2.2.0", - "@0x/assert": "^1.0.23", - "@0x/base-contract": "^3.0.13", - "@0x/contract-artifacts": "^1.3.0", - "@0x/json-schemas": "^2.1.7", - "@0x/types": "^1.5.2", - "@0x/typescript-typings": "^3.0.8", - "@0x/utils": "^3.0.1", - "@0x/web3-wrapper": "^3.2.4", - "@types/node": "*", - "bn.js": "^4.11.8", - "ethereum-types": "^1.1.6", - "ethereumjs-abi": "0.6.5", - "ethereumjs-util": "^5.1.1", - "ethers": "~4.0.4", - "lodash": "^4.17.5" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts b/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts deleted file mode 100644 index 13fbf1736..000000000 --- a/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_fetcher.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -/** - * An abstract class to be implemented in order to use OrderStateUtils. The class that - * implements this interface must be capable of fetching the balance and proxyAllowance - * for an Ethereum address and assetData - */ -export abstract class AbstractBalanceAndProxyAllowanceFetcher { - /** - * Get balance of assetData for userAddress - * @param assetData AssetData for which to fetch the balance - * @param userAddress Ethereum address for which to fetch the balance - * @return Balance amount in base units - */ - public abstract async getBalanceAsync(assetData: string, userAddress: string): Promise; - /** - * Get the 0x asset proxy allowance of assetData for userAddress - * @param assetData AssetData for which to fetch the allowance - * @param userAddress Ethereum address for which to fetch the allowance - * @return Allowance amount in base units - */ - public abstract async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise; -} diff --git a/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts b/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts deleted file mode 100644 index 0a73e92bd..000000000 --- a/packages/order-utils/src/abstract/abstract_balance_and_proxy_allowance_lazy_store.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -export abstract class AbstractBalanceAndProxyAllowanceLazyStore { - public abstract async getBalanceAsync(assetData: string, userAddress: string): Promise; - public abstract async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise; - public abstract setBalance(assetData: string, userAddress: string, balance: BigNumber): void; - public abstract deleteBalance(assetData: string, userAddress: string): void; - public abstract setProxyAllowance(assetData: string, userAddress: string, proxyAllowance: BigNumber): void; - public abstract deleteProxyAllowance(assetData: string, userAddress: string): void; - public abstract deleteAll(): void; -} diff --git a/packages/order-utils/src/abstract/abstract_order_filled_cancelled_fetcher.ts b/packages/order-utils/src/abstract/abstract_order_filled_cancelled_fetcher.ts deleted file mode 100644 index 9e240f9ef..000000000 --- a/packages/order-utils/src/abstract/abstract_order_filled_cancelled_fetcher.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -/** - * An abstract class to be implemented in order to use OrderStateUtils. The class that - * implements this interface must be capable of fetching the amount filled of an order - * and whether it's been cancelled. - */ -export abstract class AbstractOrderFilledCancelledFetcher { - /** - * Get the amount of the order's takerToken amount already filled - * @param orderHash OrderHash of order we are interested in - * @return FilledTakerAmount - */ - public abstract async getFilledTakerAmountAsync(orderHash: string): Promise; - /** - * Whether an order is cancelled - * @param orderHash OrderHash of order we are interested in - * @return Whether or not the order is cancelled - */ - public abstract async isOrderCancelledAsync(signedOrder: SignedOrder): Promise; - public abstract getZRXAssetData(): string; -} 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 deleted file mode 100644 index 186521401..000000000 --- a/packages/order-utils/src/abstract/abstract_order_filled_cancelled_lazy_store.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -export abstract class AbstractOrderFilledCancelledLazyStore { - public abstract async getFilledTakerAmountAsync(orderHash: string): Promise; - public abstract async getIsCancelledAsync(signedOrder: SignedOrder): Promise; - 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 deleted file mode 100644 index 2f73f58c4..000000000 --- a/packages/order-utils/src/assert.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { assert as sharedAssert } from '@0x/assert'; -// 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 '@0x/json-schemas'; -import { ECSignature, SignatureType } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -// tslint:enable:no-unused-variable -import * as _ from 'lodash'; - -import { utils } from './utils'; - -export const assert = { - ...sharedAssert, - 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`, - ); - }, - isOneOfExpectedSignatureTypes(signature: string, signatureTypes: SignatureType[]): void { - sharedAssert.isHexString('signature', signature); - const signatureTypeIndexIfExists = utils.getSignatureTypeIndexIfExists(signature); - const isExpectedSignatureType = _.includes(signatureTypes, signatureTypeIndexIfExists); - if (!isExpectedSignatureType) { - throw new Error( - `Unexpected signatureType: ${signatureTypeIndexIfExists}. Valid signature types: ${signatureTypes}`, - ); - } - }, -}; diff --git a/packages/order-utils/src/asset_data_utils.ts b/packages/order-utils/src/asset_data_utils.ts deleted file mode 100644 index f314891e2..000000000 --- a/packages/order-utils/src/asset_data_utils.ts +++ /dev/null @@ -1,308 +0,0 @@ -import { - AssetProxyId, - ERC20AssetData, - ERC721AssetData, - MultiAssetData, - MultiAssetDataWithRecursiveDecoding, - SingleAssetData, -} from '@0x/types'; -import { AbiEncoder, BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { constants } from './constants'; - -const encodingRules: AbiEncoder.EncodingRules = { shouldOptimize: true }; -const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true }; - -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 { - const abiEncoder = new AbiEncoder.Method(constants.ERC20_METHOD_ABI); - const args = [tokenAddress]; - const assetData = abiEncoder.encode(args, encodingRules); - return assetData; - }, - /** - * 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 { - assetDataUtils.assertIsERC20AssetData(assetData); - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - const abiEncoder = new AbiEncoder.Method(constants.ERC20_METHOD_ABI); - const decodedAssetData = abiEncoder.decode(assetData, decodingRules); - return { - assetProxyId, - // TODO(abandeali1): fix return types for `AbiEncoder.Method.decode` so that we can remove type assertion - tokenAddress: (decodedAssetData as any).tokenContract, - }; - }, - /** - * 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): string { - const abiEncoder = new AbiEncoder.Method(constants.ERC721_METHOD_ABI); - const args = [tokenAddress, tokenId]; - const assetData = abiEncoder.encode(args, encodingRules); - return assetData; - }, - /** - * 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 { - assetDataUtils.assertIsERC721AssetData(assetData); - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - const abiEncoder = new AbiEncoder.Method(constants.ERC721_METHOD_ABI); - const decodedAssetData = abiEncoder.decode(assetData, decodingRules); - return { - assetProxyId, - // TODO(abandeali1): fix return types for `AbiEncoder.Method.decode` so that we can remove type assertion - tokenAddress: (decodedAssetData as any).tokenContract, - tokenId: (decodedAssetData as any).tokenId, - }; - }, - /** - * Encodes assetData for multiple AssetProxies into a single hex encoded assetData string, usable in the makerAssetData or - * takerAssetData fields in a 0x order. - * @param amounts Amounts of each asset that correspond to a single unit within an order. - * @param nestedAssetData assetData strings that correspond to a valid assetProxyId. - * @return The hex encoded assetData string - */ - encodeMultiAssetData(amounts: BigNumber[], nestedAssetData: string[]): string { - if (amounts.length !== nestedAssetData.length) { - throw new Error( - `Invalid MultiAsset arguments. Expected length of 'amounts' (${ - amounts.length - }) to equal length of 'nestedAssetData' (${nestedAssetData.length})`, - ); - } - _.forEach(nestedAssetData, assetDataElement => assetDataUtils.validateAssetDataOrThrow(assetDataElement)); - const abiEncoder = new AbiEncoder.Method(constants.MULTI_ASSET_METHOD_ABI); - const args = [amounts, nestedAssetData]; - const assetData = abiEncoder.encode(args, encodingRules); - return assetData; - }, - /** - * Decodes a MultiAsset assetData hex string into it's corresponding amounts and nestedAssetData - * @param assetData Hex encoded assetData string to decode - * @return An object containing the decoded amounts and nestedAssetData - */ - decodeMultiAssetData(assetData: string): MultiAssetData { - assetDataUtils.assertIsMultiAssetData(assetData); - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - const abiEncoder = new AbiEncoder.Method(constants.MULTI_ASSET_METHOD_ABI); - const decodedAssetData = abiEncoder.decode(assetData, decodingRules); - // TODO(abandeali1): fix return types for `AbiEncoder.Method.decode` so that we can remove type assertion - const amounts = (decodedAssetData as any).amounts; - const nestedAssetData = (decodedAssetData as any).nestedAssetData; - if (amounts.length !== nestedAssetData.length) { - throw new Error( - `Invalid MultiAsset assetData. Expected length of 'amounts' (${ - amounts.length - }) to equal length of 'nestedAssetData' (${nestedAssetData.length})`, - ); - } - return { - assetProxyId, - amounts, - nestedAssetData, - }; - }, - /** - * Decodes a MultiAsset assetData hex string into it's corresponding amounts and decoded nestedAssetData elements (all nested elements are flattened) - * @param assetData Hex encoded assetData string to decode - * @return An object containing the decoded amounts and nestedAssetData - */ - decodeMultiAssetDataRecursively(assetData: string): MultiAssetDataWithRecursiveDecoding { - const decodedAssetData = assetDataUtils.decodeMultiAssetData(assetData); - const amounts: any[] = []; - const decodedNestedAssetData = _.map( - decodedAssetData.nestedAssetData as string[], - (nestedAssetDataElement, index) => { - const decodedNestedAssetDataElement = assetDataUtils.decodeAssetDataOrThrow(nestedAssetDataElement); - if (decodedNestedAssetDataElement.assetProxyId === AssetProxyId.MultiAsset) { - const recursivelyDecodedAssetData = assetDataUtils.decodeMultiAssetDataRecursively( - nestedAssetDataElement, - ); - amounts.push( - _.map(recursivelyDecodedAssetData.amounts, amountElement => - amountElement.times(decodedAssetData.amounts[index]), - ), - ); - return recursivelyDecodedAssetData.nestedAssetData; - } else { - amounts.push(decodedAssetData.amounts[index]); - return decodedNestedAssetDataElement as SingleAssetData; - } - }, - ); - const flattenedAmounts = _.flattenDeep(amounts); - const flattenedDecodedNestedAssetData = _.flattenDeep(decodedNestedAssetData); - return { - assetProxyId: decodedAssetData.assetProxyId, - amounts: flattenedAmounts, - // tslint:disable-next-line:no-unnecessary-type-assertion - nestedAssetData: flattenedDecodedNestedAssetData as SingleAssetData[], - }; - }, - /** - * Decode and return the assetProxyId from the assetData - * @param assetData Hex encoded assetData string to decode - * @return The assetProxyId - */ - decodeAssetProxyId(assetData: string): AssetProxyId { - if (assetData.length < constants.SELECTOR_CHAR_LENGTH_WITH_PREFIX) { - throw new Error( - `Could not decode assetData. Expected length of encoded data to be at least 10. Got ${ - assetData.length - }`, - ); - } - const assetProxyId = assetData.slice(0, constants.SELECTOR_CHAR_LENGTH_WITH_PREFIX); - if ( - assetProxyId !== AssetProxyId.ERC20 && - assetProxyId !== AssetProxyId.ERC721 && - assetProxyId !== AssetProxyId.MultiAsset - ) { - throw new Error(`Invalid assetProxyId: ${assetProxyId}`); - } - return assetProxyId; - }, - /** - * Checks if the decoded asset data is valid ERC20 data - * @param decodedAssetData The decoded asset data to check - */ - isERC20AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC20AssetData { - return decodedAssetData.assetProxyId === AssetProxyId.ERC20; - }, - /** - * Checks if the decoded asset data is valid ERC721 data - * @param decodedAssetData The decoded asset data to check - */ - isERC721AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC721AssetData { - return decodedAssetData.assetProxyId === AssetProxyId.ERC721; - }, - /** - * Checks if the decoded asset data is valid MultiAsset data - * @param decodedAssetData The decoded asset data to check - */ - isMultiAssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is MultiAssetData { - return decodedAssetData.assetProxyId === AssetProxyId.MultiAsset; - }, - /** - * Throws if the length or assetProxyId are invalid for the ERC20Proxy. - * @param assetData Hex encoded assetData string - */ - assertIsERC20AssetData(assetData: string): void { - if (assetData.length < constants.ERC20_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX) { - throw new Error( - `Could not decode ERC20 Proxy Data. Expected length of encoded data to be at least ${ - constants.ERC20_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX - }. Got ${assetData.length}`, - ); - } - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - if (assetProxyId !== AssetProxyId.ERC20) { - throw new Error( - `Could not decode ERC20 assetData. Expected assetProxyId to be ERC20 (${ - AssetProxyId.ERC20 - }), but got ${assetProxyId}`, - ); - } - }, - /** - * Throws if the length or assetProxyId are invalid for the ERC721Proxy. - * @param assetData Hex encoded assetData string - */ - assertIsERC721AssetData(assetData: string): void { - if (assetData.length < constants.ERC721_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX) { - throw new Error( - `Could not decode ERC721 assetData. Expected length of encoded data to be at least ${ - constants.ERC721_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX - }. Got ${assetData.length}`, - ); - } - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - if (assetProxyId !== AssetProxyId.ERC721) { - throw new Error( - `Could not decode ERC721 assetData. Expected assetProxyId to be ERC721 (${ - AssetProxyId.ERC721 - }), but got ${assetProxyId}`, - ); - } - }, - /** - * Throws if the length or assetProxyId are invalid for the MultiAssetProxy. - * @param assetData Hex encoded assetData string - */ - assertIsMultiAssetData(assetData: string): void { - if (assetData.length < constants.MULTI_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX) { - throw new Error( - `Could not decode MultiAsset assetData. Expected length of encoded data to be at least ${ - constants.MULTI_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX - }. Got ${assetData.length}`, - ); - } - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - if (assetProxyId !== AssetProxyId.MultiAsset) { - throw new Error( - `Could not decode MultiAsset assetData. Expected assetProxyId to be MultiAsset (${ - AssetProxyId.MultiAsset - }), but got ${assetProxyId}`, - ); - } - }, - /** - * Throws if the length or assetProxyId are invalid for the corresponding AssetProxy. - * @param assetData Hex encoded assetData string - */ - validateAssetDataOrThrow(assetData: string): void { - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - switch (assetProxyId) { - case AssetProxyId.ERC20: - assetDataUtils.assertIsERC20AssetData(assetData); - break; - case AssetProxyId.ERC721: - assetDataUtils.assertIsERC721AssetData(assetData); - break; - case AssetProxyId.MultiAsset: - assetDataUtils.assertIsMultiAssetData(assetData); - break; - default: - throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`); - } - }, - /** - * 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): SingleAssetData | MultiAssetData { - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - switch (assetProxyId) { - case AssetProxyId.ERC20: - const erc20AssetData = assetDataUtils.decodeERC20AssetData(assetData); - return erc20AssetData; - case AssetProxyId.ERC721: - const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData); - return erc721AssetData; - case AssetProxyId.MultiAsset: - const multiAssetData = assetDataUtils.decodeMultiAssetData(assetData); - return multiAssetData; - default: - throw new Error(`Unrecognized asset proxy id: ${assetProxyId}`); - } - }, -}; diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts deleted file mode 100644 index a9a687719..000000000 --- a/packages/order-utils/src/constants.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import { MethodAbi } from 'ethereum-types'; - -const ERC20_METHOD_ABI: MethodAbi = { - constant: false, - inputs: [ - { - name: 'tokenContract', - type: 'address', - }, - ], - name: 'ERC20Token', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -const ERC721_METHOD_ABI: MethodAbi = { - constant: false, - inputs: [ - { - name: 'tokenContract', - type: 'address', - }, - { - name: 'tokenId', - type: 'uint256', - }, - ], - name: 'ERC721Token', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -const MULTI_ASSET_METHOD_ABI: MethodAbi = { - constant: false, - inputs: [ - { - name: 'amounts', - type: 'uint256[]', - }, - { - name: 'nestedAssetData', - type: 'bytes[]', - }, - ], - name: 'MultiAsset', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const constants = { - NULL_ADDRESS: '0x0000000000000000000000000000000000000000', - NULL_BYTES: '0x', - NULL_ERC20_ASSET_DATA: '0xf47261b00000000000000000000000000000000000000000000000000000000000000000', - // tslint:disable-next-line:custom-no-magic-numbers - UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1), - TESTRPC_NETWORK_ID: 50, - ADDRESS_LENGTH: 20, - ERC20_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX: 74, - ERC721_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX: 136, - MULTI_ASSET_DATA_MIN_CHAR_LENGTH_WITH_PREFIX: 266, - SELECTOR_CHAR_LENGTH_WITH_PREFIX: 10, - INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite - ZERO_AMOUNT: new BigNumber(0), - EIP712_DOMAIN_NAME: '0x Protocol', - EIP712_DOMAIN_VERSION: '2', - EIP712_DOMAIN_SCHEMA: { - name: 'EIP712Domain', - parameters: [ - { name: 'name', type: 'string' }, - { name: 'version', type: 'string' }, - { name: 'verifyingContract', type: 'address' }, - ], - }, - EIP712_ORDER_SCHEMA: { - name: 'Order', - parameters: [ - { name: 'makerAddress', type: 'address' }, - { name: 'takerAddress', type: 'address' }, - { name: 'feeRecipientAddress', type: 'address' }, - { name: 'senderAddress', type: 'address' }, - { name: 'makerAssetAmount', type: 'uint256' }, - { name: 'takerAssetAmount', type: 'uint256' }, - { name: 'makerFee', type: 'uint256' }, - { name: 'takerFee', type: 'uint256' }, - { name: 'expirationTimeSeconds', type: 'uint256' }, - { name: 'salt', type: 'uint256' }, - { name: 'makerAssetData', type: 'bytes' }, - { name: 'takerAssetData', type: 'bytes' }, - ], - }, - EIP712_ZEROEX_TRANSACTION_SCHEMA: { - name: 'ZeroExTransaction', - parameters: [ - { name: 'salt', type: 'uint256' }, - { name: 'signerAddress', type: 'address' }, - { name: 'data', type: 'bytes' }, - ], - }, - ERC20_METHOD_ABI, - ERC721_METHOD_ABI, - MULTI_ASSET_METHOD_ABI, -}; diff --git a/packages/order-utils/src/crypto.ts b/packages/order-utils/src/crypto.ts deleted file mode 100644 index 8b835ff48..000000000 --- a/packages/order-utils/src/crypto.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import BN = require('bn.js'); -import ABI = require('ethereumjs-abi'); -import ethUtil = require('ethereumjs-util'); -import * as _ from 'lodash'; - -export const crypto = { - /** - * We convert types from JS to Solidity as follows: - * BigNumber -> uint256 - * number -> uint8 - * string -> string - * boolean -> bool - * valid Ethereum address -> address - */ - solSHA3(args: any[]): Buffer { - return crypto._solHash(args, ABI.soliditySHA3); - }, - solSHA256(args: any[]): Buffer { - return crypto._solHash(args, ABI.soliditySHA256); - }, - _solHash(args: any[], hashFunction: (types: string[], values: any[]) => Buffer): Buffer { - const argTypes: string[] = []; - _.each(args, (arg, i) => { - const isNumber = _.isFinite(arg); - if (isNumber) { - argTypes.push('uint8'); - } else if (BigNumber.isBigNumber(arg)) { - argTypes.push('uint256'); - const base = 10; - args[i] = new BN(arg.toString(base), base); - } else if (ethUtil.isValidAddress(arg)) { - argTypes.push('address'); - } else if (_.isString(arg)) { - argTypes.push('string'); - } else if (_.isBuffer(arg) || _.isTypedArray(arg)) { - argTypes.push('bytes'); - } else if (_.isBoolean(arg)) { - argTypes.push('bool'); - } else { - throw new Error(`Unable to guess arg type: ${arg}`); - } - }); - const hash = hashFunction(argTypes, args); - return hash; - }, -}; diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts deleted file mode 100644 index 385fda989..000000000 --- a/packages/order-utils/src/eip712_utils.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { assert } from '@0x/assert'; -import { schemas } from '@0x/json-schemas'; -import { EIP712Object, EIP712TypedData, EIP712Types, Order, ZeroExTransaction } from '@0x/types'; -import * as _ from 'lodash'; - -import { constants } from './constants'; - -export const eip712Utils = { - /** - * Creates a EIP712TypedData object specific to the 0x protocol for use with signTypedData. - * @param primaryType The primary type found in message - * @param types The additional types for the data in message - * @param message The contents of the message - * @param exchangeAddress The address of the exchange contract - * @return A typed data object - */ - createTypedData: ( - primaryType: string, - types: EIP712Types, - message: EIP712Object, - exchangeAddress: string, - ): EIP712TypedData => { - assert.isETHAddressHex('exchangeAddress', exchangeAddress); - assert.isString('primaryType', primaryType); - const typedData = { - types: { - EIP712Domain: constants.EIP712_DOMAIN_SCHEMA.parameters, - ...types, - }, - domain: { - name: constants.EIP712_DOMAIN_NAME, - version: constants.EIP712_DOMAIN_VERSION, - verifyingContract: exchangeAddress, - }, - message, - primaryType, - }; - assert.doesConformToSchema('typedData', typedData, schemas.eip712TypedDataSchema); - return typedData; - }, - /** - * Creates an Order EIP712TypedData object for use with signTypedData. - * @param Order the order - * @return A typed data object - */ - createOrderTypedData: (order: Order): EIP712TypedData => { - assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]); - const normalizedOrder = _.mapValues(order, value => { - return !_.isString(value) ? value.toString() : value; - }); - const typedData = eip712Utils.createTypedData( - constants.EIP712_ORDER_SCHEMA.name, - { Order: constants.EIP712_ORDER_SCHEMA.parameters }, - normalizedOrder, - order.exchangeAddress, - ); - return typedData; - }, - /** - * Creates an ExecuteTransaction EIP712TypedData object for use with signTypedData and - * 0x Exchange executeTransaction. - * @param ZeroExTransaction the 0x transaction - * @param exchangeAddress The address of the exchange contract - * @return A typed data object - */ - createZeroExTransactionTypedData: ( - zeroExTransaction: ZeroExTransaction, - exchangeAddress: string, - ): EIP712TypedData => { - assert.isETHAddressHex('exchangeAddress', exchangeAddress); - assert.doesConformToSchema('zeroExTransaction', zeroExTransaction, schemas.zeroExTransactionSchema); - const normalizedTransaction = _.mapValues(zeroExTransaction, value => { - return !_.isString(value) ? value.toString() : value; - }); - const typedData = eip712Utils.createTypedData( - constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.name, - { ZeroExTransaction: constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.parameters }, - normalizedTransaction, - exchangeAddress, - ); - return typedData; - }, -}; diff --git a/packages/order-utils/src/exchange_transfer_simulator.ts b/packages/order-utils/src/exchange_transfer_simulator.ts deleted file mode 100644 index 922ae8e17..000000000 --- a/packages/order-utils/src/exchange_transfer_simulator.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { AssetProxyId, ExchangeContractErrs } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -import { AbstractBalanceAndProxyAllowanceLazyStore } from './abstract/abstract_balance_and_proxy_allowance_lazy_store'; -import { assetDataUtils } from './asset_data_utils'; -import { constants } from './constants'; -import { TradeSide, TransferType } from './types'; - -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, - }, - }, -}; - -/** - * An exchange transfer simulator which simulates asset transfers exactly how the - * 0x exchange contract would do them. - */ -export class ExchangeTransferSimulator { - private readonly _store: AbstractBalanceAndProxyAllowanceLazyStore; - private static _throwValidationError( - failureReason: FailureReason, - tradeSide: TradeSide, - transferType: TransferType, - ): never { - const errMsg = ERR_MSG_MAPPING[failureReason][tradeSide][transferType]; - throw new Error(errMsg); - } - /** - * Instantiate a ExchangeTransferSimulator - * @param store A class that implements AbstractBalanceAndProxyAllowanceLazyStore - * @return an instance of ExchangeTransferSimulator - */ - constructor(store: AbstractBalanceAndProxyAllowanceLazyStore) { - this._store = store; - } - /** - * Simulates transferFrom call performed by a proxy - * @param assetData Data of the asset being transferred. Includes - * it's identifying information and assetType, - * e.g address for ERC20, address & tokenId for ERC721 - * @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( - assetData: string, - from: string, - to: string, - amountInBaseUnits: BigNumber, - tradeSide: TradeSide, - transferType: TransferType, - ): Promise { - const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); - switch (assetProxyId) { - case AssetProxyId.ERC20: - case AssetProxyId.ERC721: - // 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(assetData, to, amountInBaseUnits); - return; - } - const balance = await this._store.getBalanceAsync(assetData, from); - const proxyAllowance = await this._store.getProxyAllowanceAsync(assetData, from); - if (proxyAllowance.isLessThan(amountInBaseUnits)) { - ExchangeTransferSimulator._throwValidationError( - FailureReason.ProxyAllowance, - tradeSide, - transferType, - ); - } - if (balance.isLessThan(amountInBaseUnits)) { - ExchangeTransferSimulator._throwValidationError(FailureReason.Balance, tradeSide, transferType); - } - await this._decreaseProxyAllowanceAsync(assetData, from, amountInBaseUnits); - await this._decreaseBalanceAsync(assetData, from, amountInBaseUnits); - await this._increaseBalanceAsync(assetData, to, amountInBaseUnits); - break; - case AssetProxyId.MultiAsset: - const decodedAssetData = assetDataUtils.decodeMultiAssetData(assetData); - for (const [index, nestedAssetDataElement] of decodedAssetData.nestedAssetData.entries()) { - const amountsElement = decodedAssetData.amounts[index]; - const totalAmount = amountInBaseUnits.times(amountsElement); - await this.transferFromAsync( - nestedAssetDataElement, - from, - to, - totalAmount, - tradeSide, - transferType, - ); - } - break; - default: - break; - } - } - private async _decreaseProxyAllowanceAsync( - assetData: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise { - const proxyAllowance = await this._store.getProxyAllowanceAsync(assetData, userAddress); - // HACK: This code assumes that all tokens with an UNLIMITED_ALLOWANCE_IN_BASE_UNITS set, - // are UnlimitedAllowanceTokens. This is however not true, it just so happens that all - // DummyERC20Tokens we use in tests are. - if (!proxyAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { - this._store.setProxyAllowance(assetData, userAddress, proxyAllowance.minus(amountInBaseUnits)); - } - } - private async _increaseBalanceAsync( - assetData: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise { - const balance = await this._store.getBalanceAsync(assetData, userAddress); - this._store.setBalance(assetData, userAddress, balance.plus(amountInBaseUnits)); - } - private async _decreaseBalanceAsync( - assetData: string, - userAddress: string, - amountInBaseUnits: BigNumber, - ): Promise { - const balance = await this._store.getBalanceAsync(assetData, userAddress); - this._store.setBalance(assetData, userAddress, balance.minus(amountInBaseUnits)); - } -} diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts deleted file mode 100644 index 2150a02e4..000000000 --- a/packages/order-utils/src/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -export { orderHashUtils } from './order_hash'; -export { signatureUtils } from './signature_utils'; -export { generatePseudoRandomSalt } from './salt'; -export { assetDataUtils } from './asset_data_utils'; -export { marketUtils } from './market_utils'; -export { rateUtils } from './rate_utils'; -export { sortingUtils } from './sorting_utils'; -export { orderParsingUtils } from './parsing_utils'; - -export { OrderStateUtils } from './order_state_utils'; -export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher'; -export { AbstractBalanceAndProxyAllowanceLazyStore } from './abstract/abstract_balance_and_proxy_allowance_lazy_store'; -export { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher'; -export { AbstractOrderFilledCancelledLazyStore } from './abstract/abstract_order_filled_cancelled_lazy_store'; - -export { OrderValidationUtils } from './order_validation_utils'; -export { ExchangeTransferSimulator } from './exchange_transfer_simulator'; -export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store'; -export { OrderFilledCancelledLazyStore } from './store/order_filled_cancelled_lazy_store'; - -export { eip712Utils } from './eip712_utils'; - -export { - Provider, - JSONRPCRequestPayload, - JSONRPCErrorCallback, - JSONRPCResponsePayload, - JSONRPCResponseError, -} from 'ethereum-types'; - -export { - SignedOrder, - Order, - OrderRelevantState, - OrderState, - ECSignature, - SingleAssetData, - ERC20AssetData, - ERC721AssetData, - MultiAssetData, - MultiAssetDataWithRecursiveDecoding, - AssetProxyId, - SignatureType, - ObjectMap, - OrderStateValid, - OrderStateInvalid, - ExchangeContractErrs, - EIP712Parameter, - EIP712TypedData, - EIP712Types, - EIP712Object, - EIP712ObjectValue, - ZeroExTransaction, -} from '@0x/types'; -export { - OrderError, - TradeSide, - TransferType, - FindFeeOrdersThatCoverFeesForTargetOrdersOpts, - FindOrdersThatCoverMakerAssetFillAmountOpts, - FeeOrdersAndRemainingFeeAmount, - OrdersAndRemainingFillAmount, -} from './types'; diff --git a/packages/order-utils/src/market_utils.ts b/packages/order-utils/src/market_utils.ts deleted file mode 100644 index 9042551fa..000000000 --- a/packages/order-utils/src/market_utils.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { schemas } from '@0x/json-schemas'; -import { Order } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { assert } from './assert'; -import { constants } from './constants'; -import { - FeeOrdersAndRemainingFeeAmount, - FindFeeOrdersThatCoverFeesForTargetOrdersOpts, - FindOrdersThatCoverMakerAssetFillAmountOpts, - OrdersAndRemainingFillAmount, -} from './types'; - -export const marketUtils = { - /** - * Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount - * in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last order. - * Sort the input by ascending rate in order to get the subset of orders that will cost the least ETH. - * @param orders An array of objects that extend the Order interface. All orders should specify the same makerAsset. - * All orders should specify WETH as the takerAsset. - * @param makerAssetFillAmount The amount of makerAsset desired to be filled. - * @param opts Optional arguments this function accepts. - * @return Resulting orders and remaining fill amount that could not be covered by the input. - */ - findOrdersThatCoverMakerAssetFillAmount( - orders: T[], - makerAssetFillAmount: BigNumber, - opts?: FindOrdersThatCoverMakerAssetFillAmountOpts, - ): OrdersAndRemainingFillAmount { - assert.doesConformToSchema('orders', orders, schemas.ordersSchema); - assert.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount); - // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders - const remainingFillableMakerAssetAmounts = _.get( - opts, - 'remainingFillableMakerAssetAmounts', - _.map(orders, order => order.makerAssetAmount), - ) as BigNumber[]; - _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => - assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), - ); - assert.assert( - orders.length === remainingFillableMakerAssetAmounts.length, - 'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length', - ); - // try to get slippageBufferAmount from opts, if it's not there, default to 0 - const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber; - assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount); - // calculate total amount of makerAsset needed to be filled - const totalFillAmount = makerAssetFillAmount.plus(slippageBufferAmount); - // iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount - const result = _.reduce( - orders, - ({ resultOrders, remainingFillAmount, ordersRemainingFillableMakerAssetAmounts }, order, index) => { - if (remainingFillAmount.isLessThanOrEqualTo(constants.ZERO_AMOUNT)) { - return { - resultOrders, - remainingFillAmount: constants.ZERO_AMOUNT, - ordersRemainingFillableMakerAssetAmounts, - }; - } else { - const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index]; - const shouldIncludeOrder = makerAssetAmountAvailable.gt(constants.ZERO_AMOUNT); - // if there is no makerAssetAmountAvailable do not append order to resultOrders - // if we have exceeded the total amount we want to fill set remainingFillAmount to 0 - return { - resultOrders: shouldIncludeOrder ? _.concat(resultOrders, order) : resultOrders, - ordersRemainingFillableMakerAssetAmounts: shouldIncludeOrder - ? _.concat(ordersRemainingFillableMakerAssetAmounts, makerAssetAmountAvailable) - : ordersRemainingFillableMakerAssetAmounts, - remainingFillAmount: BigNumber.max( - constants.ZERO_AMOUNT, - remainingFillAmount.minus(makerAssetAmountAvailable), - ), - }; - } - }, - { - resultOrders: [] as T[], - remainingFillAmount: totalFillAmount, - ordersRemainingFillableMakerAssetAmounts: [] as BigNumber[], - }, - ); - return result; - }, - /** - * Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX - * in order to fill the takerFees required by orders plus a slippageBufferAmount. - * Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of - * feeOrders that will cost the least ETH. - * @param orders An array of objects that extend the Order interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @param feeOrders An array of objects that extend the Order interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @param opts Optional arguments this function accepts. - * @return Resulting orders and remaining fee amount that could not be covered by the input. - */ - findFeeOrdersThatCoverFeesForTargetOrders( - orders: T[], - feeOrders: T[], - opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts, - ): FeeOrdersAndRemainingFeeAmount { - assert.doesConformToSchema('orders', orders, schemas.ordersSchema); - assert.doesConformToSchema('feeOrders', feeOrders, schemas.ordersSchema); - // try to get remainingFillableMakerAssetAmounts from opts, if it's not there, use makerAssetAmount values from orders - const remainingFillableMakerAssetAmounts = _.get( - opts, - 'remainingFillableMakerAssetAmounts', - _.map(orders, order => order.makerAssetAmount), - ) as BigNumber[]; - _.forEach(remainingFillableMakerAssetAmounts, (amount, index) => - assert.isValidBaseUnitAmount(`remainingFillableMakerAssetAmount[${index}]`, amount), - ); - assert.assert( - orders.length === remainingFillableMakerAssetAmounts.length, - 'Expected orders.length to equal opts.remainingFillableMakerAssetAmounts.length', - ); - // try to get remainingFillableFeeAmounts from opts, if it's not there, use makerAssetAmount values from feeOrders - const remainingFillableFeeAmounts = _.get( - opts, - 'remainingFillableFeeAmounts', - _.map(feeOrders, order => order.makerAssetAmount), - ) as BigNumber[]; - _.forEach(remainingFillableFeeAmounts, (amount, index) => - assert.isValidBaseUnitAmount(`remainingFillableFeeAmounts[${index}]`, amount), - ); - assert.assert( - feeOrders.length === remainingFillableFeeAmounts.length, - 'Expected feeOrders.length to equal opts.remainingFillableFeeAmounts.length', - ); - // try to get slippageBufferAmount from opts, if it's not there, default to 0 - const slippageBufferAmount = _.get(opts, 'slippageBufferAmount', constants.ZERO_AMOUNT) as BigNumber; - assert.isValidBaseUnitAmount('opts.slippageBufferAmount', slippageBufferAmount); - // calculate total amount of ZRX needed to fill orders - const totalFeeAmount = _.reduce( - orders, - (accFees, order, index) => { - const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index]; - const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable - .multipliedBy(order.takerFee) - .dividedToIntegerBy(order.makerAssetAmount); - return accFees.plus(feeToFillMakerAssetAmountAvailable); - }, - constants.ZERO_AMOUNT, - ); - const { - resultOrders, - remainingFillAmount, - ordersRemainingFillableMakerAssetAmounts, - } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(feeOrders, totalFeeAmount, { - remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts, - slippageBufferAmount, - }); - return { - resultFeeOrders: resultOrders, - remainingFeeAmount: remainingFillAmount, - feeOrdersRemainingFillableMakerAssetAmounts: ordersRemainingFillableMakerAssetAmounts, - }; - // TODO: add more orders here to cover rounding - // https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarding-contract-specification.md#over-buying-zrx - }, -}; diff --git a/packages/order-utils/src/order_factory.ts b/packages/order-utils/src/order_factory.ts deleted file mode 100644 index f7b855bfb..000000000 --- a/packages/order-utils/src/order_factory.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { Order, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { constants } from './constants'; -import { orderHashUtils } from './order_hash'; -import { generatePseudoRandomSalt } from './salt'; -import { signatureUtils } from './signature_utils'; -import { CreateOrderOpts } from './types'; -export const orderFactory = { - createOrderFromPartial(partialOrder: Partial): Order { - const defaultOrder = generateEmptyOrder(); - return { - ...defaultOrder, - ...partialOrder, - }; - }, - createSignedOrderFromPartial(partialSignedOrder: Partial): SignedOrder { - const defaultOrder = generateEmptySignedOrder(); - return { - ...defaultOrder, - ...partialSignedOrder, - }; - }, - createOrder( - makerAddress: string, - makerAssetAmount: BigNumber, - makerAssetData: string, - takerAssetAmount: BigNumber, - takerAssetData: string, - exchangeAddress: string, - createOrderOpts: CreateOrderOpts = generateDefaultCreateOrderOpts(), - ): Order { - const defaultCreateOrderOpts = generateDefaultCreateOrderOpts(); - const order = { - makerAddress, - makerAssetAmount, - takerAssetAmount, - makerAssetData, - takerAssetData, - exchangeAddress, - takerAddress: createOrderOpts.takerAddress || defaultCreateOrderOpts.takerAddress, - senderAddress: createOrderOpts.senderAddress || defaultCreateOrderOpts.senderAddress, - makerFee: createOrderOpts.makerFee || defaultCreateOrderOpts.makerFee, - takerFee: createOrderOpts.takerFee || defaultCreateOrderOpts.takerFee, - feeRecipientAddress: createOrderOpts.feeRecipientAddress || defaultCreateOrderOpts.feeRecipientAddress, - salt: createOrderOpts.salt || defaultCreateOrderOpts.salt, - expirationTimeSeconds: - createOrderOpts.expirationTimeSeconds || defaultCreateOrderOpts.expirationTimeSeconds, - }; - return order; - }, - async createSignedOrderAsync( - provider: Provider, - makerAddress: string, - makerAssetAmount: BigNumber, - makerAssetData: string, - takerAssetAmount: BigNumber, - takerAssetData: string, - exchangeAddress: string, - createOrderOpts?: CreateOrderOpts, - ): Promise { - const order = orderFactory.createOrder( - makerAddress, - makerAssetAmount, - makerAssetData, - takerAssetAmount, - takerAssetData, - exchangeAddress, - createOrderOpts, - ); - const orderHash = orderHashUtils.getOrderHashHex(order); - const signature = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress); - const signedOrder: SignedOrder = _.assign(order, { signature }); - return signedOrder; - }, -}; - -function generateEmptySignedOrder(): SignedOrder { - return { - ...generateEmptyOrder(), - signature: constants.NULL_BYTES, - }; -} -function generateEmptyOrder(): Order { - return { - senderAddress: constants.NULL_ADDRESS, - makerAddress: constants.NULL_ADDRESS, - takerAddress: constants.NULL_ADDRESS, - makerFee: constants.ZERO_AMOUNT, - takerFee: constants.ZERO_AMOUNT, - makerAssetAmount: constants.ZERO_AMOUNT, - takerAssetAmount: constants.ZERO_AMOUNT, - makerAssetData: constants.NULL_BYTES, - takerAssetData: constants.NULL_BYTES, - salt: generatePseudoRandomSalt(), - exchangeAddress: constants.NULL_ADDRESS, - feeRecipientAddress: constants.NULL_ADDRESS, - expirationTimeSeconds: constants.INFINITE_TIMESTAMP_SEC, - }; -} - -function generateDefaultCreateOrderOpts(): { - takerAddress: string; - senderAddress: string; - makerFee: BigNumber; - takerFee: BigNumber; - feeRecipientAddress: string; - salt: BigNumber; - expirationTimeSeconds: BigNumber; -} { - return { - takerAddress: constants.NULL_ADDRESS, - senderAddress: constants.NULL_ADDRESS, - makerFee: constants.ZERO_AMOUNT, - takerFee: constants.ZERO_AMOUNT, - feeRecipientAddress: constants.NULL_ADDRESS, - salt: generatePseudoRandomSalt(), - expirationTimeSeconds: constants.INFINITE_TIMESTAMP_SEC, - }; -} diff --git a/packages/order-utils/src/order_hash.ts b/packages/order-utils/src/order_hash.ts deleted file mode 100644 index c8e9be71e..000000000 --- a/packages/order-utils/src/order_hash.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { schemas, SchemaValidator } from '@0x/json-schemas'; -import { Order, SignedOrder } from '@0x/types'; -import { signTypedDataUtils } from '@0x/utils'; -import * as _ from 'lodash'; - -import { assert } from './assert'; -import { eip712Utils } from './eip712_utils'; - -const INVALID_TAKER_FORMAT = 'instance.takerAddress is not of a type(s) string'; - -export const orderHashUtils = { - /** - * 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. - */ - 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 isValid = schemaValidator.validate(orderHash, schemas.orderHashSchema).valid; - return isValid; - }, - /** - * Computes the orderHash for a supplied order. - * @param order An object that conforms to the Order or SignedOrder interface definitions. - * @return Hex encoded string orderHash from hashing the supplied order. - */ - getOrderHashHex(order: SignedOrder | Order): string { - try { - assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]); - } catch (error) { - if (_.includes(error.message, 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'; - throw new Error(errMsg); - } - throw error; - } - - const orderHashBuff = orderHashUtils.getOrderHashBuffer(order); - const orderHashHex = `0x${orderHashBuff.toString('hex')}`; - return orderHashHex; - }, - /** - * Computes the orderHash for a supplied order - * @param order An object that conforms to the Order or SignedOrder interface definitions. - * @return A Buffer containing the resulting orderHash from hashing the supplied order - */ - getOrderHashBuffer(order: SignedOrder | Order): Buffer { - const typedData = eip712Utils.createOrderTypedData(order); - const orderHashBuff = signTypedDataUtils.generateTypedDataHash(typedData); - return orderHashBuff; - }, -}; diff --git a/packages/order-utils/src/order_state_utils.ts b/packages/order-utils/src/order_state_utils.ts deleted file mode 100644 index 430178b5d..000000000 --- a/packages/order-utils/src/order_state_utils.ts +++ /dev/null @@ -1,346 +0,0 @@ -import { - ExchangeContractErrs, - ObjectMap, - OrderRelevantState, - OrderState, - OrderStateInvalid, - OrderStateValid, - SignedOrder, -} from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher'; -import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher'; -import { assetDataUtils } from './asset_data_utils'; -import { orderHashUtils } from './order_hash'; -import { OrderValidationUtils } from './order_validation_utils'; -import { RemainingFillableCalculator } from './remaining_fillable_calculator'; -import { utils } from './utils'; - -interface SidedOrderRelevantState { - isMakerSide: boolean; - traderBalance: BigNumber; - traderIndividualBalances: ObjectMap; - traderProxyAllowance: BigNumber; - traderIndividualProxyAllowances: ObjectMap; - traderFeeBalance: BigNumber; - traderFeeProxyAllowance: BigNumber; - filledTakerAssetAmount: BigNumber; - remainingFillableAssetAmount: BigNumber; - isOrderCancelled: boolean; -} -interface OrderValidResult { - isValid: true; -} -interface OrderInvalidResult { - isValid: false; - error: ExchangeContractErrs; -} -type OrderValidationResult = OrderValidResult | OrderInvalidResult; - -export class OrderStateUtils { - private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; - private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; - private static _validateIfOrderIsValid( - signedOrder: SignedOrder, - sidedOrderRelevantState: SidedOrderRelevantState, - ): OrderValidationResult { - const isMakerSide = sidedOrderRelevantState.isMakerSide; - if (sidedOrderRelevantState.isOrderCancelled) { - return { isValid: false, error: ExchangeContractErrs.OrderCancelled }; - } - const availableTakerAssetAmount = signedOrder.takerAssetAmount.minus( - sidedOrderRelevantState.filledTakerAssetAmount, - ); - if (availableTakerAssetAmount.eq(0)) { - return { isValid: false, error: ExchangeContractErrs.OrderRemainingFillAmountZero }; - } - - if (sidedOrderRelevantState.traderBalance.eq(0)) { - const error = isMakerSide - ? ExchangeContractErrs.InsufficientMakerBalance - : ExchangeContractErrs.InsufficientTakerBalance; - return { isValid: false, error }; - } - if (sidedOrderRelevantState.traderProxyAllowance.eq(0)) { - const error = isMakerSide - ? ExchangeContractErrs.InsufficientMakerAllowance - : ExchangeContractErrs.InsufficientTakerAllowance; - return { isValid: false, error }; - } - if (!signedOrder.makerFee.eq(0)) { - if (sidedOrderRelevantState.traderFeeBalance.eq(0)) { - const error = isMakerSide - ? ExchangeContractErrs.InsufficientMakerFeeBalance - : ExchangeContractErrs.InsufficientTakerFeeBalance; - return { isValid: false, error }; - } - if (sidedOrderRelevantState.traderFeeProxyAllowance.eq(0)) { - const error = isMakerSide - ? ExchangeContractErrs.InsufficientMakerFeeAllowance - : ExchangeContractErrs.InsufficientTakerFeeAllowance; - return { isValid: false, error }; - } - } - const remainingTakerAssetAmount = signedOrder.takerAssetAmount.minus( - sidedOrderRelevantState.filledTakerAssetAmount, - ); - const isRoundingError = OrderValidationUtils.isRoundingErrorFloor( - remainingTakerAssetAmount, - signedOrder.takerAssetAmount, - signedOrder.makerAssetAmount, - ); - if (isRoundingError) { - return { isValid: false, error: ExchangeContractErrs.OrderFillRoundingError }; - } - return { isValid: true }; - } - /** - * Instantiate OrderStateUtils - * @param balanceAndProxyAllowanceFetcher A class that is capable of fetching balances - * and proxyAllowances for Ethereum addresses. It must implement AbstractBalanceAndProxyAllowanceFetcher - * @param orderFilledCancelledFetcher A class that is capable of fetching whether an order - * is cancelled and how much of it has been filled. It must implement AbstractOrderFilledCancelledFetcher - * @return Instance of OrderStateUtils - */ - constructor( - balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher, - orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher, - ) { - this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher; - this._orderFilledCancelledFetcher = orderFilledCancelledFetcher; - } - /** - * Get the orderState for an "open" order (i.e where takerAddress=NULL_ADDRESS) - * This method will only check the maker's balance/allowance to calculate the - * OrderState. - * @param signedOrder The order of interest - * @return State relevant to the signedOrder, as well as whether the signedOrder is "valid". - * Validity is defined as a non-zero amount of the order can still be filled. - */ - public async getOpenOrderStateAsync(signedOrder: SignedOrder, transactionHash?: string): Promise { - const orderRelevantState = await this.getOpenOrderRelevantStateAsync(signedOrder); - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - const isOrderCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(signedOrder); - const sidedOrderRelevantState = { - isMakerSide: true, - traderBalance: orderRelevantState.makerBalance, - traderIndividualBalances: orderRelevantState.makerIndividualBalances, - traderProxyAllowance: orderRelevantState.makerProxyAllowance, - traderIndividualProxyAllowances: orderRelevantState.makerIndividualProxyAllowances, - traderFeeBalance: orderRelevantState.makerFeeBalance, - traderFeeProxyAllowance: orderRelevantState.makerFeeProxyAllowance, - filledTakerAssetAmount: orderRelevantState.filledTakerAssetAmount, - remainingFillableAssetAmount: orderRelevantState.remainingFillableMakerAssetAmount, - isOrderCancelled, - }; - const orderValidationResult = OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState); - if (orderValidationResult.isValid) { - const orderState: OrderStateValid = { - isValid: true, - orderHash, - orderRelevantState, - transactionHash, - }; - return orderState; - } else { - const orderState: OrderStateInvalid = { - isValid: false, - orderHash, - error: orderValidationResult.error, - transactionHash, - }; - return orderState; - } - } - /** - * Get state relevant to an order (i.e makerBalance, makerAllowance, filledTakerAssetAmount, etc... - * @param signedOrder Order of interest - * @return An instance of OrderRelevantState - */ - public async getOpenOrderRelevantStateAsync(signedOrder: SignedOrder): Promise { - const isMaker = true; - const sidedOrderRelevantState = await this._getSidedOrderRelevantStateAsync( - isMaker, - signedOrder, - signedOrder.takerAddress, - ); - const remainingFillableTakerAssetAmount = sidedOrderRelevantState.remainingFillableAssetAmount - .times(signedOrder.takerAssetAmount) - .dividedToIntegerBy(signedOrder.makerAssetAmount); - - const orderRelevantState = { - makerBalance: sidedOrderRelevantState.traderBalance, - makerIndividualBalances: sidedOrderRelevantState.traderIndividualBalances, - makerProxyAllowance: sidedOrderRelevantState.traderProxyAllowance, - makerIndividualProxyAllowances: sidedOrderRelevantState.traderIndividualProxyAllowances, - makerFeeBalance: sidedOrderRelevantState.traderFeeBalance, - makerFeeProxyAllowance: sidedOrderRelevantState.traderFeeProxyAllowance, - filledTakerAssetAmount: sidedOrderRelevantState.filledTakerAssetAmount, - remainingFillableMakerAssetAmount: sidedOrderRelevantState.remainingFillableAssetAmount, - remainingFillableTakerAssetAmount, - }; - return orderRelevantState; - } - /** - * Get the max amount of the supplied order's takerAmount that could still be filled - * @param signedOrder Order of interest - * @param takerAddress Hypothetical taker of the order - * @return fillableTakerAssetAmount - */ - public async getMaxFillableTakerAssetAmountAsync( - signedOrder: SignedOrder, - takerAddress: string, - ): Promise { - // Get max fillable amount for an order, considering the makers ability to fill - let isMaker = true; - const orderRelevantMakerState = await this._getSidedOrderRelevantStateAsync( - isMaker, - signedOrder, - signedOrder.takerAddress, - ); - const remainingFillableTakerAssetAmountGivenMakersStatus = signedOrder.makerAssetAmount.eq(0) - ? new BigNumber(0) - : utils.getPartialAmountFloor( - orderRelevantMakerState.remainingFillableAssetAmount, - signedOrder.makerAssetAmount, - signedOrder.takerAssetAmount, - ); - - // Get max fillable amount for an order, considering the takers ability to fill - isMaker = false; - const orderRelevantTakerState = await this._getSidedOrderRelevantStateAsync(isMaker, signedOrder, takerAddress); - const remainingFillableTakerAssetAmountGivenTakersStatus = orderRelevantTakerState.remainingFillableAssetAmount; - - // The min of these two in the actualy max fillable by either party - const fillableTakerAssetAmount = BigNumber.min( - remainingFillableTakerAssetAmountGivenMakersStatus, - remainingFillableTakerAssetAmountGivenTakersStatus, - ); - - return fillableTakerAssetAmount; - } - private async _getSidedOrderRelevantStateAsync( - isMakerSide: boolean, - signedOrder: SignedOrder, - takerAddress: string, - ): Promise { - let traderAddress; - let assetData; - let assetAmount; - let feeAmount; - if (isMakerSide) { - traderAddress = signedOrder.makerAddress; - assetData = signedOrder.makerAssetData; - assetAmount = signedOrder.makerAssetAmount; - feeAmount = signedOrder.makerFee; - } else { - traderAddress = takerAddress; - assetData = signedOrder.takerAssetData; - assetAmount = signedOrder.takerAssetAmount; - feeAmount = signedOrder.takerFee; - } - const zrxAssetData = this._orderFilledCancelledFetcher.getZRXAssetData(); - const isAssetZRX = assetData === zrxAssetData; - - const traderBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress); - const traderIndividualBalances = await this._getAssetBalancesAsync(assetData, traderAddress); - const traderProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync( - assetData, - traderAddress, - ); - const traderIndividualProxyAllowances = await this._getAssetProxyAllowancesAsync(assetData, traderAddress); - const traderFeeBalance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync( - zrxAssetData, - traderAddress, - ); - const traderFeeProxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync( - zrxAssetData, - traderAddress, - ); - - const transferrableTraderAssetAmount = BigNumber.min(traderProxyAllowance, traderBalance); - const transferrableFeeAssetAmount = BigNumber.min(traderFeeProxyAllowance, traderFeeBalance); - - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - const filledTakerAssetAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash); - const totalMakerAssetAmount = signedOrder.makerAssetAmount; - const totalTakerAssetAmount = signedOrder.takerAssetAmount; - const isOrderCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(signedOrder); - const remainingTakerAssetAmount = isOrderCancelled - ? new BigNumber(0) - : totalTakerAssetAmount.minus(filledTakerAssetAmount); - const remainingMakerAssetAmount = remainingTakerAssetAmount.eq(0) - ? new BigNumber(0) - : remainingTakerAssetAmount.times(totalMakerAssetAmount).dividedToIntegerBy(totalTakerAssetAmount); - const remainingAssetAmount = isMakerSide ? remainingMakerAssetAmount : remainingTakerAssetAmount; - - const remainingFillableCalculator = new RemainingFillableCalculator( - feeAmount, - assetAmount, - isAssetZRX, - transferrableTraderAssetAmount, - transferrableFeeAssetAmount, - remainingAssetAmount, - ); - const remainingFillableAssetAmount = remainingFillableCalculator.computeRemainingFillable(); - - const sidedOrderRelevantState = { - isMakerSide, - traderBalance, - traderIndividualBalances, - traderProxyAllowance, - traderIndividualProxyAllowances, - traderFeeBalance, - traderFeeProxyAllowance, - filledTakerAssetAmount, - remainingFillableAssetAmount, - isOrderCancelled, - }; - return sidedOrderRelevantState; - } - private async _getAssetBalancesAsync( - assetData: string, - traderAddress: string, - initialBalances: ObjectMap = {}, - ): Promise> { - const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); - let balances: ObjectMap = { ...initialBalances }; - if (assetDataUtils.isERC20AssetData(decodedAssetData) || assetDataUtils.isERC721AssetData(decodedAssetData)) { - const balance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress); - const tokenAddress = decodedAssetData.tokenAddress; - balances[tokenAddress] = _.isUndefined(initialBalances[tokenAddress]) - ? balance - : balances[tokenAddress].plus(balance); - } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { - for (const assetDataElement of decodedAssetData.nestedAssetData) { - balances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, balances); - } - } - return balances; - } - private async _getAssetProxyAllowancesAsync( - assetData: string, - traderAddress: string, - initialAllowances: ObjectMap = {}, - ): Promise> { - const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); - let allowances: ObjectMap = { ...initialAllowances }; - if (assetDataUtils.isERC20AssetData(decodedAssetData) || assetDataUtils.isERC721AssetData(decodedAssetData)) { - const allowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync( - assetData, - traderAddress, - ); - const tokenAddress = decodedAssetData.tokenAddress; - allowances[tokenAddress] = _.isUndefined(initialAllowances[tokenAddress]) - ? allowance - : allowances[tokenAddress].plus(allowance); - } else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { - for (const assetDataElement of decodedAssetData.nestedAssetData) { - allowances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, allowances); - } - } - return allowances; - } -} diff --git a/packages/order-utils/src/order_validation_utils.ts b/packages/order-utils/src/order_validation_utils.ts deleted file mode 100644 index 95215d918..000000000 --- a/packages/order-utils/src/order_validation_utils.ts +++ /dev/null @@ -1,257 +0,0 @@ -import { ExchangeContractErrs, RevertReason, SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { OrderError, TradeSide, TransferType } from './types'; - -import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher'; -import { constants } from './constants'; -import { ExchangeTransferSimulator } from './exchange_transfer_simulator'; -import { orderHashUtils } from './order_hash'; -import { signatureUtils } from './signature_utils'; -import { utils } from './utils'; - -/** - * A utility class for validating orders - */ -export class OrderValidationUtils { - private readonly _orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher; - private readonly _provider: Provider; - /** - * A Typescript implementation mirroring the implementation of isRoundingError in the - * Exchange smart contract - * @param numerator Numerator value. When used to check an order, pass in `takerAssetFilledAmount` - * @param denominator Denominator value. When used to check an order, pass in `order.takerAssetAmount` - * @param target Target value. When used to check an order, pass in `order.makerAssetAmount` - */ - public static isRoundingErrorFloor(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 - if (denominator.eq(0)) { - throw new Error('denominator cannot be 0'); - } - const remainder = target.multipliedBy(numerator).mod(denominator); - if (remainder.eq(0)) { - return false; // no rounding error - } - - // tslint:disable-next-line:custom-no-magic-numbers - const errPercentageTimes1000000 = remainder.multipliedBy(1000000).div(numerator.multipliedBy(target)); - // tslint:disable-next-line:custom-no-magic-numbers - const isError = errPercentageTimes1000000.gt(1000); - return isError; - } - /** - * Validate that the maker & taker have sufficient balances/allowances - * to fill the supplied order to the fillTakerAssetAmount amount - * @param exchangeTradeEmulator ExchangeTradeEmulator to use - * @param signedOrder SignedOrder to test - * @param fillTakerAssetAmount Amount of takerAsset to fill the signedOrder - * @param senderAddress Sender of the fillOrder tx - * @param zrxAssetData AssetData for the ZRX token - */ - public static async validateFillOrderBalancesAllowancesThrowIfInvalidAsync( - exchangeTradeEmulator: ExchangeTransferSimulator, - signedOrder: SignedOrder, - fillTakerAssetAmount: BigNumber, - senderAddress: string, - zrxAssetData: string, - ): Promise { - const fillMakerTokenAmount = utils.getPartialAmountFloor( - fillTakerAssetAmount, - signedOrder.takerAssetAmount, - signedOrder.makerAssetAmount, - ); - await exchangeTradeEmulator.transferFromAsync( - signedOrder.makerAssetData, - signedOrder.makerAddress, - senderAddress, - fillMakerTokenAmount, - TradeSide.Maker, - TransferType.Trade, - ); - await exchangeTradeEmulator.transferFromAsync( - signedOrder.takerAssetData, - senderAddress, - signedOrder.makerAddress, - fillTakerAssetAmount, - TradeSide.Taker, - TransferType.Trade, - ); - const makerFeeAmount = utils.getPartialAmountFloor( - fillTakerAssetAmount, - signedOrder.takerAssetAmount, - signedOrder.makerFee, - ); - await exchangeTradeEmulator.transferFromAsync( - zrxAssetData, - signedOrder.makerAddress, - signedOrder.feeRecipientAddress, - makerFeeAmount, - TradeSide.Maker, - TransferType.Fee, - ); - const takerFeeAmount = utils.getPartialAmountFloor( - fillTakerAssetAmount, - signedOrder.takerAssetAmount, - signedOrder.takerFee, - ); - await exchangeTradeEmulator.transferFromAsync( - zrxAssetData, - senderAddress, - signedOrder.feeRecipientAddress, - takerFeeAmount, - TradeSide.Taker, - TransferType.Fee, - ); - } - private static _validateOrderNotExpiredOrThrow(expirationTimeSeconds: BigNumber): void { - const currentUnixTimestampSec = utils.getCurrentUnixTimestampSec(); - if (expirationTimeSeconds.isLessThan(currentUnixTimestampSec)) { - throw new Error(RevertReason.OrderUnfillable); - } - } - /** - * Instantiate OrderValidationUtils - * @param orderFilledCancelledFetcher A module that implements the AbstractOrderFilledCancelledFetcher - * @return An instance of OrderValidationUtils - */ - constructor(orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher, provider: Provider) { - this._orderFilledCancelledFetcher = orderFilledCancelledFetcher; - this._provider = provider; - } - // TODO(fabio): remove this method once the smart contracts have been refactored - // to return helpful revert reasons instead of ORDER_UNFILLABLE. Instruct devs - // to make "calls" to validate order fillability + getOrderInfo for fillable amount. - /** - * Validate if the supplied order is fillable, and throw if it isn't - * @param exchangeTradeEmulator ExchangeTradeEmulator instance - * @param signedOrder SignedOrder of interest - * @param zrxAssetData ZRX assetData - * @param expectedFillTakerTokenAmount If supplied, this call will make sure this amount is fillable. - * If it isn't supplied, we check if the order is fillable for a non-zero amount - */ - public async validateOrderFillableOrThrowAsync( - exchangeTradeEmulator: ExchangeTransferSimulator, - signedOrder: SignedOrder, - zrxAssetData: string, - expectedFillTakerTokenAmount?: BigNumber, - ): Promise { - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - const isValidSignature = await signatureUtils.isValidSignatureAsync( - this._provider, - orderHash, - signedOrder.signature, - signedOrder.makerAddress, - ); - if (!isValidSignature) { - throw new Error(RevertReason.InvalidOrderSignature); - } - - const isCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(signedOrder); - if (isCancelled) { - throw new Error('CANCELLED'); - } - const filledTakerTokenAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash); - if (signedOrder.takerAssetAmount.eq(filledTakerTokenAmount)) { - throw new Error('FULLY_FILLED'); - } - try { - OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds); - } catch (err) { - throw new Error('EXPIRED'); - } - let fillTakerAssetAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount); - if (!_.isUndefined(expectedFillTakerTokenAmount)) { - fillTakerAssetAmount = expectedFillTakerTokenAmount; - } - await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - fillTakerAssetAmount, - signedOrder.takerAddress, - zrxAssetData, - ); - } - /** - * Validate a call to FillOrder and throw if it wouldn't succeed - * @param exchangeTradeEmulator ExchangeTradeEmulator to use - * @param provider Web3 provider to use for JSON RPC requests - * @param signedOrder SignedOrder of interest - * @param fillTakerAssetAmount Amount we'd like to fill the order for - * @param takerAddress The taker of the order - * @param zrxAssetData ZRX asset data - */ - public async validateFillOrderThrowIfInvalidAsync( - exchangeTradeEmulator: ExchangeTransferSimulator, - provider: Provider, - signedOrder: SignedOrder, - fillTakerAssetAmount: BigNumber, - takerAddress: string, - zrxAssetData: string, - ): Promise { - if (signedOrder.makerAssetAmount.eq(0) || signedOrder.takerAssetAmount.eq(0)) { - throw new Error(RevertReason.OrderUnfillable); - } - if (fillTakerAssetAmount.eq(0)) { - throw new Error(RevertReason.InvalidTakerAmount); - } - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - const isValid = await signatureUtils.isValidSignatureAsync( - provider, - orderHash, - signedOrder.signature, - signedOrder.makerAddress, - ); - if (!isValid) { - throw new Error(OrderError.InvalidSignature); - } - const filledTakerTokenAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash); - if (signedOrder.takerAssetAmount.eq(filledTakerTokenAmount)) { - throw new Error(RevertReason.OrderUnfillable); - } - if (signedOrder.takerAddress !== constants.NULL_ADDRESS && signedOrder.takerAddress !== takerAddress) { - throw new Error(RevertReason.InvalidTaker); - } - OrderValidationUtils._validateOrderNotExpiredOrThrow(signedOrder.expirationTimeSeconds); - const remainingTakerTokenAmount = signedOrder.takerAssetAmount.minus(filledTakerTokenAmount); - const desiredFillTakerTokenAmount = remainingTakerTokenAmount.isLessThan(fillTakerAssetAmount) - ? remainingTakerTokenAmount - : fillTakerAssetAmount; - try { - await OrderValidationUtils.validateFillOrderBalancesAllowancesThrowIfInvalidAsync( - exchangeTradeEmulator, - signedOrder, - desiredFillTakerTokenAmount, - takerAddress, - zrxAssetData, - ); - } catch (err) { - const transferFailedErrorMessages = [ - ExchangeContractErrs.InsufficientMakerBalance, - ExchangeContractErrs.InsufficientMakerFeeBalance, - ExchangeContractErrs.InsufficientTakerBalance, - ExchangeContractErrs.InsufficientTakerFeeBalance, - ExchangeContractErrs.InsufficientMakerAllowance, - ExchangeContractErrs.InsufficientMakerFeeAllowance, - ExchangeContractErrs.InsufficientTakerAllowance, - ExchangeContractErrs.InsufficientTakerFeeAllowance, - ]; - if (_.includes(transferFailedErrorMessages, err.message)) { - throw new Error(RevertReason.TransferFailed); - } - throw err; - } - - const wouldRoundingErrorOccur = OrderValidationUtils.isRoundingErrorFloor( - desiredFillTakerTokenAmount, - signedOrder.takerAssetAmount, - signedOrder.makerAssetAmount, - ); - if (wouldRoundingErrorOccur) { - throw new Error(RevertReason.RoundingError); - } - return filledTakerTokenAmount; - } -} diff --git a/packages/order-utils/src/parsing_utils.ts b/packages/order-utils/src/parsing_utils.ts deleted file mode 100644 index 98c6899fe..000000000 --- a/packages/order-utils/src/parsing_utils.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -export const orderParsingUtils = { - convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any { - const result = _.assign({}, obj); - _.each(fields, field => { - _.update(result, field, (value: string) => { - if (_.isUndefined(value)) { - throw new Error(`Could not find field '${field}' while converting string fields to BigNumber.`); - } - return new BigNumber(value); - }); - }); - return result; - }, - convertOrderStringFieldsToBigNumber(order: any): any { - return orderParsingUtils.convertStringsFieldsToBigNumbers(order, [ - 'makerAssetAmount', - 'takerAssetAmount', - 'makerFee', - 'takerFee', - 'expirationTimeSeconds', - 'salt', - ]); - }, -}; diff --git a/packages/order-utils/src/rate_utils.ts b/packages/order-utils/src/rate_utils.ts deleted file mode 100644 index dacdbd5a2..000000000 --- a/packages/order-utils/src/rate_utils.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { schemas } from '@0x/json-schemas'; -import { Order } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -import { assert } from './assert'; -import { constants } from './constants'; - -export const rateUtils = { - /** - * Takes an order and calculates the fee adjusted rate (takerAsset/makerAsset) by calculating how much takerAsset - * is required to cover the fees (feeRate * takerFee), adding the takerAssetAmount and dividing by makerAssetAmount - * @param order An object that conforms to the order interface - * @param feeRate The market rate of ZRX denominated in takerAssetAmount - * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX) - * Defaults to 0 - * @return The rate (takerAsset/makerAsset) of the order adjusted for fees - */ - getFeeAdjustedRateOfOrder(order: Order, feeRate: BigNumber = constants.ZERO_AMOUNT): BigNumber { - assert.doesConformToSchema('order', order, schemas.orderSchema); - assert.isBigNumber('feeRate', feeRate); - assert.assert( - feeRate.gte(constants.ZERO_AMOUNT), - `Expected feeRate: ${feeRate} to be greater than or equal to 0`, - ); - const takerAssetAmountNeededToPayForFees = order.takerFee.multipliedBy(feeRate); - const totalTakerAssetAmount = takerAssetAmountNeededToPayForFees.plus(order.takerAssetAmount); - const rate = totalTakerAssetAmount.div(order.makerAssetAmount); - return rate; - }, - /** - * Takes a fee order (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) and calculates - * the fee adjusted rate (WETH/ZRX) by dividing the takerAssetAmount by the makerAmount minus the takerFee - * @param feeOrder An object that conforms to the order interface - * @return The rate (WETH/ZRX) of the fee order adjusted for fees - */ - getFeeAdjustedRateOfFeeOrder(feeOrder: Order): BigNumber { - assert.doesConformToSchema('feeOrder', feeOrder, schemas.orderSchema); - const zrxAmountAfterFees = feeOrder.makerAssetAmount.minus(feeOrder.takerFee); - assert.assert( - zrxAmountAfterFees.isGreaterThan(constants.ZERO_AMOUNT), - `Expected takerFee: ${JSON.stringify(feeOrder.takerFee)} to be less than makerAssetAmount: ${JSON.stringify( - feeOrder.makerAssetAmount, - )}`, - ); - const rate = feeOrder.takerAssetAmount.div(zrxAmountAfterFees); - return rate; - }, -}; diff --git a/packages/order-utils/src/remaining_fillable_calculator.ts b/packages/order-utils/src/remaining_fillable_calculator.ts deleted file mode 100644 index 92ffc8e80..000000000 --- a/packages/order-utils/src/remaining_fillable_calculator.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -export class RemainingFillableCalculator { - private readonly _isTraderAssetZRX: boolean; - // Transferrable Amount is the minimum of Approval and Balance - 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, - isTraderAssetZRX: boolean, - transferrableAssetAmount: BigNumber, - transferrableFeeAmount: BigNumber, - remainingOrderAssetAmount: BigNumber, - ) { - this._orderFee = orderFee; - this._orderAssetAmount = orderAssetAmount; - this._isTraderAssetZRX = isTraderAssetZRX; - this._transferrableAssetAmount = transferrableAssetAmount; - this._transferrableFeeAmount = transferrableFeeAmount; - this._remainingOrderAssetAmount = remainingOrderAssetAmount; - this._remainingOrderFeeAmount = orderAssetAmount.eq(0) - ? new BigNumber(0) - : remainingOrderAssetAmount.times(orderFee).dividedToIntegerBy(orderAssetAmount); - } - public computeRemainingFillable(): BigNumber { - if (this._hasSufficientFundsForFeeAndTransferAmount()) { - return this._remainingOrderAssetAmount; - } - if (this._orderFee.isZero()) { - return BigNumber.min(this._remainingOrderAssetAmount, this._transferrableAssetAmount); - } - return this._calculatePartiallyFillableAssetAmount(); - } - private _hasSufficientFundsForFeeAndTransferAmount(): boolean { - if (this._isTraderAssetZRX) { - const totalZRXTransferAmountRequired = this._remainingOrderAssetAmount.plus(this._remainingOrderFeeAmount); - const hasSufficientFunds = this._transferrableAssetAmount.isGreaterThanOrEqualTo( - totalZRXTransferAmountRequired, - ); - return hasSufficientFunds; - } else { - const hasSufficientFundsForTransferAmount = this._transferrableAssetAmount.isGreaterThanOrEqualTo( - this._remainingOrderAssetAmount, - ); - const hasSufficientFundsForFeeAmount = this._transferrableFeeAmount.isGreaterThanOrEqualTo( - this._remainingOrderFeeAmount, - ); - const hasSufficientFunds = hasSufficientFundsForTransferAmount && hasSufficientFundsForFeeAmount; - return hasSufficientFunds; - } - } - private _calculatePartiallyFillableAssetAmount(): BigNumber { - // Given an order for 200 wei for 2 ZRXwei fee, find 100 wei for 1 ZRXwei. Order ratio is then 100:1 - const orderToFeeRatio = this._orderAssetAmount.dividedBy(this._orderFee); - // The number of times the trader (maker or taker) can fill the order, if each fill only required the transfer of a single - // baseUnit of fee tokens. - // Given 2 ZRXwei, the maximum amount of times trader can fill this order, in terms of fees, is 2 - const fillableTimesInFeeBaseUnits = BigNumber.min(this._transferrableFeeAmount, this._remainingOrderFeeAmount); - // The number of times the trader can fill the order, given the traders asset Balance - // Assuming a balance of 150 wei, and an orderToFeeRatio of 100:1, trader can fill this order 1 time. - let fillableTimesInAssetUnits = this._transferrableAssetAmount.dividedBy(orderToFeeRatio); - if (this._isTraderAssetZRX) { - // If ZRX is the trader asset, the Fee and the trader fill amount need to be removed from the same pool; - // 200 ZRXwei for 2ZRXwei fee can only be filled once (need 202 ZRXwei) - const totalZRXTokenPooled = this._transferrableAssetAmount; - // The purchasing power here is less as the tokens are taken from the same Pool - // For every one number of fills, we have to take an extra ZRX out of the pool - fillableTimesInAssetUnits = totalZRXTokenPooled.dividedBy(orderToFeeRatio.plus(new BigNumber(1))); - } - // When Ratio is not fully divisible there can be remainders which cannot be represented, so they are floored. - // This can result in a RoundingError being thrown by the Exchange Contract. - const partiallyFillableAssetAmount = fillableTimesInAssetUnits - .times(this._orderAssetAmount) - .dividedToIntegerBy(this._orderFee); - const partiallyFillableFeeAmount = fillableTimesInFeeBaseUnits - .times(this._orderAssetAmount) - .dividedToIntegerBy(this._orderFee); - const partiallyFillableAmount = BigNumber.min(partiallyFillableAssetAmount, partiallyFillableFeeAmount); - return partiallyFillableAmount; - } -} diff --git a/packages/order-utils/src/salt.ts b/packages/order-utils/src/salt.ts deleted file mode 100644 index 95df66c99..000000000 --- a/packages/order-utils/src/salt.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -const MAX_DIGITS_IN_UNSIGNED_256_INT = 78; - -/** - * 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. - */ -export function 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(MAX_DIGITS_IN_UNSIGNED_256_INT); - const factor = new BigNumber(10).pow(MAX_DIGITS_IN_UNSIGNED_256_INT - 1); - const salt = randomNumber.times(factor).integerValue(); - return salt; -} diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts deleted file mode 100644 index 131144d48..000000000 --- a/packages/order-utils/src/signature_utils.ts +++ /dev/null @@ -1,417 +0,0 @@ -import { ExchangeContract, IValidatorContract, IWalletContract } from '@0x/abi-gen-wrappers'; -import * as artifacts from '@0x/contract-artifacts'; -import { schemas } from '@0x/json-schemas'; -import { ECSignature, Order, SignatureType, SignedOrder, ValidatorSignature } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { Provider } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { assert } from './assert'; -import { eip712Utils } from './eip712_utils'; -import { orderHashUtils } from './order_hash'; -import { OrderError } from './types'; -import { utils } from './utils'; - -export const signatureUtils = { - /** - * Verifies that the provided signature is valid according to the 0x Protocol smart contracts - * @param data The hex encoded data signed by the supplied signature. - * @param signature A hex encoded 0x Protocol signature made up of: [TypeSpecificData][SignatureType]. - * E.g [vrs][SignatureType.EIP712] - * @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. - */ - async isValidSignatureAsync( - provider: Provider, - data: string, - signature: string, - signerAddress: string, - ): Promise { - 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}`); - } - - switch (signatureTypeIndexIfExists) { - case SignatureType.Illegal: - case SignatureType.Invalid: - return false; - - case SignatureType.EIP712: { - const ecSignature = signatureUtils.parseECSignature(signature); - return signatureUtils.isValidECSignature(data, ecSignature, signerAddress); - } - - case SignatureType.EthSign: { - const ecSignature = signatureUtils.parseECSignature(signature); - const prefixedMessageHex = signatureUtils.addSignedMessagePrefix(data); - return signatureUtils.isValidECSignature(prefixedMessageHex, ecSignature, signerAddress); - } - - case SignatureType.Wallet: { - const isValid = await signatureUtils.isValidWalletSignatureAsync( - provider, - data, - signature, - signerAddress, - ); - return isValid; - } - - case SignatureType.Validator: { - const isValid = await signatureUtils.isValidValidatorSignatureAsync( - provider, - data, - signature, - signerAddress, - ); - return isValid; - } - - case SignatureType.PreSigned: { - return signatureUtils.isValidPresignedSignatureAsync(provider, data, signerAddress); - } - - default: - throw new Error(`Unhandled SignatureType: ${signatureTypeIndexIfExists}`); - } - }, - /** - * Verifies that the provided presigned signature is valid according to the 0x Protocol smart contracts - * @param provider Web3 provider to use for all JSON RPC requests - * @param data The hex encoded data signed by the supplied signature - * @param signerAddress The hex encoded address that signed the data, producing the supplied signature. - * @return Whether the data was preSigned by the supplied signerAddress - */ - async isValidPresignedSignatureAsync(provider: Provider, data: string, signerAddress: string): Promise { - 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; - }, - /** - * Verifies that the provided wallet signature is valid according to the 0x Protocol smart contracts - * @param provider Web3 provider to use for all JSON RPC requests - * @param data The hex encoded data signed by the supplied signature. - * @param signature A hex encoded presigned 0x Protocol signature made up of: [SignatureType.Presigned] - * @param signerAddress The hex encoded address that signed the data, producing the supplied signature. - * @return Whether the data was preSigned by the supplied signerAddress. - */ - async isValidWalletSignatureAsync( - provider: Provider, - data: string, - signature: string, - signerAddress: string, - ): Promise { - 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(0, -2); - const walletContract = new IWalletContract(artifacts.IWallet.compilerOutput.abi, signerAddress, provider); - const isValid = await walletContract.isValidSignature.callAsync(data, signatureWithoutType); - return isValid; - }, - /** - * Verifies that the provided validator signature is valid according to the 0x Protocol smart contracts - * @param provider Web3 provider to use for all JSON RPC requests - * @param data The hex encoded data signed by the supplied signature. - * @param signature A hex encoded presigned 0x Protocol signature made up of: [SignatureType.Presigned] - * @param signerAddress The hex encoded address that signed the data, producing the supplied signature. - * @return Whether the data was preSigned by the supplied signerAddress. - */ - async isValidValidatorSignatureAsync( - provider: Provider, - data: string, - signature: string, - signerAddress: string, - ): Promise { - 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( - signerAddress, - validatorSignature.validatorAddress, - ); - if (!isValidatorApproved) { - throw new Error( - `Validator ${validatorSignature.validatorAddress} was not pre-approved by ${signerAddress}.`, - ); - } - - const validatorContract = new IValidatorContract( - artifacts.IValidator.compilerOutput.abi, - signerAddress, - provider, - ); - const isValid = await validatorContract.isValidSignature.callAsync( - data, - signerAddress, - validatorSignature.signature, - ); - return isValid; - }, - /** - * Checks if the supplied elliptic curve signature corresponds to signing `data` with - * the private key corresponding to `signerAddress` - * @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 ECSignature is valid. - */ - isValidECSignature(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 msgHashBuff = ethUtil.toBuffer(data); - try { - const pubKey = ethUtil.ecrecover( - msgHashBuff, - signature.v, - ethUtil.toBuffer(signature.r), - ethUtil.toBuffer(signature.s), - ); - const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey)); - const normalizedRetrievedAddress = retrievedAddress.toLowerCase(); - return normalizedRetrievedAddress === normalizedSignerAddress; - } catch (err) { - return false; - } - }, - /** - * Signs an order and returns a SignedOrder. First `eth_signTypedData` is requested - * then a fallback to `eth_sign` if not available on the supplied provider. - * @param order The Order to sign. - * @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address - * must be available via the supplied Provider. - * @return A SignedOrder containing the order and Elliptic curve signature with Signature Type. - */ - async ecSignOrderAsync(provider: Provider, order: Order, signerAddress: string): Promise { - assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]); - try { - const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(provider, order, signerAddress); - return signedOrder; - } catch (err) { - // HACK: We are unable to handle specific errors thrown since provider is not an object - // under our control. It could be Metamask Web3, Ethers, or any general RPC provider. - // We check for a user denying the signature request in a way that supports Metamask and - // Coinbase Wallet. Unfortunately for signers with a different error message, - // they will receive two signature requests. - if (err.message.includes('User denied message signature')) { - throw err; - } - const orderHash = orderHashUtils.getOrderHashHex(order); - const signatureHex = await signatureUtils.ecSignHashAsync(provider, orderHash, signerAddress); - const signedOrder = { - ...order, - signature: signatureHex, - }; - return signedOrder; - } - }, - /** - * Signs an order using `eth_signTypedData` and returns a SignedOrder. - * @param order The Order to sign. - * @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address - * must be available via the supplied Provider. - * @return A SignedOrder containing the order and Elliptic curve signature with Signature Type. - */ - async ecSignTypedDataOrderAsync(provider: Provider, order: Order, signerAddress: string): Promise { - assert.isWeb3Provider('provider', provider); - assert.isETHAddressHex('signerAddress', signerAddress); - assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]); - const web3Wrapper = new Web3Wrapper(provider); - await assert.isSenderAddressAsync('signerAddress', signerAddress, web3Wrapper); - const normalizedSignerAddress = signerAddress.toLowerCase(); - const typedData = eip712Utils.createOrderTypedData(order); - try { - const signature = await web3Wrapper.signTypedDataAsync(normalizedSignerAddress, typedData); - const ecSignatureRSV = parseSignatureHexAsRSV(signature); - const signatureBuffer = Buffer.concat([ - ethUtil.toBuffer(ecSignatureRSV.v), - ethUtil.toBuffer(ecSignatureRSV.r), - ethUtil.toBuffer(ecSignatureRSV.s), - ethUtil.toBuffer(SignatureType.EIP712), - ]); - const signatureHex = `0x${signatureBuffer.toString('hex')}`; - return { - ...order, - signature: signatureHex, - }; - } catch (err) { - // Detect if Metamask to transition users to the MetamaskSubprovider - if ((provider as any).isMetaMask) { - throw new Error(OrderError.InvalidMetamaskSigner); - } else { - throw err; - } - } - }, - /** - * Signs a hash using `eth_sign` and returns its elliptic curve signature and signature type. - * @param msgHash Hex encoded message to sign. - * @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address - * must be available via the supplied Provider. - * @return A hex encoded string containing the Elliptic curve signature generated by signing the msgHash and the Signature Type. - */ - async ecSignHashAsync(provider: Provider, msgHash: string, signerAddress: string): Promise { - assert.isWeb3Provider('provider', provider); - assert.isHexString('msgHash', msgHash); - assert.isETHAddressHex('signerAddress', signerAddress); - const web3Wrapper = new Web3Wrapper(provider); - await assert.isSenderAddressAsync('signerAddress', signerAddress, web3Wrapper); - const normalizedSignerAddress = signerAddress.toLowerCase(); - const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHash); - const prefixedMsgHashHex = signatureUtils.addSignedMessagePrefix(msgHash); - - // 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. - // r + s + v is the most prevalent format from eth_sign, so we attempt this first. - // tslint:disable-next-line:custom-no-magic-numbers - const validVParamValues = [27, 28]; - const ecSignatureRSV = parseSignatureHexAsRSV(signature); - if (_.includes(validVParamValues, ecSignatureRSV.v)) { - const isValidRSVSignature = signatureUtils.isValidECSignature( - prefixedMsgHashHex, - ecSignatureRSV, - normalizedSignerAddress, - ); - if (isValidRSVSignature) { - const convertedSignatureHex = signatureUtils.convertECSignatureToSignatureHex(ecSignatureRSV); - return convertedSignatureHex; - } - } - const ecSignatureVRS = parseSignatureHexAsVRS(signature); - if (_.includes(validVParamValues, ecSignatureVRS.v)) { - const isValidVRSSignature = signatureUtils.isValidECSignature( - prefixedMsgHashHex, - ecSignatureVRS, - normalizedSignerAddress, - ); - if (isValidVRSSignature) { - const convertedSignatureHex = signatureUtils.convertECSignatureToSignatureHex(ecSignatureVRS); - return convertedSignatureHex; - } - } - // Detect if Metamask to transition users to the MetamaskSubprovider - if ((provider as any).isMetaMask) { - throw new Error(OrderError.InvalidMetamaskSigner); - } else { - throw new Error(OrderError.InvalidSignature); - } - }, - /** - * Combines ECSignature with V,R,S and the EthSign signature type for use in 0x protocol - * @param ecSignature The ECSignature of the signed data - * @return Hex encoded string of signature (v,r,s) with Signature Type - */ - convertECSignatureToSignatureHex(ecSignature: ECSignature): string { - const signatureBuffer = Buffer.concat([ - ethUtil.toBuffer(ecSignature.v), - ethUtil.toBuffer(ecSignature.r), - ethUtil.toBuffer(ecSignature.s), - ]); - const signatureHex = `0x${signatureBuffer.toString('hex')}`; - const signatureWithType = signatureUtils.convertToSignatureWithType(signatureHex, SignatureType.EthSign); - return signatureWithType; - }, - /** - * Combines the signature proof and the Signature Type. - * @param signature The hex encoded signature proof - * @param signatureType The signature type, i.e EthSign, Wallet etc. - * @return Hex encoded string of signature proof with Signature Type - */ - convertToSignatureWithType(signature: string, signatureType: SignatureType): string { - const signatureBuffer = Buffer.concat([ethUtil.toBuffer(signature), ethUtil.toBuffer(signatureType)]); - const signatureHex = `0x${signatureBuffer.toString('hex')}`; - return signatureHex; - }, - /** - * Adds the relevant prefix to the message being signed. - * @param message Message to sign - * @return Prefixed message - */ - addSignedMessagePrefix(message: string): string { - assert.isString('message', message); - const msgBuff = ethUtil.toBuffer(message); - const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff); - const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff); - return prefixedMsgHex; - }, - /** - * Parse a 0x protocol hex-encoded signature string into its ECSignature components - * @param signature A hex encoded ecSignature 0x Protocol signature - * @return An ECSignature object with r,s,v parameters - */ - parseECSignature(signature: string): ECSignature { - assert.isHexString('signature', signature); - const ecSignatureTypes = [SignatureType.EthSign, SignatureType.EIP712]; - assert.isOneOfExpectedSignatureTypes(signature, ecSignatureTypes); - - // tslint:disable-next-line:custom-no-magic-numbers - const vrsHex = signature.slice(0, -2); - const ecSignature = parseSignatureHexAsVRS(vrsHex); - - return ecSignature; - }, -}; - -function parseValidatorSignature(signature: string): ValidatorSignature { - assert.isOneOfExpectedSignatureTypes(signature, [SignatureType.Validator]); - // tslint:disable:custom-no-magic-numbers - const validatorSignature = { - validatorAddress: signature.slice(-22, -2), - signature: signature.slice(0, -22), - }; - // tslint:enable:custom-no-magic-numbers - return validatorSignature; -} - -function parseSignatureHexAsVRS(signatureHex: string): ECSignature { - const signatureBuffer = ethUtil.toBuffer(signatureHex); - let v = signatureBuffer[0]; - // HACK: Sometimes v is returned as [0, 1] and sometimes as [27, 28] - // If it is returned as [0, 1], add 27 to both so it becomes [27, 28] - const lowestValidV = 27; - const isProperlyFormattedV = v >= lowestValidV; - if (!isProperlyFormattedV) { - v += lowestValidV; - } - // signatureBuffer contains vrs - const vEndIndex = 1; - const rsIndex = 33; - const r = signatureBuffer.slice(vEndIndex, rsIndex); - const sEndIndex = 65; - const s = signatureBuffer.slice(rsIndex, sEndIndex); - const ecSignature: ECSignature = { - v, - r: ethUtil.bufferToHex(r), - s: ethUtil.bufferToHex(s), - }; - return ecSignature; -} - -function 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/order-utils/src/sorting_utils.ts b/packages/order-utils/src/sorting_utils.ts deleted file mode 100644 index 1de24264f..000000000 --- a/packages/order-utils/src/sorting_utils.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { schemas } from '@0x/json-schemas'; -import { Order } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { assert } from './assert'; -import { constants } from './constants'; -import { rateUtils } from './rate_utils'; - -export const sortingUtils = { - /** - * Takes an array of orders and sorts them by takerAsset/makerAsset rate in ascending order (best rate first). - * Adjusts the rate of each order according to the feeRate and takerFee for that order. - * @param orders An array of objects that extend the Order interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @param feeRate The market rate of ZRX denominated in takerAssetAmount - * (ex. feeRate is 0.1 takerAsset/ZRX if it takes 1 unit of takerAsset to buy 10 ZRX) - * Defaults to 0 - * @return The input orders sorted by rate in ascending order - */ - sortOrdersByFeeAdjustedRate(orders: T[], feeRate: BigNumber = constants.ZERO_AMOUNT): T[] { - assert.doesConformToSchema('orders', orders, schemas.ordersSchema); - assert.isBigNumber('feeRate', feeRate); - const rateCalculator = (order: Order) => rateUtils.getFeeAdjustedRateOfOrder(order, feeRate); - const sortedOrders = sortOrders(orders, rateCalculator); - return sortedOrders; - }, - /** - * Takes an array of fee orders (makerAssetData corresponds to ZRX and takerAssetData corresponds to WETH) - * and sorts them by rate in ascending order (best rate first). Adjusts the rate according to the takerFee. - * @param feeOrders An array of objects that extend the Order interface. All orders should specify ZRX as - * the makerAsset and WETH as the takerAsset. - * @return The input orders sorted by rate in ascending order - */ - sortFeeOrdersByFeeAdjustedRate(feeOrders: T[]): T[] { - assert.doesConformToSchema('feeOrders', feeOrders, schemas.ordersSchema); - const rateCalculator = rateUtils.getFeeAdjustedRateOfFeeOrder.bind(rateUtils); - const sortedOrders = sortOrders(feeOrders, rateCalculator); - return sortedOrders; - }, -}; - -type RateCalculator = (order: Order) => BigNumber; - -// takes an array of orders, copies them, and sorts the copy based on the rate definition provided by rateCalculator -function sortOrders(orders: T[], rateCalculator: RateCalculator): T[] { - const copiedOrders = _.cloneDeep(orders); - copiedOrders.sort((firstOrder, secondOrder) => { - const firstOrderRate = rateCalculator(firstOrder); - const secondOrderRate = rateCalculator(secondOrder); - return firstOrderRate.comparedTo(secondOrderRate); - }); - return copiedOrders; -} 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 deleted file mode 100644 index ae3e36238..000000000 --- a/packages/order-utils/src/store/balance_and_proxy_allowance_lazy_store.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { AssetProxyId } from '@0x/types'; -import { BigNumber } from '@0x/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 readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher; - private _balance: { - [assetData: string]: { - [userAddress: string]: BigNumber; - }; - }; - private _proxyAllowance: { - [assetData: string]: { - [userAddress: string]: BigNumber; - }; - }; - /** - * Instantiates a BalanceAndProxyAllowanceLazyStore - * @param balanceAndProxyAllowanceFetcher Class the implements the AbstractBalanceAndProxyAllowanceFetcher - * @return Instance of BalanceAndProxyAllowanceLazyStore - */ - constructor(balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher) { - this._balanceAndProxyAllowanceFetcher = balanceAndProxyAllowanceFetcher; - this._balance = {}; - this._proxyAllowance = {}; - } - /** - * Get a users balance of an asset - * @param assetData AssetData of interest - * @param userAddress Ethereum address of interest - */ - public async getBalanceAsync(assetData: string, userAddress: string): Promise { - if (_.isUndefined(this._balance[assetData]) || _.isUndefined(this._balance[assetData][userAddress])) { - const balance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, userAddress); - this.setBalance(assetData, userAddress, balance); - } - const cachedBalance = this._balance[assetData][userAddress]; - return cachedBalance; - } - /** - * Set the balance of an asset for a user - * @param assetData AssetData of interest - * @param userAddress Ethereum address of interest - */ - public setBalance(assetData: string, userAddress: string, balance: BigNumber): void { - if (_.isUndefined(this._balance[assetData])) { - this._balance[assetData] = {}; - } - this._balance[assetData][userAddress] = balance; - } - /** - * Clear the balance of an asset for a user - * @param assetData AssetData of interest - * @param userAddress Ethereum address of interest - */ - public deleteBalance(assetData: string, userAddress: string): void { - if (!_.isUndefined(this._balance[assetData])) { - delete this._balance[assetData][userAddress]; - if (_.isEmpty(this._balance[assetData])) { - delete this._balance[assetData]; - } - } - } - /** - * Get the 0x asset proxy allowance - * @param assetData AssetData of interest - * @param userAddress Ethereum address of interest - */ - public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise { - if ( - _.isUndefined(this._proxyAllowance[assetData]) || - _.isUndefined(this._proxyAllowance[assetData][userAddress]) - ) { - const proxyAllowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync( - assetData, - userAddress, - ); - this.setProxyAllowance(assetData, userAddress, proxyAllowance); - } - const cachedProxyAllowance = this._proxyAllowance[assetData][userAddress]; - return cachedProxyAllowance; - } - /** - * Set the 0x asset proxy allowance - * @param assetData AssetData of interest - * @param userAddress Ethereum address of interest - */ - public setProxyAllowance(assetData: string, userAddress: string, proxyAllowance: BigNumber): void { - if (_.isUndefined(this._proxyAllowance[assetData])) { - this._proxyAllowance[assetData] = {}; - } - this._proxyAllowance[assetData][userAddress] = proxyAllowance; - } - /** - * Clear the 0x asset proxy allowance - * @param assetData AssetData of interest - * @param userAddress Ethereum address of interest - */ - public deleteProxyAllowance(assetData: string, userAddress: string): void { - if (!_.isUndefined(this._proxyAllowance[assetData])) { - delete this._proxyAllowance[assetData][userAddress]; - if (_.isEmpty(this._proxyAllowance[assetData])) { - delete this._proxyAllowance[assetData]; - } - } - } - /** - * Clear all ERC721 0x proxy allowances a user has on all items of a specific ERC721 contract - * @param tokenAddress ERc721 token address - * @param userAddress Owner Ethereum address - */ - public deleteAllERC721ProxyAllowance(tokenAddress: string, userAddress: string): void { - for (const assetData in this._proxyAllowance) { - if (this._proxyAllowance.hasOwnProperty(assetData)) { - const decodedAssetData = assetDataUtils.decodeERC721AssetData(assetData); - if ( - decodedAssetData.assetProxyId === AssetProxyId.ERC721 && - decodedAssetData.tokenAddress === tokenAddress && - !_.isUndefined(this._proxyAllowance[assetData][userAddress]) - ) { - delete this._proxyAllowance[assetData][userAddress]; - } - } - } - } - /** - * Delete all balances & allowances - */ - 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 deleted file mode 100644 index afd6f1108..000000000 --- a/packages/order-utils/src/store/order_filled_cancelled_lazy_store.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { AbstractOrderFilledCancelledFetcher } from '../abstract/abstract_order_filled_cancelled_fetcher'; -import { AbstractOrderFilledCancelledLazyStore } from '../abstract/abstract_order_filled_cancelled_lazy_store'; -import { orderHashUtils } from '../order_hash'; - -/** - * 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; - }; - /** - * Instantiate a OrderFilledCancelledLazyStore - * @param orderFilledCancelledFetcher Class instance that implements the AbstractOrderFilledCancelledFetcher - * @returns An instance of OrderFilledCancelledLazyStore - */ - constructor(orderFilledCancelledFetcher: AbstractOrderFilledCancelledFetcher) { - this._orderFilledCancelledFetcher = orderFilledCancelledFetcher; - this._filledTakerAmount = {}; - this._isCancelled = {}; - } - /** - * Get the filledTakerAssetAmount of an order - * @param orderHash OrderHash from order of interest - * @return filledTakerAssetAmount - */ - public async getFilledTakerAmountAsync(orderHash: string): Promise { - if (_.isUndefined(this._filledTakerAmount[orderHash])) { - const filledTakerAmount = await this._orderFilledCancelledFetcher.getFilledTakerAmountAsync(orderHash); - this.setFilledTakerAmount(orderHash, filledTakerAmount); - } - const cachedFilledTakerAmount = this._filledTakerAmount[orderHash]; - return cachedFilledTakerAmount; - } - /** - * Set the filledTakerAssetAmount of an order - * @param orderHash OrderHash from order of interest - * @param filledTakerAmount Desired filledTakerAssetAmount - */ - public setFilledTakerAmount(orderHash: string, filledTakerAmount: BigNumber): void { - this._filledTakerAmount[orderHash] = filledTakerAmount; - } - /** - * Clear the filledTakerAssetAmount of an order - * @param orderHash OrderHash from order of interest - */ - public deleteFilledTakerAmount(orderHash: string): void { - delete this._filledTakerAmount[orderHash]; - } - /** - * Check if an order has been cancelled - * @param orderHash OrderHash from order of interest - * @return Whether the order has been cancelled - */ - public async getIsCancelledAsync(signedOrder: SignedOrder): Promise { - const orderHash = orderHashUtils.getOrderHashHex(signedOrder); - if (_.isUndefined(this._isCancelled[orderHash])) { - const isCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(signedOrder); - this.setIsCancelled(orderHash, isCancelled); - } - const cachedIsCancelled = this._isCancelled[orderHash]; // tslint:disable-line:boolean-naming - return cachedIsCancelled; - } - /** - * Set whether an order has been cancelled or not - * @param orderHash OrderHash from order of interest - * @param isCancelled Whether this order should be cancelled or not - */ - public setIsCancelled(orderHash: string, isCancelled: boolean): void { - this._isCancelled[orderHash] = isCancelled; - } - /** - * Clear whether the order has been cancelled if already set - * @param orderHash OrderHash from order of interest - */ - public deleteIsCancelled(orderHash: string): void { - delete this._isCancelled[orderHash]; - } - /** - * Clear all filled/cancelled state - */ - public deleteAll(): void { - this.deleteAllFilled(); - this.deleteAllIsCancelled(); - } - /** - * Clear all cancelled state - */ - public deleteAllIsCancelled(): void { - this._isCancelled = {}; - } - /** - * Clear all filled state - */ - public deleteAllFilled(): void { - this._filledTakerAmount = {}; - } - /** - * Get the ZRX assetData - */ - public getZRXAssetData(): string { - const zrxAssetData = this._orderFilledCancelledFetcher.getZRXAssetData(); - return zrxAssetData; - } -} diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts deleted file mode 100644 index 55ec553db..000000000 --- a/packages/order-utils/src/types.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -export enum OrderError { - InvalidSignature = 'INVALID_SIGNATURE', - InvalidMetamaskSigner = "MetaMask provider must be wrapped in a MetamaskSubprovider (from the '@0x/subproviders' package) in order to work with this method.", -} - -export enum TradeSide { - Maker = 'maker', - Taker = 'taker', -} - -export enum TransferType { - Trade = 'trade', - Fee = 'fee', -} - -export interface CreateOrderOpts { - takerAddress?: string; - senderAddress?: string; - makerFee?: BigNumber; - takerFee?: BigNumber; - feeRecipientAddress?: string; - salt?: BigNumber; - expirationTimeSeconds?: BigNumber; -} - -/** - * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter. - * You can use `OrderStateUtils` `@0x/order-utils` to perform blockchain lookups for these values. - * Defaults to `makerAssetAmount` values from the orders param. - * slippageBufferAmount: An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills. - * Defaults to 0 - */ -export interface FindOrdersThatCoverMakerAssetFillAmountOpts { - remainingFillableMakerAssetAmounts?: BigNumber[]; - slippageBufferAmount?: BigNumber; -} - -/** - * remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter. - * You can use `OrderStateUtils` `@0x/order-utils` to perform blockchain lookups for these values. - * Defaults to `makerAssetAmount` values from the orders param. - * remainingFillableFeeAmounts: An array of BigNumbers corresponding to the feeOrders parameter. - * You can use OrderStateUtils @0x/order-utils to perform blockchain lookups for these values. - * Defaults to `makerAssetAmount` values from the feeOrders param. - * slippageBufferAmount: An additional amount of fee to be covered by the result in case of trade collisions or partial fills. - * Defaults to 0 - */ -export interface FindFeeOrdersThatCoverFeesForTargetOrdersOpts { - remainingFillableMakerAssetAmounts?: BigNumber[]; - remainingFillableFeeAmounts?: BigNumber[]; - slippageBufferAmount?: BigNumber; -} - -export interface FeeOrdersAndRemainingFeeAmount { - resultFeeOrders: T[]; - feeOrdersRemainingFillableMakerAssetAmounts: BigNumber[]; - remainingFeeAmount: BigNumber; -} - -export interface OrdersAndRemainingFillAmount { - resultOrders: T[]; - ordersRemainingFillableMakerAssetAmounts: BigNumber[]; - remainingFillAmount: BigNumber; -} diff --git a/packages/order-utils/src/utils.ts b/packages/order-utils/src/utils.ts deleted file mode 100644 index 64195dbed..000000000 --- a/packages/order-utils/src/utils.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -export const utils = { - getSignatureTypeIndexIfExists(signature: string): number { - // tslint:disable-next-line:custom-no-magic-numbers - const signatureTypeHex = signature.slice(-2); - const base = 16; - const signatureTypeInt = parseInt(signatureTypeHex, base); - return signatureTypeInt; - }, - getCurrentUnixTimestampSec(): BigNumber { - const milisecondsInSecond = 1000; - return new BigNumber(Date.now() / milisecondsInSecond).integerValue(); - }, - getPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber { - const fillMakerTokenAmount = numerator - .multipliedBy(target) - .div(denominator) - .integerValue(0); - return fillMakerTokenAmount; - }, -}; diff --git a/packages/order-utils/test/assert_test.ts b/packages/order-utils/test/assert_test.ts deleted file mode 100644 index 631971787..000000000 --- a/packages/order-utils/test/assert_test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import * as chai from 'chai'; -import 'mocha'; - -import { assert } from '../src/assert'; - -import { chaiSetup } from './utils/chai_setup'; -import { web3Wrapper } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('Assertion library', () => { - describe('#isSenderAddressHexAsync', () => { - it('throws when address is invalid', async () => { - const address = '0xdeadbeef'; - const varName = 'address'; - return expect(assert.isSenderAddressAsync(varName, address, web3Wrapper)).to.be.rejectedWith( - `Expected ${varName} to be of type ETHAddressHex, encountered: ${address}`, - ); - }); - it('throws when address is unavailable', async () => { - const validUnrelatedAddress = '0x8b0292b11a196601eddce54b665cafeca0347d42'; - const varName = 'address'; - return expect(assert.isSenderAddressAsync(varName, validUnrelatedAddress, web3Wrapper)).to.be.rejectedWith( - `Specified ${varName} ${validUnrelatedAddress} isn't available through the supplied web3 provider`, - ); - }); - it("doesn't throw if address is available", async () => { - const availableAddress = (await web3Wrapper.getAvailableAddressesAsync())[0]; - const varName = 'address'; - return expect(assert.isSenderAddressAsync(varName, availableAddress, web3Wrapper)).to.become(undefined); - }); - }); -}); diff --git a/packages/order-utils/test/asset_data_utils_test.ts b/packages/order-utils/test/asset_data_utils_test.ts deleted file mode 100644 index c498c5a00..000000000 --- a/packages/order-utils/test/asset_data_utils_test.ts +++ /dev/null @@ -1,110 +0,0 @@ -import * as chai from 'chai'; - -import { AssetProxyId, ERC721AssetData } from '@0x/types'; -import { BigNumber } from '@0x/utils'; - -import { assetDataUtils } from '../src/asset_data_utils'; - -import { chaiSetup } from './utils/chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; - -const KNOWN_ERC20_ENCODING = { - address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48', - assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48', -}; -const KNOWN_ERC721_ENCODING = { - address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48', - tokenId: new BigNumber(1), - assetData: - '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001', -}; -const KNOWN_MULTI_ASSET_ENCODING = { - amounts: [new BigNumber(1), new BigNumber(1)], - nestedAssetData: [KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC721_ENCODING.assetData], - assetData: - '0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000', -}; - -describe('assetDataUtils', () => { - it('should encode ERC20', () => { - const assetData = assetDataUtils.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address); - expect(assetData).to.equal(KNOWN_ERC20_ENCODING.assetData); - }); - it('should decode ERC20', () => { - const decodedAssetData = assetDataUtils.decodeERC20AssetData(KNOWN_ERC20_ENCODING.assetData); - expect(decodedAssetData.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address); - expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.ERC20); - }); - it('should encode ERC721', () => { - const assetData = assetDataUtils.encodeERC721AssetData( - KNOWN_ERC721_ENCODING.address, - KNOWN_ERC721_ENCODING.tokenId, - ); - expect(assetData).to.equal(KNOWN_ERC721_ENCODING.assetData); - }); - it('should decode ERC721', () => { - const decodedAssetData = assetDataUtils.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData); - expect(decodedAssetData.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address); - expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.ERC721); - expect(decodedAssetData.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId); - }); - it('should encode ERC20 and ERC721 multiAssetData', () => { - const assetData = assetDataUtils.encodeMultiAssetData( - KNOWN_MULTI_ASSET_ENCODING.amounts, - KNOWN_MULTI_ASSET_ENCODING.nestedAssetData, - ); - expect(assetData).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData); - }); - it('should decode ERC20 and ERC721 multiAssetData', () => { - const decodedAssetData = assetDataUtils.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData); - expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset); - expect(decodedAssetData.amounts).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.amounts); - expect(decodedAssetData.nestedAssetData).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.nestedAssetData); - }); - it('should recursively decode ERC20 and ERC721 multiAssetData', () => { - const decodedAssetData = assetDataUtils.decodeMultiAssetDataRecursively(KNOWN_MULTI_ASSET_ENCODING.assetData); - expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset); - expect(decodedAssetData.amounts).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.amounts); - const decodedErc20AssetData = decodedAssetData.nestedAssetData[0]; - // tslint:disable-next-line:no-unnecessary-type-assertion - const decodedErc721AssetData = decodedAssetData.nestedAssetData[1] as ERC721AssetData; - expect(decodedErc20AssetData.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address); - expect(decodedErc20AssetData.assetProxyId).to.equal(AssetProxyId.ERC20); - expect(decodedErc721AssetData.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address); - expect(decodedErc721AssetData.assetProxyId).to.equal(AssetProxyId.ERC721); - expect(decodedErc721AssetData.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId); - }); - it('should recursively decode nested assetData within multiAssetData', () => { - const amounts = [new BigNumber(1), new BigNumber(1), new BigNumber(2)]; - const nestedAssetData = [ - KNOWN_ERC20_ENCODING.assetData, - KNOWN_ERC721_ENCODING.assetData, - KNOWN_MULTI_ASSET_ENCODING.assetData, - ]; - const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); - const decodedAssetData = assetDataUtils.decodeMultiAssetDataRecursively(assetData); - expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset); - const expectedAmounts = [new BigNumber(1), new BigNumber(1), new BigNumber(2), new BigNumber(2)]; - expect(decodedAssetData.amounts).to.deep.equal(expectedAmounts); - const expectedLength = 4; - expect(decodedAssetData.nestedAssetData.length).to.be.equal(expectedLength); - const decodedErc20AssetData1 = decodedAssetData.nestedAssetData[0]; - // tslint:disable-next-line:no-unnecessary-type-assertion - const decodedErc721AssetData1 = decodedAssetData.nestedAssetData[1] as ERC721AssetData; - const decodedErc20AssetData2 = decodedAssetData.nestedAssetData[2]; - // tslint:disable-next-line:no-unnecessary-type-assertion - const decodedErc721AssetData2 = decodedAssetData.nestedAssetData[3] as ERC721AssetData; - expect(decodedErc20AssetData1.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address); - expect(decodedErc20AssetData1.assetProxyId).to.equal(AssetProxyId.ERC20); - expect(decodedErc721AssetData1.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address); - expect(decodedErc721AssetData1.assetProxyId).to.equal(AssetProxyId.ERC721); - expect(decodedErc721AssetData1.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId); - expect(decodedErc20AssetData2.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address); - expect(decodedErc20AssetData2.assetProxyId).to.equal(AssetProxyId.ERC20); - expect(decodedErc721AssetData2.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address); - expect(decodedErc721AssetData2.assetProxyId).to.equal(AssetProxyId.ERC721); - expect(decodedErc721AssetData2.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId); - }); -}); diff --git a/packages/order-utils/test/eip712_utils_test.ts b/packages/order-utils/test/eip712_utils_test.ts deleted file mode 100644 index a54e49958..000000000 --- a/packages/order-utils/test/eip712_utils_test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { constants } from '../src/constants'; -import { eip712Utils } from '../src/eip712_utils'; - -import { chaiSetup } from './utils/chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('EIP712 Utils', () => { - describe('createTypedData', () => { - it('adds in the EIP712DomainSeparator', () => { - const primaryType = 'Test'; - const typedData = eip712Utils.createTypedData( - primaryType, - { Test: [{ name: 'testValue', type: 'uint256' }] }, - { testValue: '1' }, - constants.NULL_ADDRESS, - ); - expect(typedData.domain).to.not.be.undefined(); - expect(typedData.types.EIP712Domain).to.not.be.undefined(); - const domainObject = typedData.domain; - expect(domainObject.name).to.eq(constants.EIP712_DOMAIN_NAME); - expect(typedData.primaryType).to.eq(primaryType); - }); - }); - describe('createTypedData', () => { - it('adds in the EIP712DomainSeparator', () => { - const typedData = eip712Utils.createZeroExTransactionTypedData( - { - salt: new BigNumber('0'), - data: constants.NULL_BYTES, - signerAddress: constants.NULL_ADDRESS, - }, - constants.NULL_ADDRESS, - ); - expect(typedData.primaryType).to.eq(constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.name); - expect(typedData.types.EIP712Domain).to.not.be.undefined(); - }); - }); -}); diff --git a/packages/order-utils/test/exchange_transfer_simulator_test.ts b/packages/order-utils/test/exchange_transfer_simulator_test.ts deleted file mode 100644 index c26eb1907..000000000 --- a/packages/order-utils/test/exchange_transfer_simulator_test.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { DummyERC20TokenContract, ERC20ProxyContract, ERC20TokenContract } from '@0x/abi-gen-wrappers'; -import * as artifacts from '@0x/contract-artifacts'; -import { BlockchainLifecycle, devConstants } from '@0x/dev-utils'; -import { ExchangeContractErrs } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; - -import { assetDataUtils } from '../src/asset_data_utils'; -import { constants } from '../src/constants'; -import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator'; -import { BalanceAndProxyAllowanceLazyStore } from '../src/store/balance_and_proxy_allowance_lazy_store'; -import { TradeSide, TransferType } from '../src/types'; - -import { chaiSetup } from './utils/chai_setup'; -import { SimpleERC20BalanceAndProxyAllowanceFetcher } from './utils/simple_erc20_balance_and_proxy_allowance_fetcher'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); - -describe('ExchangeTransferSimulator', async () => { - const transferAmount = new BigNumber(5); - let userAddresses: string[]; - let dummyERC20Token: DummyERC20TokenContract; - let coinbase: string; - let sender: string; - let recipient: string; - let exampleAssetData: string; - let exchangeTransferSimulator: ExchangeTransferSimulator; - let txHash: string; - let erc20ProxyAddress: string; - before(async function(): Promise { - const mochaTestTimeoutMs = 20000; - this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this - - userAddresses = await web3Wrapper.getAvailableAddressesAsync(); - [coinbase, sender, recipient] = userAddresses; - - const txDefaults = { - gas: devConstants.GAS_LIMIT, - from: devConstants.TESTRPC_FIRST_ADDRESS, - }; - - const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync( - artifacts.ERC20Proxy, - provider, - txDefaults, - ); - erc20ProxyAddress = erc20Proxy.address; - - const totalSupply = new BigNumber(100000000000000000000); - const name = 'Test'; - const symbol = 'TST'; - const decimals = new BigNumber(18); - // tslint:disable-next-line:no-unused-variable - dummyERC20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync( - artifacts.DummyERC20Token, - provider, - txDefaults, - name, - symbol, - decimals, - totalSupply, - ); - - exampleAssetData = assetDataUtils.encodeERC20AssetData(dummyERC20Token.address); - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - describe('#transferFromAsync', function(): void { - // HACK: For some reason these tests need a slightly longer timeout - const mochaTestTimeoutMs = 3000; - this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this - beforeEach(() => { - const simpleERC20BalanceAndProxyAllowanceFetcher = new SimpleERC20BalanceAndProxyAllowanceFetcher( - (dummyERC20Token as any) as ERC20TokenContract, - erc20ProxyAddress, - ); - const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore( - simpleERC20BalanceAndProxyAllowanceFetcher, - ); - exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore); - }); - it("throws if the user doesn't have enough allowance", async () => { - return expect( - exchangeTransferSimulator.transferFromAsync( - exampleAssetData, - sender, - recipient, - transferAmount, - TradeSide.Taker, - TransferType.Trade, - ), - ).to.be.rejectedWith(ExchangeContractErrs.InsufficientTakerAllowance); - }); - it("throws if the user doesn't have enough balance", async () => { - txHash = await dummyERC20Token.approve.sendTransactionAsync(erc20ProxyAddress, transferAmount, { - from: sender, - }); - await web3Wrapper.awaitTransactionSuccessAsync(txHash); - return expect( - exchangeTransferSimulator.transferFromAsync( - exampleAssetData, - sender, - recipient, - transferAmount, - TradeSide.Maker, - TransferType.Trade, - ), - ).to.be.rejectedWith(ExchangeContractErrs.InsufficientMakerBalance); - }); - it('updates balances and proxyAllowance after transfer', async () => { - txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, { - from: coinbase, - }); - await web3Wrapper.awaitTransactionSuccessAsync(txHash); - - txHash = await dummyERC20Token.approve.sendTransactionAsync(erc20ProxyAddress, transferAmount, { - from: sender, - }); - await web3Wrapper.awaitTransactionSuccessAsync(txHash); - - await exchangeTransferSimulator.transferFromAsync( - exampleAssetData, - sender, - recipient, - transferAmount, - TradeSide.Taker, - TransferType.Trade, - ); - const store = (exchangeTransferSimulator as any)._store; - const senderBalance = await store.getBalanceAsync(exampleAssetData, sender); - const recipientBalance = await store.getBalanceAsync(exampleAssetData, recipient); - const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleAssetData, sender); - expect(senderBalance).to.be.bignumber.equal(0); - expect(recipientBalance).to.be.bignumber.equal(transferAmount); - expect(senderProxyAllowance).to.be.bignumber.equal(0); - }); - it("doesn't update proxyAllowance after transfer if unlimited", async () => { - txHash = await dummyERC20Token.transfer.sendTransactionAsync(sender, transferAmount, { - from: coinbase, - }); - await web3Wrapper.awaitTransactionSuccessAsync(txHash); - txHash = await dummyERC20Token.approve.sendTransactionAsync( - erc20ProxyAddress, - constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, - { - from: sender, - }, - ); - await web3Wrapper.awaitTransactionSuccessAsync(txHash); - await exchangeTransferSimulator.transferFromAsync( - exampleAssetData, - sender, - recipient, - transferAmount, - TradeSide.Taker, - TransferType.Trade, - ); - const store = (exchangeTransferSimulator as any)._store; - const senderBalance = await store.getBalanceAsync(exampleAssetData, sender); - const recipientBalance = await store.getBalanceAsync(exampleAssetData, recipient); - const senderProxyAllowance = await store.getProxyAllowanceAsync(exampleAssetData, sender); - expect(senderBalance).to.be.bignumber.equal(0); - expect(recipientBalance).to.be.bignumber.equal(transferAmount); - expect(senderProxyAllowance).to.be.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); - }); - }); -}); diff --git a/packages/order-utils/test/market_utils_test.ts b/packages/order-utils/test/market_utils_test.ts deleted file mode 100644 index 42ea195bb..000000000 --- a/packages/order-utils/test/market_utils_test.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { marketUtils } from '../src'; -import { constants } from '../src/constants'; - -import { chaiSetup } from './utils/chai_setup'; -import { testOrderFactory } from './utils/test_order_factory'; - -chaiSetup.configure(); -const expect = chai.expect; - -// tslint:disable: no-unused-expression -describe('marketUtils', () => { - describe('#findOrdersThatCoverMakerAssetFillAmount', () => { - describe('no orders', () => { - it('returns empty and unchanged remainingFillAmount', async () => { - const fillAmount = new BigNumber(10); - const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - [], - fillAmount, - ); - expect(resultOrders).to.be.empty; - expect(remainingFillAmount).to.be.bignumber.equal(fillAmount); - }); - }); - describe('orders are completely fillable', () => { - // generate three signed orders each with 10 units of makerAsset, 30 total - const makerAssetAmount = new BigNumber(10); - const inputOrders = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - }, - 3, - ); - it('returns input orders and zero remainingFillAmount when input exactly matches requested fill amount', async () => { - // try to fill 20 units of makerAsset - // include 10 units of slippageBufferAmount - const fillAmount = new BigNumber(20); - const slippageBufferAmount = new BigNumber(10); - const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - inputOrders, - fillAmount, - { - slippageBufferAmount, - }, - ); - expect(resultOrders).to.be.deep.equal(inputOrders); - expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); - }); - it('returns input orders and zero remainingFillAmount when input has more than requested fill amount', async () => { - // try to fill 15 units of makerAsset - // include 10 units of slippageBufferAmount - const fillAmount = new BigNumber(15); - const slippageBufferAmount = new BigNumber(10); - const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - inputOrders, - fillAmount, - { - slippageBufferAmount, - }, - ); - expect(resultOrders).to.be.deep.equal(inputOrders); - expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); - }); - it('returns input orders and non-zero remainingFillAmount when input has less than requested fill amount', async () => { - // try to fill 30 units of makerAsset - // include 5 units of slippageBufferAmount - const fillAmount = new BigNumber(30); - const slippageBufferAmount = new BigNumber(5); - const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - inputOrders, - fillAmount, - { - slippageBufferAmount, - }, - ); - expect(resultOrders).to.be.deep.equal(inputOrders); - expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5)); - }); - it('returns first order and zero remainingFillAmount when requested fill amount is exactly covered by the first order', async () => { - // try to fill 10 units of makerAsset - const fillAmount = new BigNumber(10); - const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - inputOrders, - fillAmount, - ); - expect(resultOrders).to.be.deep.equal([inputOrders[0]]); - expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); - }); - it('returns first two orders and zero remainingFillAmount when requested fill amount is over covered by the first two order', async () => { - // try to fill 15 units of makerAsset - const fillAmount = new BigNumber(15); - const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - inputOrders, - fillAmount, - ); - expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]); - expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); - }); - }); - describe('orders are partially fillable', () => { - // generate three signed orders each with 10 units of makerAsset, 30 total - const makerAssetAmount = new BigNumber(10); - const inputOrders = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - }, - 3, - ); - // generate remainingFillableMakerAssetAmounts that cover different partial fill scenarios - // 1. order is completely filled already - // 2. order is partially fillable - // 3. order is completely fillable - const remainingFillableMakerAssetAmounts = [constants.ZERO_AMOUNT, new BigNumber(5), makerAssetAmount]; - it('returns last two orders and non-zero remainingFillAmount when trying to fill original makerAssetAmounts', async () => { - // try to fill 30 units of makerAsset - const fillAmount = new BigNumber(30); - const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount( - inputOrders, - fillAmount, - { - remainingFillableMakerAssetAmounts, - }, - ); - expect(resultOrders).to.be.deep.equal([inputOrders[1], inputOrders[2]]); - expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(15)); - }); - }); - }); - describe('#findFeeOrdersThatCoverFeesForTargetOrders', () => { - // generate three signed fee orders each with 10 units of ZRX, 30 total - const zrxAmount = new BigNumber(10); - const inputFeeOrders = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount: zrxAmount, - }, - 3, - ); - describe('no target orders', () => { - it('returns empty and zero remainingFeeAmount', async () => { - const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( - [], - inputFeeOrders, - ); - expect(resultFeeOrders).to.be.empty; - expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); - }); - }); - describe('no fee orders', () => { - // generate three signed orders each with 10 units of makerAsset, 30 total - // each signed order requires 10 units of takerFee - const makerAssetAmount = new BigNumber(10); - const takerFee = new BigNumber(10); - const inputOrders = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerFee, - }, - 3, - ); - // generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount - const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount]; - it('returns empty and non-zero remainingFeeAmount', async () => { - const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( - inputOrders, - [], - { - remainingFillableMakerAssetAmounts, - }, - ); - expect(resultFeeOrders).to.be.empty; - expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); - }); - }); - describe('target orders have no fees', () => { - // generate three signed orders each with 10 units of makerAsset, 30 total - const makerAssetAmount = new BigNumber(10); - const inputOrders = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - }, - 3, - ); - it('returns empty and zero remainingFeeAmount', async () => { - const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( - inputOrders, - inputFeeOrders, - ); - expect(resultFeeOrders).to.be.empty; - expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); - }); - }); - describe('target orders require fees and are completely fillable', () => { - // generate three signed orders each with 10 units of makerAsset, 30 total - // each signed order requires 10 units of takerFee - const makerAssetAmount = new BigNumber(10); - const takerFee = new BigNumber(10); - const inputOrders = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerFee, - }, - 3, - ); - it('returns input fee orders and zero remainingFeeAmount', async () => { - const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( - inputOrders, - inputFeeOrders, - ); - expect(resultFeeOrders).to.be.deep.equal(inputFeeOrders); - expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); - }); - }); - describe('target orders require fees and are partially fillable', () => { - // generate three signed orders each with 10 units of makerAsset, 30 total - // each signed order requires 10 units of takerFee - const makerAssetAmount = new BigNumber(10); - const takerFee = new BigNumber(10); - const inputOrders = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerFee, - }, - 3, - ); - // generate remainingFillableMakerAssetAmounts that cover different partial fill scenarios - // 1. order is completely filled already - // 2. order is partially fillable - // 3. order is completely fillable - const remainingFillableMakerAssetAmounts = [constants.ZERO_AMOUNT, new BigNumber(5), makerAssetAmount]; - it('returns first two input fee orders and zero remainingFeeAmount', async () => { - const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( - inputOrders, - inputFeeOrders, - { - remainingFillableMakerAssetAmounts, - }, - ); - expect(resultFeeOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]); - expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT); - }); - }); - describe('target orders require more fees than available', () => { - // generate three signed orders each with 10 units of makerAsset, 30 total - // each signed order requires 20 units of takerFee - const makerAssetAmount = new BigNumber(10); - const takerFee = new BigNumber(20); - const inputOrders = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerFee, - }, - 3, - ); - it('returns input fee orders and non-zero remainingFeeAmount', async () => { - const { resultFeeOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders( - inputOrders, - inputFeeOrders, - ); - expect(resultFeeOrders).to.be.deep.equal(inputFeeOrders); - expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30)); - }); - }); - }); -}); diff --git a/packages/order-utils/test/order_hash_test.ts b/packages/order-utils/test/order_hash_test.ts deleted file mode 100644 index 30fb15a37..000000000 --- a/packages/order-utils/test/order_hash_test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Order } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { orderHashUtils } from '../src'; - -import { constants } from '../src/constants'; - -import { chaiSetup } from './utils/chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('Order hashing', () => { - describe('#getOrderHashHex', () => { - const expectedOrderHash = '0x434c6b41e2fb6dfcfe1b45c4492fb03700798e9c1afc6f801ba6203f948c1fa7'; - const fakeExchangeContractAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48'; - const order: Order = { - makerAddress: constants.NULL_ADDRESS, - takerAddress: constants.NULL_ADDRESS, - senderAddress: constants.NULL_ADDRESS, - feeRecipientAddress: constants.NULL_ADDRESS, - makerAssetData: constants.NULL_ADDRESS, - takerAssetData: constants.NULL_ADDRESS, - exchangeAddress: fakeExchangeContractAddress, - salt: new BigNumber(0), - makerFee: new BigNumber(0), - takerFee: new BigNumber(0), - makerAssetAmount: new BigNumber(0), - takerAssetAmount: new BigNumber(0), - expirationTimeSeconds: new BigNumber(0), - }; - it('calculates the order hash', async () => { - const orderHash = orderHashUtils.getOrderHashHex(order); - expect(orderHash).to.be.equal(expectedOrderHash); - }); - it('calculates the order hash if amounts are strings', async () => { - // It's common for developers using javascript to provide the amounts - // as strings. Since we eventually toString() the BigNumber - // before encoding we should result in the same orderHash in this scenario - // tslint:disable-next-line:no-unnecessary-type-assertion - const orderHash = orderHashUtils.getOrderHashHex({ - ...order, - makerAssetAmount: '0', - takerAssetAmount: '0', - makerFee: '0', - takerFee: '0', - } as any); - expect(orderHash).to.be.equal(expectedOrderHash); - }); - it('throws a readable error message if taker format is invalid', async () => { - const orderWithInvalidtakerFormat = { - ...order, - takerAddress: (null as any) as string, - }; - const expectedErrorMessage = - 'Order taker must be of type string. If you want anyone to be able to fill an order - pass ZeroEx.NULL_ADDRESS'; - expect(() => orderHashUtils.getOrderHashHex(orderWithInvalidtakerFormat)).to.throw(expectedErrorMessage); - }); - }); - describe('#isValidOrderHash', () => { - it('returns false if the value is not a hex string', () => { - const isValid = orderHashUtils.isValidOrderHash('not a hex'); - expect(isValid).to.be.false(); - }); - it('returns false if the length is wrong', () => { - const isValid = orderHashUtils.isValidOrderHash('0xdeadbeef'); - expect(isValid).to.be.false(); - }); - it('returns true if order hash is correct', () => { - const orderHashLength = 65; - const isValid = orderHashUtils.isValidOrderHash(`0x${Array(orderHashLength).join('0')}`); - expect(isValid).to.be.true(); - }); - }); -}); diff --git a/packages/order-utils/test/order_state_utils_test.ts b/packages/order-utils/test/order_state_utils_test.ts deleted file mode 100644 index 42acd54c6..000000000 --- a/packages/order-utils/test/order_state_utils_test.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { AbstractBalanceAndProxyAllowanceFetcher } from '../src/abstract/abstract_balance_and_proxy_allowance_fetcher'; -import { AbstractOrderFilledCancelledFetcher } from '../src/abstract/abstract_order_filled_cancelled_fetcher'; -import { OrderStateUtils } from '../src/order_state_utils'; - -import { chaiSetup } from './utils/chai_setup'; -import { testOrderFactory } from './utils/test_order_factory'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('OrderStateUtils', () => { - describe('#getOpenOrderStateAsync', () => { - const buildMockBalanceFetcher = (takerBalance: BigNumber): AbstractBalanceAndProxyAllowanceFetcher => { - const balanceFetcher = { - async getBalanceAsync(_assetData: string, _userAddress: string): Promise { - return takerBalance; - }, - async getProxyAllowanceAsync(_assetData: string, _userAddress: string): Promise { - return takerBalance; - }, - }; - return balanceFetcher; - }; - const buildMockOrderFilledFetcher = ( - filledAmount: BigNumber = new BigNumber(0), - cancelled: boolean = false, - ): AbstractOrderFilledCancelledFetcher => { - const orderFetcher = { - async getFilledTakerAmountAsync(_orderHash: string): Promise { - return filledAmount; - }, - async isOrderCancelledAsync(_signedOrder: SignedOrder): Promise { - return cancelled; - }, - getZRXAssetData(): string { - return ''; - }, - }; - return orderFetcher; - }; - it('should have valid order state if order can be fully filled with small maker amount', async () => { - const makerAssetAmount = new BigNumber(10); - const takerAssetAmount = new BigNumber(10000000000000000); - const takerBalance = takerAssetAmount; - const orderFilledAmount = new BigNumber(0); - const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); - const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount); - const [signedOrder] = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerAssetAmount, - }, - 1, - ); - - const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); - const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); - expect(orderState.isValid).to.eq(true); - }); - it('should be invalid when an order is partially filled where only a rounding error remains', async () => { - const makerAssetAmount = new BigNumber(1001); - const takerAssetAmount = new BigNumber(3); - const takerBalance = takerAssetAmount; - const orderFilledAmount = new BigNumber(2); - const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); - const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount); - const [signedOrder] = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerAssetAmount, - }, - 1, - ); - - const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); - const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); - expect(orderState.isValid).to.eq(false); - }); - it('should be invalid when an order is cancelled', async () => { - const makerAssetAmount = new BigNumber(1000); - const takerAssetAmount = new BigNumber(2); - const takerBalance = takerAssetAmount; - const orderFilledAmount = new BigNumber(0); - const isCancelled = true; - const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); - const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled); - const [signedOrder] = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerAssetAmount, - }, - 1, - ); - - const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); - const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); - expect(orderState.isValid).to.eq(false); - }); - it('should be invalid when an order is fully filled', async () => { - const makerAssetAmount = new BigNumber(1000); - const takerAssetAmount = new BigNumber(2); - const takerBalance = takerAssetAmount; - const orderFilledAmount = takerAssetAmount; - const isCancelled = false; - const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); - const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount, isCancelled); - const [signedOrder] = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerAssetAmount, - }, - 1, - ); - - const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); - const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder); - expect(orderState.isValid).to.eq(false); - }); - it('should include the transactionHash in orderState if supplied in method invocation', async () => { - const makerAssetAmount = new BigNumber(10); - const takerAssetAmount = new BigNumber(10000000000000000); - const takerBalance = takerAssetAmount; - const orderFilledAmount = new BigNumber(0); - const mockBalanceFetcher = buildMockBalanceFetcher(takerBalance); - const mockOrderFilledFetcher = buildMockOrderFilledFetcher(orderFilledAmount); - const [signedOrder] = testOrderFactory.generateTestSignedOrders( - { - makerAssetAmount, - takerAssetAmount, - }, - 1, - ); - - const orderStateUtils = new OrderStateUtils(mockBalanceFetcher, mockOrderFilledFetcher); - const transactionHash = '0xdeadbeef'; - const orderState = await orderStateUtils.getOpenOrderStateAsync(signedOrder, transactionHash); - expect(orderState.transactionHash).to.eq(transactionHash); - }); - }); -}); diff --git a/packages/order-utils/test/order_validation_utils_test.ts b/packages/order-utils/test/order_validation_utils_test.ts deleted file mode 100644 index d4d12a6a7..000000000 --- a/packages/order-utils/test/order_validation_utils_test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { OrderValidationUtils } from '../src/order_validation_utils'; - -import { chaiSetup } from './utils/chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('OrderValidationUtils', () => { - describe('#isRoundingError', () => { - it('should return false if there is a rounding error of 0.1%', async () => { - const numerator = new BigNumber(20); - const denominator = new BigNumber(999); - const target = new BigNumber(50); - // rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1% - const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target); - expect(isRoundingError).to.be.false(); - }); - - it('should return false if there is a rounding of 0.09%', async () => { - const numerator = new BigNumber(20); - const denominator = new BigNumber(9991); - const target = new BigNumber(500); - // rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09% - const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target); - expect(isRoundingError).to.be.false(); - }); - - it('should return true if there is a rounding error of 0.11%', async () => { - const numerator = new BigNumber(20); - const denominator = new BigNumber(9989); - const target = new BigNumber(500); - // rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011% - const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target); - expect(isRoundingError).to.be.true(); - }); - - it('should return true if there is a rounding error > 0.1%', async () => { - const numerator = new BigNumber(3); - const denominator = new BigNumber(7); - const target = new BigNumber(10); - // rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67% - const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target); - expect(isRoundingError).to.be.true(); - }); - - it('should return false when there is no rounding error', async () => { - const numerator = new BigNumber(1); - const denominator = new BigNumber(2); - const target = new BigNumber(10); - - const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target); - expect(isRoundingError).to.be.false(); - }); - - it('should return false when there is rounding error <= 0.1%', async () => { - // randomly generated numbers - const numerator = new BigNumber(76564); - const denominator = new BigNumber(676373677); - const target = new BigNumber(105762562); - // rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) / - // (76564*105762562/676373677) = 0.0007% - const isRoundingError = OrderValidationUtils.isRoundingErrorFloor(numerator, denominator, target); - expect(isRoundingError).to.be.false(); - }); - }); -}); diff --git a/packages/order-utils/test/rate_utils_test.ts b/packages/order-utils/test/rate_utils_test.ts deleted file mode 100644 index b13878bb5..000000000 --- a/packages/order-utils/test/rate_utils_test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { rateUtils } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { testOrderFactory } from './utils/test_order_factory'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('rateUtils', () => { - const testOrder = testOrderFactory.generateTestSignedOrder({ - makerAssetAmount: new BigNumber(100), - takerAssetAmount: new BigNumber(100), - takerFee: new BigNumber(20), - }); - describe('#getFeeAdjustedRateOfOrder', () => { - it('throws when feeRate is less than zero', async () => { - const feeRate = new BigNumber(-1); - expect(() => rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate)).to.throw( - 'Expected feeRate: -1 to be greater than or equal to 0', - ); - }); - it('correctly calculates fee adjusted rate when feeRate is provided', async () => { - const feeRate = new BigNumber(2); // ZRX costs 2 units of takerAsset per 1 unit of ZRX - const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfOrder(testOrder, feeRate); - // the order actually takes 100 + (2 * 20) takerAsset units to fill 100 units of makerAsset - expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1.4)); - }); - it('correctly calculates fee adjusted rate when no feeRate is provided', async () => { - const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfOrder(testOrder); - // because no feeRate was provided we just assume 0 fees - // the order actually takes 100 takerAsset units to fill 100 units of makerAsset - expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1)); - }); - }); - describe('#getFeeAdjustedRateOfFeeOrder', () => { - it('throws when takerFee exceeds makerAssetAmount', async () => { - const badOrder = testOrderFactory.generateTestSignedOrder({ - makerAssetAmount: new BigNumber(100), - takerFee: new BigNumber(101), - }); - expect(() => rateUtils.getFeeAdjustedRateOfFeeOrder(badOrder)).to.throw( - 'Expected takerFee: "101" to be less than makerAssetAmount: "100"', - ); - }); - it('correctly calculates fee adjusted rate', async () => { - const feeAdjustedRate = rateUtils.getFeeAdjustedRateOfFeeOrder(testOrder); - // the order actually takes 100 takerAsset units to fill (100 - 20) units of makerAsset - expect(feeAdjustedRate).to.bignumber.equal(new BigNumber(1.25)); - }); - }); -}); diff --git a/packages/order-utils/test/remaining_fillable_calculator_test.ts b/packages/order-utils/test/remaining_fillable_calculator_test.ts deleted file mode 100644 index affad8f1c..000000000 --- a/packages/order-utils/test/remaining_fillable_calculator_test.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { SignedOrder } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as chai from 'chai'; -import 'mocha'; - -import { RemainingFillableCalculator } from '../src/remaining_fillable_calculator'; - -import { chaiSetup } from './utils/chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('RemainingFillableCalculator', () => { - let calculator: RemainingFillableCalculator; - let signedOrder: SignedOrder; - let transferrableMakeAssetAmount: BigNumber; - let transferrableMakerFeeTokenAmount: BigNumber; - let remainingMakeAssetAmount: BigNumber; - let makerAmount: BigNumber; - let takerAmount: BigNumber; - let makerFeeAmount: BigNumber; - let isMakeAssetZRX: boolean; - const makerAssetData: string = '0x1'; - const takerAssetData: string = '0x2'; - const decimals: number = 4; - const zero: BigNumber = new BigNumber(0); - const zeroAddress = '0x0'; - const signature: string = - '0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403'; - beforeEach(async () => { - [makerAmount, takerAmount, makerFeeAmount] = [ - Web3Wrapper.toBaseUnitAmount(new BigNumber(50), decimals), - Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals), - Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals), - ]; - [transferrableMakeAssetAmount, transferrableMakerFeeTokenAmount] = [ - Web3Wrapper.toBaseUnitAmount(new BigNumber(50), decimals), - Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals), - ]; - }); - function buildSignedOrder(): SignedOrder { - return { - signature, - exchangeAddress: zeroAddress, - feeRecipientAddress: zeroAddress, - senderAddress: zeroAddress, - makerAddress: zeroAddress, - takerAddress: zeroAddress, - makerFee: makerFeeAmount, - takerFee: zero, - makerAssetAmount: makerAmount, - takerAssetAmount: takerAmount, - makerAssetData, - takerAssetData, - salt: zero, - expirationTimeSeconds: zero, - }; - } - describe('Maker token is NOT ZRX', () => { - before(async () => { - isMakeAssetZRX = false; - }); - it('calculates the correct amount when unfilled and funds available', () => { - signedOrder = buildSignedOrder(); - remainingMakeAssetAmount = signedOrder.makerAssetAmount; - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(remainingMakeAssetAmount); - }); - it('calculates the correct amount when partially filled and funds available', () => { - signedOrder = buildSignedOrder(); - remainingMakeAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(remainingMakeAssetAmount); - }); - it('calculates the amount to be 0 when all fee funds are transferred', () => { - signedOrder = buildSignedOrder(); - transferrableMakerFeeTokenAmount = zero; - remainingMakeAssetAmount = signedOrder.makerAssetAmount; - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(zero); - }); - it('calculates the correct amount when balance is less than remaining fillable', () => { - signedOrder = buildSignedOrder(); - const partiallyFilledAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); - remainingMakeAssetAmount = signedOrder.makerAssetAmount.minus(partiallyFilledAmount); - transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(partiallyFilledAmount); - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(transferrableMakeAssetAmount); - }); - describe('Order to Fee Ratio is < 1', () => { - beforeEach(async () => { - [makerAmount, takerAmount, makerFeeAmount] = [ - Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals), - Web3Wrapper.toBaseUnitAmount(new BigNumber(6), decimals), - Web3Wrapper.toBaseUnitAmount(new BigNumber(6), decimals), - ]; - }); - it('calculates the correct amount when funds unavailable', () => { - signedOrder = buildSignedOrder(); - remainingMakeAssetAmount = signedOrder.makerAssetAmount; - const transferredAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); - transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(transferredAmount); - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(transferrableMakeAssetAmount); - }); - }); - describe('Ratio is not evenly divisble', () => { - beforeEach(async () => { - [makerAmount, takerAmount, makerFeeAmount] = [ - Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals), - Web3Wrapper.toBaseUnitAmount(new BigNumber(7), decimals), - Web3Wrapper.toBaseUnitAmount(new BigNumber(7), decimals), - ]; - }); - it('calculates the correct amount when funds unavailable', () => { - signedOrder = buildSignedOrder(); - remainingMakeAssetAmount = signedOrder.makerAssetAmount; - const transferredAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); - transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(transferredAmount); - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - const calculatedFillableAmount = calculator.computeRemainingFillable(); - expect(calculatedFillableAmount.isLessThanOrEqualTo(transferrableMakeAssetAmount)).to.be.true(); - expect(calculatedFillableAmount).to.be.bignumber.greaterThan(new BigNumber(0)); - const orderToFeeRatio = signedOrder.makerAssetAmount.dividedBy(signedOrder.makerFee); - const calculatedFeeAmount = calculatedFillableAmount.dividedBy(orderToFeeRatio); - expect(calculatedFeeAmount).to.be.bignumber.lessThan(transferrableMakerFeeTokenAmount); - }); - }); - }); - describe('Maker Token is ZRX', () => { - before(async () => { - isMakeAssetZRX = true; - }); - it('calculates the correct amount when unfilled and funds available', () => { - signedOrder = buildSignedOrder(); - transferrableMakeAssetAmount = makerAmount.plus(makerFeeAmount); - transferrableMakerFeeTokenAmount = transferrableMakeAssetAmount; - remainingMakeAssetAmount = signedOrder.makerAssetAmount; - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(remainingMakeAssetAmount); - }); - it('calculates the correct amount when partially filled and funds available', () => { - signedOrder = buildSignedOrder(); - remainingMakeAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals); - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(remainingMakeAssetAmount); - }); - it('calculates the amount to be 0 when all fee funds are transferred', () => { - signedOrder = buildSignedOrder(); - transferrableMakeAssetAmount = zero; - transferrableMakerFeeTokenAmount = zero; - remainingMakeAssetAmount = signedOrder.makerAssetAmount; - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - expect(calculator.computeRemainingFillable()).to.be.bignumber.equal(zero); - }); - it('calculates the correct amount when balance is less than remaining fillable', () => { - signedOrder = buildSignedOrder(); - const partiallyFilledAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals); - remainingMakeAssetAmount = signedOrder.makerAssetAmount.minus(partiallyFilledAmount); - transferrableMakeAssetAmount = remainingMakeAssetAmount.minus(partiallyFilledAmount); - transferrableMakerFeeTokenAmount = transferrableMakeAssetAmount; - - const orderToFeeRatio = signedOrder.makerAssetAmount.dividedToIntegerBy(signedOrder.makerFee); - const expectedFillableAmount = new BigNumber(450980); - calculator = new RemainingFillableCalculator( - signedOrder.makerFee, - signedOrder.makerAssetAmount, - isMakeAssetZRX, - transferrableMakeAssetAmount, - transferrableMakerFeeTokenAmount, - remainingMakeAssetAmount, - ); - const calculatedFillableAmount = calculator.computeRemainingFillable(); - const numberOfFillsInRatio = calculatedFillableAmount.dividedToIntegerBy(orderToFeeRatio); - const calculatedFillableAmountPlusFees = calculatedFillableAmount.plus(numberOfFillsInRatio); - expect(calculatedFillableAmountPlusFees).to.be.bignumber.lessThan(transferrableMakeAssetAmount); - expect(calculatedFillableAmountPlusFees).to.be.bignumber.lessThan(remainingMakeAssetAmount); - expect(calculatedFillableAmount).to.be.bignumber.equal(expectedFillableAmount); - expect(numberOfFillsInRatio.decimalPlaces()).to.be.equal(0); - }); - }); -}); diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts deleted file mode 100644 index 937382056..000000000 --- a/packages/order-utils/test/signature_utils_test.ts +++ /dev/null @@ -1,324 +0,0 @@ -import { Order, SignatureType } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import { JSONRPCErrorCallback, JSONRPCRequestPayload } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; -import 'mocha'; - -import { generatePseudoRandomSalt, orderHashUtils } from '../src'; -import { constants } from '../src/constants'; -import { signatureUtils } from '../src/signature_utils'; - -import { chaiSetup } from './utils/chai_setup'; -import { provider, web3Wrapper } from './utils/web3_wrapper'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('Signature utils', () => { - let makerAddress: string; - const fakeExchangeContractAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48'; - let order: Order; - before(async () => { - const availableAddreses = await web3Wrapper.getAvailableAddressesAsync(); - makerAddress = availableAddreses[0]; - order = { - makerAddress, - takerAddress: constants.NULL_ADDRESS, - senderAddress: constants.NULL_ADDRESS, - feeRecipientAddress: constants.NULL_ADDRESS, - makerAssetData: constants.NULL_ADDRESS, - takerAssetData: constants.NULL_ADDRESS, - exchangeAddress: fakeExchangeContractAddress, - salt: new BigNumber(0), - makerFee: new BigNumber(0), - takerFee: new BigNumber(0), - makerAssetAmount: new BigNumber(0), - takerAssetAmount: new BigNumber(0), - expirationTimeSeconds: new BigNumber(0), - }; - }); - describe('#isValidSignatureAsync', () => { - let dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0'; - const ethSignSignature = - '0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403'; - let address = '0x5409ed021d9299bf6814279a6a1411a7e866a631'; - - it("should return false if the data doesn't pertain to the signature & address", async () => { - const bytes32Zeros = '0x0000000000000000000000000000000000000000000000000000000000000000'; - expect( - await signatureUtils.isValidSignatureAsync(provider, bytes32Zeros, ethSignSignature, address), - ).to.be.false(); - }); - it("should return false if the address doesn't pertain to the signature & data", async () => { - const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42'; - expect( - await signatureUtils.isValidSignatureAsync(provider, dataHex, ethSignSignature, validUnrelatedAddress), - ).to.be.false(); - }); - it("should return false if the signature doesn't pertain to the dataHex & address", async () => { - const signatureArray = ethSignSignature.split(''); - // tslint:disable-next-line:custom-no-magic-numbers - signatureArray[5] = 'C'; // V = 28, instead of 27 - const wrongSignature = signatureArray.join(''); - expect( - await signatureUtils.isValidSignatureAsync(provider, dataHex, wrongSignature, address), - ).to.be.false(); - }); - - it('should throw if signatureType is invalid', () => { - const signatureArray = ethSignSignature.split(''); - signatureArray[3] = '9'; // SignatureType w/ index 9 doesn't exist - const signatureWithInvalidType = signatureArray.join(''); - expect( - signatureUtils.isValidSignatureAsync(provider, dataHex, signatureWithInvalidType, address), - ).to.be.rejected(); - }); - - it('should return true for a valid Ecrecover (EthSign) signature', async () => { - const isValidSignatureLocal = await signatureUtils.isValidSignatureAsync( - provider, - dataHex, - ethSignSignature, - address, - ); - expect(isValidSignatureLocal).to.be.true(); - }); - - it('should return true for a valid EIP712 signature', async () => { - dataHex = '0xa1d7403bcbbcd75ec233cfd6584ff8dabed677d0e9bb32c2bea94e9dd8a109da'; - address = '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb'; - const eip712Signature = - '0x1bdde07aac4bf12c12ddbb155919c43eba4146a2cfcf904a862950dbebe332554c6674975603eb5a4eaf8fd7f2e06350267e5b36cda9851a89f8bb49fe2fc9afe202'; - const isValidSignatureLocal = await signatureUtils.isValidSignatureAsync( - provider, - dataHex, - eip712Signature, - address, - ); - expect(isValidSignatureLocal).to.be.true(); - }); - }); - describe('#isValidECSignature', () => { - const signature = { - v: 27, - r: '0xaca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d64393', - s: '0x46b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf2', - }; - const data = '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad'; - const address = '0x0e5cb767cce09a7f3ca594df118aa519be5e2b5a'; - - it("should return false if the data doesn't pertain to the signature & address", async () => { - expect(signatureUtils.isValidECSignature('0x0', signature, address)).to.be.false(); - }); - it("should return false if the address doesn't pertain to the signature & data", async () => { - const validUnrelatedAddress = '0x8b0292b11a196601ed2ce54b665cafeca0347d42'; - expect(signatureUtils.isValidECSignature(data, signature, validUnrelatedAddress)).to.be.false(); - }); - it("should return false if the signature doesn't pertain to the data & address", async () => { - const wrongSignature = _.assign({}, signature, { v: 28 }); - expect(signatureUtils.isValidECSignature(data, wrongSignature, address)).to.be.false(); - }); - it('should return true if the signature does pertain to the data & address', async () => { - const isValidSignatureLocal = signatureUtils.isValidECSignature(data, signature, address); - expect(isValidSignatureLocal).to.be.true(); - }); - }); - describe('#generateSalt', () => { - it('generates different salts', () => { - const isEqual = generatePseudoRandomSalt().eq(generatePseudoRandomSalt()); - expect(isEqual).to.be.false(); - }); - it('generates salt in range [0..2^256)', () => { - const salt = generatePseudoRandomSalt(); - expect(salt.isGreaterThanOrEqualTo(0)).to.be.true(); - // tslint:disable-next-line:custom-no-magic-numbers - const twoPow256 = new BigNumber(2).pow(256); - expect(salt.isLessThan(twoPow256)).to.be.true(); - }); - }); - describe('#ecSignOrderAsync', () => { - it('should default to eth_sign if eth_signTypedData is unavailable', async () => { - const expectedSignature = - '0x1c3582f06356a1314dbf1c0e534c4d8e92e59b056ee607a7ff5a825f5f2cc5e6151c5cc7fdd420f5608e4d5bef108e42ad90c7a4b408caef32e24374cf387b0d7603'; - - const fakeProvider = { - async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise { - if (payload.method === 'eth_signTypedData') { - callback(new Error('Internal RPC Error')); - } else if (payload.method === 'eth_sign') { - const [address, message] = payload.params; - const signature = await web3Wrapper.signMessageAsync(address, message); - callback(null, { - id: 42, - jsonrpc: '2.0', - result: signature, - }); - } else { - callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] }); - } - }, - }; - const signedOrder = await signatureUtils.ecSignOrderAsync(fakeProvider, order, makerAddress); - expect(signedOrder.signature).to.equal(expectedSignature); - }); - it('should throw if the user denies the signing request', async () => { - const fakeProvider = { - async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise { - if (payload.method === 'eth_signTypedData') { - callback(new Error('User denied message signature')); - } else if (payload.method === 'eth_sign') { - const [address, message] = payload.params; - const signature = await web3Wrapper.signMessageAsync(address, message); - callback(null, { - id: 42, - jsonrpc: '2.0', - result: signature, - }); - } else { - callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] }); - } - }, - }; - expect(signatureUtils.ecSignOrderAsync(fakeProvider, order, makerAddress)).to.to.be.rejectedWith( - 'User denied message signature', - ); - }); - }); - describe('#ecSignHashAsync', () => { - before(async () => { - const availableAddreses = await web3Wrapper.getAvailableAddressesAsync(); - makerAddress = availableAddreses[0]; - }); - it('should return the correct Signature', async () => { - const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0'; - const expectedSignature = - '0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403'; - const ecSignature = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress); - expect(ecSignature).to.equal(expectedSignature); - }); - it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => { - const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004'; - const expectedSignature = - '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03'; - - const fakeProvider = { - async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise { - if (payload.method === 'eth_sign') { - const [address, message] = payload.params; - expect(message).to.equal(orderHash); - const signature = await web3Wrapper.signMessageAsync(address, message); - // tslint:disable-next-line:custom-no-magic-numbers - const rsvHex = `0x${signature.substr(130)}${signature.substr(2, 128)}`; - callback(null, { - id: 42, - jsonrpc: '2.0', - result: rsvHex, - }); - } else { - callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] }); - } - }, - }; - const ecSignature = await signatureUtils.ecSignHashAsync(fakeProvider, orderHash, makerAddress); - expect(ecSignature).to.equal(expectedSignature); - }); - it('should return the correct Signature for signatureHex concatenated as V + R + S', async () => { - const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004'; - const expectedSignature = - '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03'; - const fakeProvider = { - async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise { - if (payload.method === 'eth_sign') { - const [address, message] = payload.params; - const signature = await web3Wrapper.signMessageAsync(address, message); - callback(null, { - id: 42, - jsonrpc: '2.0', - result: signature, - }); - } else { - callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] }); - } - }, - }; - - const ecSignature = await signatureUtils.ecSignHashAsync(fakeProvider, orderHash, makerAddress); - expect(ecSignature).to.equal(expectedSignature); - }); - it('should return a valid signature', async () => { - const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004'; - const ecSignature = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress); - - const isValidSignature = await signatureUtils.isValidSignatureAsync( - provider, - orderHash, - ecSignature, - makerAddress, - ); - expect(isValidSignature).to.be.true(); - }); - }); - describe('#ecSignTypedDataOrderAsync', () => { - it('should result in the same signature as signing the order hash without an ethereum message prefix', async () => { - // Note: Since order hash is an EIP712 hash the result of a valid EIP712 signature - // of order hash is the same as signing the order without the Ethereum Message prefix. - const orderHashHex = orderHashUtils.getOrderHashHex(order); - const sig = ethUtil.ecsign( - ethUtil.toBuffer(orderHashHex), - Buffer.from('F2F48EE19680706196E2E339E5DA3491186E0C4C5030670656B0E0164837257D', 'hex'), - ); - const signatureBuffer = Buffer.concat([ - ethUtil.toBuffer(sig.v), - ethUtil.toBuffer(sig.r), - ethUtil.toBuffer(sig.s), - ethUtil.toBuffer(SignatureType.EIP712), - ]); - const signatureHex = `0x${signatureBuffer.toString('hex')}`; - const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(provider, order, makerAddress); - const isValidSignature = await signatureUtils.isValidSignatureAsync( - provider, - orderHashHex, - signedOrder.signature, - makerAddress, - ); - expect(signatureHex).to.eq(signedOrder.signature); - expect(isValidSignature).to.eq(true); - }); - it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => { - const expectedSignature = - '0x1cd472c439833774b55d248c31b6585f21aea1b9363ebb4ec58549e46b62eb5a6f696f5781f62de008ee7f77650ef940d99c97ec1dee67b3f5cea1bbfdfeb2eba602'; - const fakeProvider = { - async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise { - if (payload.method === 'eth_signTypedData') { - const [address, typedData] = payload.params; - const signature = await web3Wrapper.signTypedDataAsync(address, typedData); - callback(null, { - id: 42, - jsonrpc: '2.0', - result: signature, - }); - } else { - callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] }); - } - }, - }; - const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(fakeProvider, order, makerAddress); - expect(signedOrder.signature).to.equal(expectedSignature); - }); - }); - describe('#convertECSignatureToSignatureHex', () => { - const ecSignature: ECSignature = { - v: 27, - r: '0xaca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d64393', - s: '0x46b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf2', - }; - it('should concatenate v,r,s and append the EthSign signature type', async () => { - const expectedSignatureWithSignatureType = - '0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203'; - const signatureWithSignatureType = signatureUtils.convertECSignatureToSignatureHex(ecSignature); - expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType); - }); - }); -}); diff --git a/packages/order-utils/test/sorting_utils_test.ts b/packages/order-utils/test/sorting_utils_test.ts deleted file mode 100644 index 0b8757496..000000000 --- a/packages/order-utils/test/sorting_utils_test.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import 'mocha'; - -import { sortingUtils } from '../src'; - -import { chaiSetup } from './utils/chai_setup'; -import { testOrderFactory } from './utils/test_order_factory'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('sortingUtils', () => { - describe('#sortOrdersByFeeAdjustedRate', () => { - const feeRate = new BigNumber(1); // ZRX costs 1 unit of takerAsset per 1 unit of ZRX - // rate: 2 takerAsset / makerAsset - const testOrder1 = testOrderFactory.generateTestSignedOrder({ - makerAssetAmount: new BigNumber(100), - takerAssetAmount: new BigNumber(200), - }); - // rate: 1 takerAsset / makerAsset - const testOrder2 = testOrderFactory.generateTestSignedOrder({ - makerAssetAmount: new BigNumber(100), - takerAssetAmount: new BigNumber(100), - }); - // rate: 2.5 takerAsset / makerAsset - const testOrder3 = testOrderFactory.generateTestSignedOrder({ - makerAssetAmount: new BigNumber(100), - takerAssetAmount: new BigNumber(200), - takerFee: new BigNumber(50), - }); - it('correctly sorts by fee adjusted rate when feeRate is Provided', async () => { - const orders = [testOrder1, testOrder2, testOrder3]; - const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders, feeRate); - expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]); - }); - it('correctly sorts by fee adjusted rate when no feeRate is Provided', async () => { - const orders = [testOrder1, testOrder2, testOrder3]; - const sortedOrders = sortingUtils.sortOrdersByFeeAdjustedRate(orders); - expect(sortedOrders).to.deep.equal([testOrder2, testOrder1, testOrder3]); - }); - }); - describe('#sortFeeOrdersByFeeAdjustedRate', () => { - // rate: 200 takerAsset / makerAsset - const testOrder1 = testOrderFactory.generateTestSignedOrder({ - makerAssetAmount: new BigNumber(100), - takerAssetAmount: new BigNumber(200), - takerFee: new BigNumber(99), - }); - // rate: 1 takerAsset / makerAsset - const testOrder2 = testOrderFactory.generateTestSignedOrder({ - makerAssetAmount: new BigNumber(100), - takerAssetAmount: new BigNumber(100), - }); - // rate: 4 takerAsset / makerAsset - const testOrder3 = testOrderFactory.generateTestSignedOrder({ - makerAssetAmount: new BigNumber(100), - takerAssetAmount: new BigNumber(200), - takerFee: new BigNumber(50), - }); - it('correctly sorts by fee adjusted rate', async () => { - const orders = [testOrder1, testOrder2, testOrder3]; - const sortedOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate(orders); - expect(sortedOrders).to.deep.equal([testOrder2, testOrder3, testOrder1]); - }); - }); -}); diff --git a/packages/order-utils/test/utils/chai_setup.ts b/packages/order-utils/test/utils/chai_setup.ts deleted file mode 100644 index 1a8733093..000000000 --- a/packages/order-utils/test/utils/chai_setup.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as chai from 'chai'; -import chaiAsPromised = require('chai-as-promised'); -import ChaiBigNumber = require('chai-bignumber'); -import * as dirtyChai from 'dirty-chai'; - -export const chaiSetup = { - configure(): void { - chai.config.includeStack = true; - chai.use(ChaiBigNumber()); - chai.use(dirtyChai); - chai.use(chaiAsPromised); - }, -}; 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 deleted file mode 100644 index d3ea8b456..000000000 --- a/packages/order-utils/test/utils/simple_erc20_balance_and_proxy_allowance_fetcher.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ERC20TokenContract } from '@0x/abi-gen-wrappers'; -import { BigNumber } from '@0x/utils'; - -import { AbstractBalanceAndProxyAllowanceFetcher } from '../../src/abstract/abstract_balance_and_proxy_allowance_fetcher'; - -export class SimpleERC20BalanceAndProxyAllowanceFetcher implements AbstractBalanceAndProxyAllowanceFetcher { - private readonly _erc20TokenContract: ERC20TokenContract; - private readonly _erc20ProxyAddress: string; - constructor(erc20TokenWrapper: ERC20TokenContract, erc20ProxyAddress: string) { - this._erc20TokenContract = erc20TokenWrapper; - this._erc20ProxyAddress = erc20ProxyAddress; - } - public async getBalanceAsync(_assetData: string, userAddress: string): Promise { - // HACK: We cheat and don't pass in the assetData since it's always the same token used - // in our tests. - const balance = await this._erc20TokenContract.balanceOf.callAsync(userAddress); - return balance; - } - public async getProxyAllowanceAsync(_assetData: string, userAddress: string): Promise { - // HACK: We cheat and don't pass in the assetData since it's always the same token used - // in our tests. - const proxyAllowance = await this._erc20TokenContract.allowance.callAsync(userAddress, this._erc20ProxyAddress); - return proxyAllowance; - } -} diff --git a/packages/order-utils/test/utils/test_order_factory.ts b/packages/order-utils/test/utils/test_order_factory.ts deleted file mode 100644 index 4efe0b38e..000000000 --- a/packages/order-utils/test/utils/test_order_factory.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Order, SignedOrder } from '@0x/types'; -import * as _ from 'lodash'; - -import { constants } from '../../src/constants'; -import { orderFactory } from '../../src/order_factory'; - -const BASE_TEST_ORDER: Order = orderFactory.createOrder( - constants.NULL_ADDRESS, - constants.ZERO_AMOUNT, - constants.NULL_ERC20_ASSET_DATA, - constants.ZERO_AMOUNT, - constants.NULL_ERC20_ASSET_DATA, - constants.NULL_ADDRESS, -); -const BASE_TEST_SIGNED_ORDER: SignedOrder = { - ...BASE_TEST_ORDER, - signature: constants.NULL_BYTES, -}; - -export const testOrderFactory = { - generateTestSignedOrder(partialOrder: Partial): SignedOrder { - return transformObject(BASE_TEST_SIGNED_ORDER, partialOrder); - }, - generateTestSignedOrders(partialOrder: Partial, numOrders: number): SignedOrder[] { - const baseTestOrders = _.map(_.range(numOrders), () => BASE_TEST_SIGNED_ORDER); - return _.map(baseTestOrders, order => transformObject(order, partialOrder)); - }, -}; - -function transformObject(input: T, transformation: Partial): T { - const copy = _.cloneDeep(input); - return _.assign(copy, transformation); -} diff --git a/packages/order-utils/test/utils/web3_wrapper.ts b/packages/order-utils/test/utils/web3_wrapper.ts deleted file mode 100644 index accfcb7fe..000000000 --- a/packages/order-utils/test/utils/web3_wrapper.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { web3Factory } from '@0x/dev-utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { Provider } from 'ethereum-types'; - -const provider: Provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true }); -const web3Wrapper = new Web3Wrapper(provider); - -export { provider, web3Wrapper }; diff --git a/packages/order-utils/tsconfig.json b/packages/order-utils/tsconfig.json deleted file mode 100644 index 718e623c7..000000000 --- a/packages/order-utils/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig", - "compilerOptions": { - "outDir": "lib", - "rootDir": "." - }, - "include": ["src/**/*", "test/**/*"] -} diff --git a/packages/order-utils/tslint.json b/packages/order-utils/tslint.json deleted file mode 100644 index dd9053357..000000000 --- a/packages/order-utils/tslint.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["@0x/tslint-config"] -} diff --git a/packages/order-utils/typedoc-tsconfig.json b/packages/order-utils/typedoc-tsconfig.json deleted file mode 100644 index b9c6b36f3..000000000 --- a/packages/order-utils/typedoc-tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../typedoc-tsconfig", - "compilerOptions": { - "outDir": "lib" - }, - "include": ["src/**/*", "test/**/*"] -} -- cgit v1.2.3