Merge branch 'development' into sol-compile-lot
This commit is contained in:
commit
c1ec849554
@ -81,7 +81,7 @@
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
@ -94,7 +94,7 @@
|
||||
"source-map-support": "^0.5.0",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"webpack": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -56,14 +56,14 @@
|
||||
"@types/tmp": "^0.0.33",
|
||||
"@types/yargs": "^10.0.0",
|
||||
"chai": "^4.1.2",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^5.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -36,7 +36,7 @@
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/valid-url": "^1.0.2",
|
||||
"chai": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
@ -44,7 +44,7 @@
|
||||
"nyc": "^11.0.1",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/json-schemas": "^1.0.1-rc.4",
|
||||
|
@ -34,13 +34,13 @@
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"chai": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/typescript-typings": "^1.0.4",
|
||||
|
@ -64,7 +64,7 @@
|
||||
"devDependencies": {
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/fetch-mock": "^5.12.2",
|
||||
"@types/fetch-mock": "^6.0.3",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/query-string": "^5.0.1",
|
||||
@ -73,7 +73,7 @@
|
||||
"async-child-process": "^1.1.1",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"fetch-mock": "^5.13.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
@ -83,7 +83,7 @@
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "~0.8.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -57,7 +57,7 @@
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
@ -68,7 +68,7 @@
|
||||
"sinon": "^4.0.0",
|
||||
"source-map-support": "^0.5.0",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"web3-provider-engine": "14.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -59,7 +59,7 @@
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
@ -68,7 +68,7 @@
|
||||
"solc": "^0.4.24",
|
||||
"solhint": "^1.2.1",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -104,6 +104,17 @@ describe('FillOrder Tests', () => {
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
|
||||
});
|
||||
it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount with zero decimals', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
orderScenario: {
|
||||
...defaultFillScenario.orderScenario,
|
||||
makerAssetAmountScenario: OrderAssetAmountScenario.Small,
|
||||
makerAssetDataScenario: AssetDataScenario.ERC20ZeroDecimals,
|
||||
},
|
||||
};
|
||||
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(provider, fillScenario);
|
||||
});
|
||||
it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => {
|
||||
const fillScenario = {
|
||||
...defaultFillScenario,
|
||||
|
@ -81,6 +81,12 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
erc20FiveDecimalTokenCount,
|
||||
fiveDecimals,
|
||||
);
|
||||
const zeroDecimals = new BigNumber(0);
|
||||
const erc20ZeroDecimalTokenCount = 2;
|
||||
const [erc20ZeroDecimalTokenA, erc20ZeroDecimalTokenB] = await erc20Wrapper.deployDummyTokensAsync(
|
||||
erc20ZeroDecimalTokenCount,
|
||||
zeroDecimals,
|
||||
);
|
||||
const erc20Proxy = await erc20Wrapper.deployProxyAsync();
|
||||
await erc20Wrapper.setBalancesAndAllowancesAsync();
|
||||
|
||||
@ -119,6 +125,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
|
||||
zrxToken.address,
|
||||
[erc20EighteenDecimalTokenA.address, erc20EighteenDecimalTokenB.address],
|
||||
[erc20FiveDecimalTokenA.address, erc20FiveDecimalTokenB.address],
|
||||
[erc20ZeroDecimalTokenA.address, erc20ZeroDecimalTokenB.address],
|
||||
erc721Token,
|
||||
erc721Balances,
|
||||
exchangeContract.address,
|
||||
|
@ -21,6 +21,8 @@ const POINT_ONE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(100_000_000_000_000_000)
|
||||
const POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(50_000_000_000_000_000);
|
||||
const TEN_UNITS_FIVE_DECIMALS = new BigNumber(1_000_000);
|
||||
const FIVE_UNITS_FIVE_DECIMALS = new BigNumber(500_000);
|
||||
const TEN_UNITS_ZERO_DECIMALS = new BigNumber(10);
|
||||
const ONE_THOUSAND_UNITS_ZERO_DECIMALS = new BigNumber(1000);
|
||||
const ONE_NFT_UNIT = new BigNumber(1);
|
||||
|
||||
export class OrderFactoryFromScenario {
|
||||
@ -28,6 +30,7 @@ export class OrderFactoryFromScenario {
|
||||
private readonly _zrxAddress: string;
|
||||
private readonly _nonZrxERC20EighteenDecimalTokenAddresses: string[];
|
||||
private readonly _erc20FiveDecimalTokenAddresses: string[];
|
||||
private readonly _erc20ZeroDecimalTokenAddresses: string[];
|
||||
private readonly _erc721Token: DummyERC721TokenContract;
|
||||
private readonly _erc721Balances: ERC721TokenIdsByOwner;
|
||||
private readonly _exchangeAddress: string;
|
||||
@ -36,6 +39,7 @@ export class OrderFactoryFromScenario {
|
||||
zrxAddress: string,
|
||||
nonZrxERC20EighteenDecimalTokenAddresses: string[],
|
||||
erc20FiveDecimalTokenAddresses: string[],
|
||||
erc20ZeroDecimalTokenAddresses: string[],
|
||||
erc721Token: DummyERC721TokenContract,
|
||||
erc721Balances: ERC721TokenIdsByOwner,
|
||||
exchangeAddress: string,
|
||||
@ -44,6 +48,7 @@ export class OrderFactoryFromScenario {
|
||||
this._zrxAddress = zrxAddress;
|
||||
this._nonZrxERC20EighteenDecimalTokenAddresses = nonZrxERC20EighteenDecimalTokenAddresses;
|
||||
this._erc20FiveDecimalTokenAddresses = erc20FiveDecimalTokenAddresses;
|
||||
this._erc20ZeroDecimalTokenAddresses = erc20ZeroDecimalTokenAddresses;
|
||||
this._erc721Token = erc721Token;
|
||||
this._erc721Balances = erc721Balances;
|
||||
this._exchangeAddress = exchangeAddress;
|
||||
@ -89,6 +94,9 @@ export class OrderFactoryFromScenario {
|
||||
erc721MakerAssetIds[0],
|
||||
);
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
makerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[0]);
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
|
||||
}
|
||||
@ -109,6 +117,9 @@ export class OrderFactoryFromScenario {
|
||||
erc721TakerAssetIds[0],
|
||||
);
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
takerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[1]);
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
|
||||
}
|
||||
@ -126,6 +137,9 @@ export class OrderFactoryFromScenario {
|
||||
case AssetDataScenario.ERC721:
|
||||
makerAssetAmount = ONE_NFT_UNIT;
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
makerAssetAmount = ONE_THOUSAND_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
|
||||
}
|
||||
@ -142,6 +156,9 @@ export class OrderFactoryFromScenario {
|
||||
case AssetDataScenario.ERC721:
|
||||
makerAssetAmount = ONE_NFT_UNIT;
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
makerAssetAmount = TEN_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
|
||||
}
|
||||
@ -166,6 +183,9 @@ export class OrderFactoryFromScenario {
|
||||
case AssetDataScenario.ERC721:
|
||||
takerAssetAmount = ONE_NFT_UNIT;
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
takerAssetAmount = ONE_THOUSAND_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
|
||||
}
|
||||
@ -182,6 +202,9 @@ export class OrderFactoryFromScenario {
|
||||
case AssetDataScenario.ERC721:
|
||||
takerAssetAmount = ONE_NFT_UNIT;
|
||||
break;
|
||||
case AssetDataScenario.ERC20ZeroDecimals:
|
||||
takerAssetAmount = TEN_UNITS_ZERO_DECIMALS;
|
||||
break;
|
||||
default:
|
||||
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
|
||||
}
|
||||
|
@ -177,10 +177,11 @@ export enum ExpirationTimeSecondsScenario {
|
||||
}
|
||||
|
||||
export enum AssetDataScenario {
|
||||
ERC721 = 'ERC721',
|
||||
ERC20ZeroDecimals = 'ERC20_ZERO_DECIMALS',
|
||||
ZRXFeeToken = 'ZRX_FEE_TOKEN',
|
||||
ERC20FiveDecimals = 'ERC20_FIVE_DECIMALS',
|
||||
ERC20NonZRXEighteenDecimals = 'ERC20_NON_ZRX_EIGHTEEN_DECIMALS',
|
||||
ERC721 = 'ERC721',
|
||||
}
|
||||
|
||||
export enum TakerAssetFillAmountScenario {
|
||||
|
@ -35,14 +35,14 @@
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"chai": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"nyc": "^11.0.1",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/subproviders": "^1.0.5",
|
||||
|
@ -37,11 +37,11 @@
|
||||
"devDependencies": {
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^8.0.53",
|
||||
|
@ -33,12 +33,12 @@
|
||||
"@0xproject/sol-compiler": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/base-contract": "^2.0.0-rc.1",
|
||||
|
@ -60,7 +60,7 @@
|
||||
"@types/lodash.values": "^4.3.3",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"chai": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"lodash.foreach": "^4.5.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
@ -70,7 +70,7 @@
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -56,6 +56,6 @@
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
}
|
||||
}
|
||||
|
@ -44,12 +44,12 @@
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@0xproject/types": "^1.0.1-rc.4",
|
||||
"@types/yargs": "^10.0.0",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -40,7 +40,7 @@
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lerna/batch-packages": "^3.0.0-beta.18",
|
||||
|
@ -1,4 +1,22 @@
|
||||
[
|
||||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.1-rc.3",
|
||||
"changes": [
|
||||
|
@ -61,7 +61,7 @@
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
@ -70,7 +70,7 @@
|
||||
"sinon": "^4.0.0",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^1.0.5",
|
||||
|
@ -25,3 +25,5 @@ export { EIP712Utils } from './eip712_utils';
|
||||
export { OrderValidationUtils } from './order_validation_utils';
|
||||
export { ExchangeTransferSimulator } from './exchange_transfer_simulator';
|
||||
export { marketUtils } from './market_utils';
|
||||
export { rateUtils } from './rate_utils';
|
||||
export { sortingUtils } from './sorting_utils';
|
||||
|
@ -1,46 +1,51 @@
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { SignedOrder } from '@0xproject/types';
|
||||
import { Order } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { assert } from './assert';
|
||||
import { constants } from './constants';
|
||||
import { FindFeeOrdersThatCoverFeesForTargetOrdersOpts, FindOrdersThatCoverMakerAssetFillAmountOpts } from './types';
|
||||
|
||||
export const marketUtils = {
|
||||
/**
|
||||
* Takes an array of orders and returns a subset of those orders that has enough makerAssetAmount (taking into account on-chain balances,
|
||||
* allowances, and partial fills) in order to fill the input makerAssetFillAmount plus slippageBufferAmount. Iterates from first order to last.
|
||||
* 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 signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify the same makerAsset.
|
||||
* All orders should specify WETH as the takerAsset.
|
||||
* @param remainingFillableMakerAssetAmounts An array of BigNumbers corresponding to the signedOrders parameter.
|
||||
* You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups
|
||||
* for these values.
|
||||
* @param makerAssetFillAmount The amount of makerAsset desired to be filled.
|
||||
* @param slippageBufferAmount An additional amount of makerAsset to be covered by the result in case of trade collisions or partial fills.
|
||||
* @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(
|
||||
signedOrders: SignedOrder[],
|
||||
remainingFillableMakerAssetAmounts: BigNumber[],
|
||||
findOrdersThatCoverMakerAssetFillAmount<T extends Order>(
|
||||
orders: T[],
|
||||
makerAssetFillAmount: BigNumber,
|
||||
slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT,
|
||||
): { resultOrders: SignedOrder[]; remainingFillAmount: BigNumber } {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
opts?: FindOrdersThatCoverMakerAssetFillAmountOpts,
|
||||
): { resultOrders: T[]; remainingFillAmount: BigNumber } {
|
||||
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.isValidBaseUnitAmount('makerAssetFillAmount', makerAssetFillAmount);
|
||||
assert.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount);
|
||||
assert.assert(
|
||||
signedOrders.length === remainingFillableMakerAssetAmounts.length,
|
||||
'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length',
|
||||
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 signedOrders input from left to right until we have enough makerAsset to fill totalFillAmount
|
||||
// iterate through the orders input from left to right until we have enough makerAsset to fill totalFillAmount
|
||||
const result = _.reduce(
|
||||
signedOrders,
|
||||
orders,
|
||||
({ resultOrders, remainingFillAmount }, order, index) => {
|
||||
if (remainingFillAmount.lessThanOrEqualTo(constants.ZERO_AMOUNT)) {
|
||||
return { resultOrders, remainingFillAmount: constants.ZERO_AMOUNT };
|
||||
@ -59,55 +64,61 @@ export const marketUtils = {
|
||||
};
|
||||
}
|
||||
},
|
||||
{ resultOrders: [] as SignedOrder[], remainingFillAmount: totalFillAmount },
|
||||
{ resultOrders: [] as T[], remainingFillAmount: totalFillAmount },
|
||||
);
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Takes an array of orders and an array of feeOrders. Returns a subset of the feeOrders that has enough ZRX (taking into account
|
||||
* on-chain balances, allowances, and partial fills) in order to fill the takerFees required by signedOrders plus a
|
||||
* slippageBufferAmount. Iterates from first feeOrder to last. Sort the feeOrders by ascending rate in order to get the subset of
|
||||
* 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 signedOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as
|
||||
* the makerAsset and WETH as the takerAsset.
|
||||
* @param remainingFillableMakerAssetAmounts An array of BigNumbers corresponding to the signedOrders parameter.
|
||||
* You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups
|
||||
* for these values.
|
||||
* @param signedFeeOrders An array of objects that conform to the SignedOrder interface. All orders should specify ZRX as
|
||||
* the makerAsset and WETH as the takerAsset.
|
||||
* @param remainingFillableFeeAmounts An array of BigNumbers corresponding to the signedFeeOrders parameter.
|
||||
* You can use OrderStateUtils @0xproject/order-utils to perform blockchain lookups
|
||||
* for these values.
|
||||
* @param slippageBufferAmount An additional amount of fee to be covered by the result in case of trade collisions or partial fills.
|
||||
* @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(
|
||||
signedOrders: SignedOrder[],
|
||||
remainingFillableMakerAssetAmounts: BigNumber[],
|
||||
signedFeeOrders: SignedOrder[],
|
||||
remainingFillableFeeAmounts: BigNumber[],
|
||||
slippageBufferAmount: BigNumber = constants.ZERO_AMOUNT,
|
||||
): { resultOrders: SignedOrder[]; remainingFeeAmount: BigNumber } {
|
||||
assert.doesConformToSchema('signedOrders', signedOrders, schemas.signedOrdersSchema);
|
||||
findFeeOrdersThatCoverFeesForTargetOrders<T extends Order>(
|
||||
orders: T[],
|
||||
feeOrders: T[],
|
||||
opts?: FindFeeOrdersThatCoverFeesForTargetOrdersOpts,
|
||||
): { resultOrders: T[]; remainingFeeAmount: BigNumber } {
|
||||
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.doesConformToSchema('signedFeeOrders', signedFeeOrders, schemas.signedOrdersSchema);
|
||||
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.isValidBaseUnitAmount('slippageBufferAmount', slippageBufferAmount);
|
||||
assert.assert(
|
||||
signedOrders.length === remainingFillableMakerAssetAmounts.length,
|
||||
'Expected signedOrders.length to equal remainingFillableMakerAssetAmounts.length',
|
||||
feeOrders.length === remainingFillableFeeAmounts.length,
|
||||
'Expected feeOrders.length to equal opts.remainingFillableFeeAmounts.length',
|
||||
);
|
||||
assert.assert(
|
||||
signedOrders.length === remainingFillableMakerAssetAmounts.length,
|
||||
'Expected signedFeeOrders.length to equal remainingFillableFeeAmounts.length',
|
||||
);
|
||||
// calculate total amount of ZRX needed to fill signedOrders
|
||||
// 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(
|
||||
signedOrders,
|
||||
orders,
|
||||
(accFees, order, index) => {
|
||||
const makerAssetAmountAvailable = remainingFillableMakerAssetAmounts[index];
|
||||
const feeToFillMakerAssetAmountAvailable = makerAssetAmountAvailable
|
||||
@ -118,10 +129,12 @@ export const marketUtils = {
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
signedFeeOrders,
|
||||
remainingFillableFeeAmounts,
|
||||
feeOrders,
|
||||
totalFeeAmount,
|
||||
slippageBufferAmount,
|
||||
{
|
||||
remainingFillableMakerAssetAmounts: remainingFillableFeeAmounts,
|
||||
slippageBufferAmount,
|
||||
},
|
||||
);
|
||||
return {
|
||||
resultOrders,
|
||||
|
@ -11,6 +11,7 @@ import { BigNumber } from '@0xproject/utils';
|
||||
import { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';
|
||||
import { AbstractOrderFilledCancelledFetcher } from './abstract/abstract_order_filled_cancelled_fetcher';
|
||||
import { orderHashUtils } from './order_hash';
|
||||
import { OrderValidationUtils } from './order_validation_utils';
|
||||
import { RemainingFillableCalculator } from './remaining_fillable_calculator';
|
||||
import { utils } from './utils';
|
||||
|
||||
@ -22,9 +23,16 @@ interface SidedOrderRelevantState {
|
||||
traderFeeProxyAllowance: BigNumber;
|
||||
filledTakerAssetAmount: BigNumber;
|
||||
remainingFillableAssetAmount: BigNumber;
|
||||
isOrderCancelled: boolean;
|
||||
}
|
||||
|
||||
const ACCEPTABLE_RELATIVE_ROUNDING_ERROR = 0.0001;
|
||||
interface OrderValidResult {
|
||||
isValid: true;
|
||||
}
|
||||
interface OrderInvalidResult {
|
||||
isValid: false;
|
||||
error: ExchangeContractErrs;
|
||||
}
|
||||
type OrderValidationResult = OrderValidResult | OrderInvalidResult;
|
||||
|
||||
export class OrderStateUtils {
|
||||
private readonly _balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher;
|
||||
@ -32,64 +40,56 @@ export class OrderStateUtils {
|
||||
private static _validateIfOrderIsValid(
|
||||
signedOrder: SignedOrder,
|
||||
sidedOrderRelevantState: SidedOrderRelevantState,
|
||||
): void {
|
||||
): 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)) {
|
||||
throw new Error(ExchangeContractErrs.OrderRemainingFillAmountZero);
|
||||
return { isValid: false, error: ExchangeContractErrs.OrderRemainingFillAmountZero };
|
||||
}
|
||||
|
||||
if (sidedOrderRelevantState.traderBalance.eq(0)) {
|
||||
throw new Error(
|
||||
isMakerSide
|
||||
? ExchangeContractErrs.InsufficientMakerBalance
|
||||
: ExchangeContractErrs.InsufficientTakerBalance,
|
||||
);
|
||||
const error = isMakerSide
|
||||
? ExchangeContractErrs.InsufficientMakerBalance
|
||||
: ExchangeContractErrs.InsufficientTakerBalance;
|
||||
return { isValid: false, error };
|
||||
}
|
||||
if (sidedOrderRelevantState.traderProxyAllowance.eq(0)) {
|
||||
throw new Error(
|
||||
isMakerSide
|
||||
? ExchangeContractErrs.InsufficientMakerAllowance
|
||||
: ExchangeContractErrs.InsufficientTakerAllowance,
|
||||
);
|
||||
const error = isMakerSide
|
||||
? ExchangeContractErrs.InsufficientMakerAllowance
|
||||
: ExchangeContractErrs.InsufficientTakerAllowance;
|
||||
return { isValid: false, error };
|
||||
}
|
||||
if (!signedOrder.makerFee.eq(0)) {
|
||||
if (sidedOrderRelevantState.traderFeeBalance.eq(0)) {
|
||||
throw new Error(
|
||||
isMakerSide
|
||||
? ExchangeContractErrs.InsufficientMakerFeeBalance
|
||||
: ExchangeContractErrs.InsufficientTakerFeeBalance,
|
||||
);
|
||||
const error = isMakerSide
|
||||
? ExchangeContractErrs.InsufficientMakerFeeBalance
|
||||
: ExchangeContractErrs.InsufficientTakerFeeBalance;
|
||||
return { isValid: false, error };
|
||||
}
|
||||
if (sidedOrderRelevantState.traderFeeProxyAllowance.eq(0)) {
|
||||
throw new Error(
|
||||
isMakerSide
|
||||
? ExchangeContractErrs.InsufficientMakerFeeAllowance
|
||||
: ExchangeContractErrs.InsufficientTakerFeeAllowance,
|
||||
);
|
||||
const error = isMakerSide
|
||||
? ExchangeContractErrs.InsufficientMakerFeeAllowance
|
||||
: ExchangeContractErrs.InsufficientTakerFeeAllowance;
|
||||
return { isValid: false, error };
|
||||
}
|
||||
}
|
||||
|
||||
let minFillableTakerAssetAmountWithinNoRoundingErrorRange;
|
||||
if (isMakerSide) {
|
||||
minFillableTakerAssetAmountWithinNoRoundingErrorRange = signedOrder.takerAssetAmount
|
||||
.dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
|
||||
.dividedBy(signedOrder.makerAssetAmount);
|
||||
} else {
|
||||
minFillableTakerAssetAmountWithinNoRoundingErrorRange = signedOrder.makerAssetAmount
|
||||
.dividedBy(ACCEPTABLE_RELATIVE_ROUNDING_ERROR)
|
||||
.dividedBy(signedOrder.takerAssetAmount);
|
||||
}
|
||||
|
||||
if (
|
||||
sidedOrderRelevantState.remainingFillableAssetAmount.lessThan(
|
||||
minFillableTakerAssetAmountWithinNoRoundingErrorRange,
|
||||
)
|
||||
) {
|
||||
throw new Error(ExchangeContractErrs.OrderFillRoundingError);
|
||||
const remainingTakerAssetAmount = signedOrder.takerAssetAmount.minus(
|
||||
sidedOrderRelevantState.filledTakerAssetAmount,
|
||||
);
|
||||
const isRoundingError = OrderValidationUtils.isRoundingError(
|
||||
remainingTakerAssetAmount,
|
||||
signedOrder.takerAssetAmount,
|
||||
signedOrder.makerAssetAmount,
|
||||
);
|
||||
if (isRoundingError) {
|
||||
return { isValid: false, error: ExchangeContractErrs.OrderFillRoundingError };
|
||||
}
|
||||
return { isValid: true };
|
||||
}
|
||||
constructor(
|
||||
balanceAndProxyAllowanceFetcher: AbstractBalanceAndProxyAllowanceFetcher,
|
||||
@ -101,6 +101,7 @@ export class OrderStateUtils {
|
||||
public async getOpenOrderStateAsync(signedOrder: SignedOrder): Promise<OrderState> {
|
||||
const orderRelevantState = await this.getOpenOrderRelevantStateAsync(signedOrder);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
const isOrderCancelled = await this._orderFilledCancelledFetcher.isOrderCancelledAsync(orderHash);
|
||||
const sidedOrderRelevantState = {
|
||||
isMakerSide: true,
|
||||
traderBalance: orderRelevantState.makerBalance,
|
||||
@ -109,20 +110,21 @@ export class OrderStateUtils {
|
||||
traderFeeProxyAllowance: orderRelevantState.makerFeeProxyAllowance,
|
||||
filledTakerAssetAmount: orderRelevantState.filledTakerAssetAmount,
|
||||
remainingFillableAssetAmount: orderRelevantState.remainingFillableMakerAssetAmount,
|
||||
isOrderCancelled,
|
||||
};
|
||||
try {
|
||||
OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState);
|
||||
const orderValidationResult = OrderStateUtils._validateIfOrderIsValid(signedOrder, sidedOrderRelevantState);
|
||||
if (orderValidationResult.isValid) {
|
||||
const orderState: OrderStateValid = {
|
||||
isValid: true,
|
||||
orderHash,
|
||||
orderRelevantState,
|
||||
};
|
||||
return orderState;
|
||||
} catch (err) {
|
||||
} else {
|
||||
const orderState: OrderStateInvalid = {
|
||||
isValid: false,
|
||||
orderHash,
|
||||
error: err.message,
|
||||
error: orderValidationResult.error,
|
||||
};
|
||||
return orderState;
|
||||
}
|
||||
@ -278,6 +280,7 @@ export class OrderStateUtils {
|
||||
traderFeeProxyAllowance,
|
||||
filledTakerAssetAmount,
|
||||
remainingFillableAssetAmount,
|
||||
isOrderCancelled,
|
||||
};
|
||||
return sidedOrderRelevantState;
|
||||
}
|
||||
|
48
packages/order-utils/src/rate_utils.ts
Normal file
48
packages/order-utils/src/rate_utils.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { Order } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/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.mul(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.sub(feeOrder.takerFee);
|
||||
assert.assert(
|
||||
zrxAmountAfterFees.greaterThan(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;
|
||||
},
|
||||
};
|
54
packages/order-utils/src/sorting_utils.ts
Normal file
54
packages/order-utils/src/sorting_utils.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { schemas } from '@0xproject/json-schemas';
|
||||
import { Order } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/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<T extends Order>(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: Order[]): Order[] {
|
||||
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<T extends Order>(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;
|
||||
}
|
@ -41,3 +41,31 @@ export interface CreateOrderOpts {
|
||||
salt?: BigNumber;
|
||||
expirationTimeSeconds?: BigNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter.
|
||||
* You can use `OrderStateUtils` `@0xproject/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` `@0xproject/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 @0xproject/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;
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ describe('marketUtils', () => {
|
||||
it('returns empty and unchanged remainingFillAmount', async () => {
|
||||
const fillAmount = new BigNumber(10);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
[],
|
||||
[],
|
||||
fillAmount,
|
||||
);
|
||||
@ -34,8 +33,6 @@ describe('marketUtils', () => {
|
||||
},
|
||||
3,
|
||||
);
|
||||
// generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
|
||||
const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
|
||||
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
|
||||
@ -43,9 +40,10 @@ describe('marketUtils', () => {
|
||||
const slippageBufferAmount = new BigNumber(10);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
fillAmount,
|
||||
slippageBufferAmount,
|
||||
{
|
||||
slippageBufferAmount,
|
||||
},
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal(inputOrders);
|
||||
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
@ -57,9 +55,10 @@ describe('marketUtils', () => {
|
||||
const slippageBufferAmount = new BigNumber(10);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
fillAmount,
|
||||
slippageBufferAmount,
|
||||
{
|
||||
slippageBufferAmount,
|
||||
},
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal(inputOrders);
|
||||
expect(remainingFillAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
@ -71,9 +70,10 @@ describe('marketUtils', () => {
|
||||
const slippageBufferAmount = new BigNumber(5);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
fillAmount,
|
||||
slippageBufferAmount,
|
||||
{
|
||||
slippageBufferAmount,
|
||||
},
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal(inputOrders);
|
||||
expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(5));
|
||||
@ -83,7 +83,6 @@ describe('marketUtils', () => {
|
||||
const fillAmount = new BigNumber(10);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
fillAmount,
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal([inputOrders[0]]);
|
||||
@ -94,7 +93,6 @@ describe('marketUtils', () => {
|
||||
const fillAmount = new BigNumber(15);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
fillAmount,
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal([inputOrders[0], inputOrders[1]]);
|
||||
@ -120,8 +118,10 @@ describe('marketUtils', () => {
|
||||
const fillAmount = new BigNumber(30);
|
||||
const { resultOrders, remainingFillAmount } = marketUtils.findOrdersThatCoverMakerAssetFillAmount(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
fillAmount,
|
||||
{
|
||||
remainingFillableMakerAssetAmounts,
|
||||
},
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal([inputOrders[1], inputOrders[2]]);
|
||||
expect(remainingFillAmount).to.be.bignumber.equal(new BigNumber(15));
|
||||
@ -137,15 +137,11 @@ describe('marketUtils', () => {
|
||||
},
|
||||
3,
|
||||
);
|
||||
// generate remainingFillableFeeAmounts that equal the zrxAmount
|
||||
const remainingFillableFeeAmounts = [zrxAmount, zrxAmount, zrxAmount];
|
||||
describe('no target orders', () => {
|
||||
it('returns empty and zero remainingFeeAmount', async () => {
|
||||
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
||||
[],
|
||||
[],
|
||||
inputFeeOrders,
|
||||
remainingFillableFeeAmounts,
|
||||
);
|
||||
expect(resultOrders).to.be.empty;
|
||||
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
@ -168,9 +164,10 @@ describe('marketUtils', () => {
|
||||
it('returns empty and non-zero remainingFeeAmount', async () => {
|
||||
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
[],
|
||||
[],
|
||||
{
|
||||
remainingFillableMakerAssetAmounts,
|
||||
},
|
||||
);
|
||||
expect(resultOrders).to.be.empty;
|
||||
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
|
||||
@ -185,14 +182,10 @@ describe('marketUtils', () => {
|
||||
},
|
||||
3,
|
||||
);
|
||||
// generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
|
||||
const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
|
||||
it('returns empty and zero remainingFeeAmount', async () => {
|
||||
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
inputFeeOrders,
|
||||
remainingFillableFeeAmounts,
|
||||
);
|
||||
expect(resultOrders).to.be.empty;
|
||||
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
@ -210,14 +203,10 @@ describe('marketUtils', () => {
|
||||
},
|
||||
3,
|
||||
);
|
||||
// generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
|
||||
const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
|
||||
it('returns input fee orders and zero remainingFeeAmount', async () => {
|
||||
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
inputFeeOrders,
|
||||
remainingFillableFeeAmounts,
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal(inputFeeOrders);
|
||||
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
@ -243,9 +232,10 @@ describe('marketUtils', () => {
|
||||
it('returns first two input fee orders and zero remainingFeeAmount', async () => {
|
||||
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
inputFeeOrders,
|
||||
remainingFillableFeeAmounts,
|
||||
{
|
||||
remainingFillableMakerAssetAmounts,
|
||||
},
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal([inputFeeOrders[0], inputFeeOrders[1]]);
|
||||
expect(remainingFeeAmount).to.be.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
@ -263,14 +253,10 @@ describe('marketUtils', () => {
|
||||
},
|
||||
3,
|
||||
);
|
||||
// generate remainingFillableMakerAssetAmounts that equal the makerAssetAmount
|
||||
const remainingFillableMakerAssetAmounts = [makerAssetAmount, makerAssetAmount, makerAssetAmount];
|
||||
it('returns input fee orders and non-zero remainingFeeAmount', async () => {
|
||||
const { resultOrders, remainingFeeAmount } = marketUtils.findFeeOrdersThatCoverFeesForTargetOrders(
|
||||
inputOrders,
|
||||
remainingFillableMakerAssetAmounts,
|
||||
inputFeeOrders,
|
||||
remainingFillableFeeAmounts,
|
||||
);
|
||||
expect(resultOrders).to.be.deep.equal(inputFeeOrders);
|
||||
expect(remainingFeeAmount).to.be.bignumber.equal(new BigNumber(30));
|
||||
|
124
packages/order-utils/test/order_state_utils_test.ts
Normal file
124
packages/order-utils/test/order_state_utils_test.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import { BigNumber } from '@0xproject/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<BigNumber> {
|
||||
return takerBalance;
|
||||
},
|
||||
async getProxyAllowanceAsync(_assetData: string, _userAddress: string): Promise<BigNumber> {
|
||||
return takerBalance;
|
||||
},
|
||||
};
|
||||
return balanceFetcher;
|
||||
};
|
||||
const buildMockOrderFilledFetcher = (
|
||||
filledAmount: BigNumber = new BigNumber(0),
|
||||
cancelled: boolean = false,
|
||||
): AbstractOrderFilledCancelledFetcher => {
|
||||
const orderFetcher = {
|
||||
async getFilledTakerAmountAsync(_orderHash: string): Promise<BigNumber> {
|
||||
return filledAmount;
|
||||
},
|
||||
async isOrderCancelledAsync(_orderHash: string): Promise<boolean> {
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
55
packages/order-utils/test/rate_utils_test.ts
Normal file
55
packages/order-utils/test/rate_utils_test.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { BigNumber } from '@0xproject/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));
|
||||
});
|
||||
});
|
||||
});
|
67
packages/order-utils/test/sorting_utils_test.ts
Normal file
67
packages/order-utils/test/sorting_utils_test.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { BigNumber } from '@0xproject/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]);
|
||||
});
|
||||
});
|
||||
});
|
@ -55,7 +55,7 @@
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
@ -67,7 +67,7 @@
|
||||
"sinon": "^4.0.0",
|
||||
"source-map-support": "^0.5.0",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^1.0.5",
|
||||
|
@ -501,25 +501,27 @@ describe('OrderWatcher', () => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderCancelled);
|
||||
});
|
||||
orderWatcher.subscribe(callback);
|
||||
await contractWrappers.exchange.cancelOrderAsync(signedOrder);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateInvalid when within rounding error range', (done: DoneCallback) => {
|
||||
it('should emit orderStateInvalid when within rounding error range after a partial fill', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
const remainingFillableAmountInBaseUnits = new BigNumber(100);
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
const fillAmountInBaseUnits = new BigNumber(2);
|
||||
const makerAssetAmount = new BigNumber(1001);
|
||||
const takerAssetAmount = new BigNumber(3);
|
||||
signedOrder = await fillScenarios.createAsymmetricFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
makerAssetAmount,
|
||||
takerAssetAmount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
@ -527,11 +529,7 @@ describe('OrderWatcher', () => {
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.OrderFillRoundingError);
|
||||
});
|
||||
orderWatcher.subscribe(callback);
|
||||
await contractWrappers.exchange.fillOrderAsync(
|
||||
signedOrder,
|
||||
fillableAmount.minus(remainingFillableAmountInBaseUnits),
|
||||
takerAddress,
|
||||
);
|
||||
await contractWrappers.exchange.fillOrderAsync(signedOrder, fillAmountInBaseUnits, takerAddress);
|
||||
})().catch(done);
|
||||
});
|
||||
describe('erc721', () => {
|
||||
|
@ -34,7 +34,7 @@
|
||||
"@types/react-dom": "^16.0.3",
|
||||
"@types/react-tap-event-plugin": "0.0.30",
|
||||
"awesome-typescript-loader": "^3.1.3",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"css-loader": "^0.28.9",
|
||||
"json-loader": "^0.5.4",
|
||||
"less": "^2.7.2",
|
||||
@ -45,7 +45,7 @@
|
||||
"source-map-loader": "^0.2.3",
|
||||
"style-loader": "^0.20.2",
|
||||
"tslint": "^5.9.1",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"webpack": "^3.11.0",
|
||||
"webpack-dev-server": "^2.11.1"
|
||||
},
|
||||
|
@ -29,11 +29,11 @@
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"@types/compare-versions": "^3.0.0",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "^5.9.1",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/react-shared": "^1.0.6",
|
||||
|
@ -28,11 +28,11 @@
|
||||
"@0xproject/dev-utils": "^1.0.4",
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "^5.9.1",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/is-mobile": "0.3.0",
|
||||
|
@ -62,7 +62,7 @@
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.2",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
@ -72,7 +72,7 @@
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"types-bn": "^0.0.1",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"web3-typescript-typings": "^0.10.2",
|
||||
"zeppelin-solidity": "1.8.0"
|
||||
},
|
||||
|
@ -79,7 +79,7 @@
|
||||
"@types/rimraf": "^2.0.2",
|
||||
"@types/solidity-parser-antlr": "^0.2.1",
|
||||
"chai": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
@ -89,7 +89,7 @@
|
||||
"sinon": "^4.0.0",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -26,11 +26,11 @@
|
||||
"devDependencies": {
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/types": "^1.0.1-rc.4",
|
||||
|
@ -57,7 +57,7 @@
|
||||
"@types/yargs": "^10.0.0",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
@ -66,7 +66,7 @@
|
||||
"nyc": "^11.0.1",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -74,7 +74,7 @@
|
||||
"@types/sinon": "^2.2.2",
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
@ -84,7 +84,7 @@
|
||||
"sinon": "^4.0.0",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"webpack": "^3.1.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
@ -43,7 +43,7 @@
|
||||
"shx": "^0.2.2",
|
||||
"source-map-loader": "^0.1.6",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"webpack": "^3.1.0",
|
||||
"webpack-node-externals": "^1.6.0"
|
||||
}
|
||||
|
@ -36,10 +36,10 @@
|
||||
"devDependencies": {
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"@types/lodash": "4.14.104",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"shx": "^0.2.2",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.5",
|
||||
|
@ -26,11 +26,11 @@
|
||||
"devDependencies": {
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"@0xproject/tslint-config": "^1.0.5",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^8.0.53",
|
||||
|
@ -62,8 +62,7 @@ export interface ValidatorSignature {
|
||||
export enum ExchangeContractErrs {
|
||||
OrderFillExpired = 'ORDER_FILL_EXPIRED',
|
||||
OrderCancelExpired = 'ORDER_CANCEL_EXPIRED',
|
||||
OrderCancelAmountZero = 'ORDER_CANCEL_AMOUNT_ZERO',
|
||||
OrderAlreadyCancelledOrFilled = 'ORDER_ALREADY_CANCELLED_OR_FILLED',
|
||||
OrderCancelled = 'ORDER_CANCELLED',
|
||||
OrderFillAmountZero = 'ORDER_FILL_AMOUNT_ZERO',
|
||||
OrderRemainingFillAmountZero = 'ORDER_REMAINING_FILL_AMOUNT_ZERO',
|
||||
OrderFillRoundingError = 'ORDER_FILL_ROUNDING_ERROR',
|
||||
|
@ -33,7 +33,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0xproject/monorepo-scripts": "^1.0.5",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"shx": "^0.2.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@ -34,13 +34,13 @@
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"chai": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^4.1.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/types": "^1.0.1-rc.4",
|
||||
|
@ -51,7 +51,7 @@
|
||||
"chai": "^4.0.1",
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^2.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ganache-core": "0xProject/ganache-core#monorepo-dep",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
@ -61,7 +61,7 @@
|
||||
"shx": "^0.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"typedoc": "0xProject/typedoc",
|
||||
"typescript": "2.9.2"
|
||||
"typescript": "3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0xproject/assert": "^1.0.5",
|
||||
|
@ -84,7 +84,7 @@
|
||||
"@types/redux": "^3.6.0",
|
||||
"awesome-typescript-loader": "^3.1.3",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"copyfiles": "^1.2.0",
|
||||
"copyfiles": "^2.0.0",
|
||||
"css-loader": "0.23.x",
|
||||
"exports-loader": "0.6.x",
|
||||
"imports-loader": "0.6.x",
|
||||
@ -98,7 +98,7 @@
|
||||
"style-loader": "0.13.x",
|
||||
"tslint": "5.11.0",
|
||||
"tslint-config-0xproject": "^0.0.2",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.0.1",
|
||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||
"webpack": "^3.1.0",
|
||||
"webpack-dev-middleware": "^1.10.0",
|
||||
|
@ -247,12 +247,9 @@ export const utils = {
|
||||
} = {
|
||||
[ExchangeContractErrs.OrderFillExpired]: 'This order has expired',
|
||||
[ExchangeContractErrs.OrderCancelExpired]: 'This order has expired',
|
||||
[ExchangeContractErrs.OrderCancelAmountZero]: "Order cancel amount can't be 0",
|
||||
[ExchangeContractErrs.OrderAlreadyCancelledOrFilled]:
|
||||
'This order has already been completely filled or cancelled',
|
||||
[ExchangeContractErrs.OrderCancelled]: 'This order has been cancelled',
|
||||
[ExchangeContractErrs.OrderFillAmountZero]: "Order fill amount can't be 0",
|
||||
[ExchangeContractErrs.OrderRemainingFillAmountZero]:
|
||||
'This order has already been completely filled or cancelled',
|
||||
[ExchangeContractErrs.OrderRemainingFillAmountZero]: 'This order has already been completely filled',
|
||||
[ExchangeContractErrs.OrderFillRoundingError]:
|
||||
'Rounding error will occur when filling this order. Please try filling a different amount.',
|
||||
[ExchangeContractErrs.InsufficientTakerBalance]:
|
||||
|
102
yarn.lock
102
yarn.lock
@ -944,9 +944,9 @@
|
||||
"@types/express-serve-static-core" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/fetch-mock@^5.12.2":
|
||||
version "5.12.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-5.12.2.tgz#8c96517ff74303031c65c5da2d99858e34c844d2"
|
||||
"@types/fetch-mock@^6.0.3":
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-6.0.3.tgz#54ba90776293e728089bf53ba53e3c69f1c80655"
|
||||
|
||||
"@types/find-versions@^2.0.0":
|
||||
version "2.0.0"
|
||||
@ -1369,9 +1369,9 @@ aes-js@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d"
|
||||
|
||||
aes-js@^0.2.3:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d"
|
||||
aes-js@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072"
|
||||
|
||||
ajv-keywords@^2.1.0:
|
||||
version "2.1.1"
|
||||
@ -2429,10 +2429,6 @@ balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
|
||||
base-x@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-1.1.0.tgz#42d3d717474f9ea02207f6d1aa1f426913eeb7ac"
|
||||
|
||||
base-x@^3.0.2:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77"
|
||||
@ -2836,7 +2832,7 @@ browserslist@^2.1.2:
|
||||
caniuse-lite "^1.0.30000792"
|
||||
electron-to-chromium "^1.3.30"
|
||||
|
||||
bs58@=4.0.1:
|
||||
bs58@=4.0.1, bs58@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a"
|
||||
dependencies:
|
||||
@ -2846,18 +2842,13 @@ bs58@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d"
|
||||
|
||||
bs58@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bs58/-/bs58-3.1.0.tgz#d4c26388bf4804cac714141b1945aa47e5eb248e"
|
||||
bs58check@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc"
|
||||
dependencies:
|
||||
base-x "^1.1.0"
|
||||
|
||||
bs58check@^1.0.8:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-1.3.4.tgz#c52540073749117714fa042c3047eb8f9151cbf8"
|
||||
dependencies:
|
||||
bs58 "^3.1.0"
|
||||
bs58 "^4.0.0"
|
||||
create-hash "^1.1.0"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
btoa@1.1.2:
|
||||
version "1.1.2"
|
||||
@ -3766,18 +3757,7 @@ copy-webpack-plugin@^4.0.1:
|
||||
p-limit "^1.0.0"
|
||||
serialize-javascript "^1.4.0"
|
||||
|
||||
copyfiles@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-1.2.0.tgz#a8da3ac41aa2220ae29bd3c58b6984294f2c593c"
|
||||
dependencies:
|
||||
glob "^7.0.5"
|
||||
ltcdr "^2.2.1"
|
||||
minimatch "^3.0.3"
|
||||
mkdirp "^0.5.1"
|
||||
noms "0.0.0"
|
||||
through2 "^2.0.1"
|
||||
|
||||
copyfiles@^2.0.0:
|
||||
copyfiles@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.0.0.tgz#bbd78bb78e8fd6db5c67adf54249317b24560f2a"
|
||||
dependencies:
|
||||
@ -5209,7 +5189,7 @@ ethereumjs-util@5.1.5, ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumj
|
||||
safe-buffer "^5.1.1"
|
||||
secp256k1 "^3.0.1"
|
||||
|
||||
ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0:
|
||||
ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
|
||||
dependencies:
|
||||
@ -5263,21 +5243,23 @@ ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4:
|
||||
rustbn.js "~0.1.1"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
ethereumjs-wallet@0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb"
|
||||
ethereumjs-wallet@~0.6.0:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz#67244b6af3e8113b53d709124b25477b64aeccda"
|
||||
dependencies:
|
||||
aes-js "^0.2.3"
|
||||
bs58check "^1.0.8"
|
||||
ethereumjs-util "^4.4.0"
|
||||
hdkey "^0.7.0"
|
||||
aes-js "^3.1.1"
|
||||
bs58check "^2.1.2"
|
||||
ethereumjs-util "^5.2.0"
|
||||
hdkey "^1.0.0"
|
||||
safe-buffer "^5.1.2"
|
||||
scrypt.js "^0.2.0"
|
||||
utf8 "^2.1.1"
|
||||
uuid "^2.0.1"
|
||||
utf8 "^3.0.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
ethers@3.0.22:
|
||||
version "3.0.22"
|
||||
resolved "https://registry.npmjs.org/ethers/-/ethers-3.0.22.tgz#7fab1ea16521705837aa43c15831877b2716b436"
|
||||
ethers@0xproject/ethers.js#eip-838-reasons, ethers@3.0.22:
|
||||
version "3.0.18"
|
||||
uid b91342bd200d142af0165d6befddf783c8ae8447
|
||||
resolved "https://codeload.github.com/0xproject/ethers.js/tar.gz/b91342bd200d142af0165d6befddf783c8ae8447"
|
||||
dependencies:
|
||||
aes-js "3.0.0"
|
||||
bn.js "^4.4.0"
|
||||
@ -6693,13 +6675,21 @@ hawk@~6.0.2:
|
||||
hoek "4.x.x"
|
||||
sntp "2.x.x"
|
||||
|
||||
hdkey@^0.7.0, hdkey@^0.7.1:
|
||||
hdkey@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632"
|
||||
dependencies:
|
||||
coinstring "^2.0.0"
|
||||
secp256k1 "^3.0.1"
|
||||
|
||||
hdkey@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.0.0.tgz#1d658dfe966aaa542c1d499586200b325e5c0cf4"
|
||||
dependencies:
|
||||
coinstring "^2.0.0"
|
||||
safe-buffer "^5.1.1"
|
||||
secp256k1 "^3.0.1"
|
||||
|
||||
he@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
@ -8559,10 +8549,6 @@ lru-cache@~2.2.1:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d"
|
||||
|
||||
ltcdr@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ltcdr/-/ltcdr-2.2.1.tgz#5ab87ad1d4c1dab8e8c08bbf037ee0c1902287cf"
|
||||
|
||||
ltgt@^2.1.2, ltgt@~2.2.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5"
|
||||
@ -13705,9 +13691,9 @@ typescript@2.7.1:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.1.tgz#bb3682c2c791ac90e7c6210b26478a8da085c359"
|
||||
|
||||
typescript@2.9.2:
|
||||
version "2.9.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
|
||||
typescript@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.0.1.tgz#43738f29585d3a87575520a4b93ab6026ef11fdb"
|
||||
|
||||
typewise-core@^1.2, typewise-core@^1.2.0:
|
||||
version "1.2.0"
|
||||
@ -14036,6 +14022,10 @@ utf8@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96"
|
||||
|
||||
utf8@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1"
|
||||
|
||||
util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
@ -14081,6 +14071,10 @@ uuid@^2.0.1:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
|
||||
|
||||
uuid@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||
|
||||
uvm@1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/uvm/-/uvm-1.7.0.tgz#685d3a149ec7118fb73a73dfdc158ab46b0f0634"
|
||||
|
Loading…
x
Reference in New Issue
Block a user