merge developmemnt

This commit is contained in:
Fabio Berger 2018-10-04 18:59:55 +01:00
commit 3991e66a58
154 changed files with 3675 additions and 1231 deletions

View File

@ -11,34 +11,26 @@ jobs:
steps:
- checkout
- run: echo 'export PATH=$HOME/CIRCLE_PROJECT_REPONAME/node_modules/.bin:$PATH' >> $BASH_ENV
- restore_cache:
name: Restore Yarn Package Cache
keys:
- yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
- yarn-packages-{{ .Branch }}
- yarn-packages-master
- yarn-packages-
- run:
name: install-yarn
command: sudo npm install --global yarn@1.9.4
- run:
name: yarn
command: yarn --frozen-lockfile install || yarn --frozen-lockfile install
- save_cache:
name: Save Yarn Package Cache
key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:
- node_modules/
- run: >
if [ -z "$(git diff --name-only development packages/website)" ]; then
yarn build --exclude website
else
yarn build
fi
- run: yarn build:ci:no_website
- save_cache:
key: repo-{{ .Environment.CIRCLE_SHA1 }}
paths:
- ~/repo
build-website:
docker:
- image: circleci/node:9
working_directory: ~/repo
steps:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: cd packages/website && yarn build
test-contracts-ganache:
docker:
- image: circleci/node:9
@ -177,8 +169,10 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn prettier:ci
- run: yarn lerna run lint
- run: yarn prettier:ci
- run: cd packages/0x.js && yarn build:umd:prod
- run: yarn bundlesize
submit-coverage:
docker:
- image: circleci/node:9
@ -244,6 +238,9 @@ workflows:
main:
jobs:
- build
- build-website:
requires:
- build
- test-contracts-ganache:
requires:
- build

View File

@ -25,6 +25,7 @@
"lerna": "lerna",
"build": "wsrun build $PKG --fast-exit -r --stages",
"build:no_website": "wsrun build $PKG --fast-exit -r --stages --exclude @0xproject/website",
"build:ci:no_website": "wsrun build:ci $PKG --fast-exit -r --stages --exclude @0xproject/website",
"build:monorepo_scripts": "PKG=@0xproject/monorepo-scripts yarn build",
"build:ts": "tsc -b",
"watch:ts": "tsc -b -w",
@ -35,15 +36,25 @@
"test": "wsrun test $PKG --fast-exit --serial --exclude-missing",
"generate_doc": "node ./packages/monorepo-scripts/lib/doc_generate_and_upload.js",
"test:generate_docs:circleci": "for i in ${npm_package_config_packagesWithDocPages}; do yarn generate_doc --package $i --shouldUpload false --isStaging true || break -1; done;",
"bundlesize": "bundlesize",
"lint": "wsrun lint $PKG --fast-exit --parallel --exclude-missing"
},
"config": {
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic",
"packagesWithDocPages": "0x.js connect json-schemas subproviders web3-wrapper contract-wrappers order-utils order-watcher sol-compiler sol-cov ethereum-types"
},
"bundlesize": [
{
"path": "packages/0x.js/_bundles/index.min.js"
},
{
"path": "packages/instant/public/main.bundle.js"
}
],
"devDependencies": {
"@0x-lerna-fork/lerna": "3.0.0-beta.25",
"async-child-process": "^1.1.1",
"bundlesize": "^0.17.0",
"coveralls": "^3.0.0",
"ganache-cli": "6.1.3",
"lcov-result-merger": "^3.0.0",

View File

@ -4,7 +4,6 @@ webpack.config.js
yarn-error.log
test/
/src/
/_bundles/
/contract_templates/
/generated_docs/
/scripts/

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.8",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.7",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.8 - _October 2, 2018_
* Dependencies updated
## v1.0.7 - _September 28, 2018_
* Dependencies updated

View File

@ -16,6 +16,7 @@
"types": "lib/index.d.ts",
"scripts": {
"build": "yarn build:all",
"build:ci": "yarn build:commonjs",
"build:all": "run-p build:umd:prod build:commonjs",
"lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
"test:circleci": "run-s test:coverage",
@ -51,13 +52,12 @@
"@types/node": "*",
"@types/sinon": "^2.2.2",
"@types/web3-provider-engine": "^14.0.0",
"awesome-typescript-loader": "^3.1.3",
"awesome-typescript-loader": "^5.2.1",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
"copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"json-loader": "^0.5.4",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",
@ -69,8 +69,8 @@
"tslint": "5.11.0",
"typedoc": "0.12.0",
"typescript": "3.0.1",
"uglifyjs-webpack-plugin": "^1.3.0",
"webpack": "^3.1.0"
"uglifyjs-webpack-plugin": "^2.0.1",
"webpack": "^4.20.2"
},
"dependencies": {
"@0xproject/assert": "^1.0.12",

View File

@ -2,8 +2,7 @@
* This is to generate the umd bundle only
*/
const _ = require('lodash');
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const path = require('path');
const production = process.env.NODE_ENV === 'production';
@ -16,6 +15,7 @@ if (production) {
module.exports = {
entry,
mode: 'production',
output: {
path: path.resolve(__dirname, '_bundles'),
filename: '[name].js',
@ -27,19 +27,18 @@ module.exports = {
extensions: ['.ts', '.js', '.json'],
},
devtool: 'source-map',
plugins: [
// TODO: Revert to webpack bundled version with webpack v4.
// The v3 series bundled version does not support ES6 and
// fails to build.
new UglifyJsPlugin({
sourceMap: true,
uglifyOptions: {
mangle: {
reserved: ['BigNumber'],
optimization: {
minimizer: [
new TerserPlugin({
sourceMap: true,
terserOptions: {
mangle: {
reserved: ['BigNumber'],
},
},
},
}),
],
}),
],
},
module: {
rules: [
{
@ -59,10 +58,6 @@ module.exports = {
],
exclude: /node_modules/,
},
{
test: /\.json$/,
loader: 'json-loader',
},
],
},
};

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.13",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.12",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.13 - _October 2, 2018_
* Dependencies updated
## v1.0.12 - _September 28, 2018_
* Dependencies updated

View File

@ -11,6 +11,7 @@
"lint": "tslint --project .",
"clean": "shx rm -rf lib",
"build": "tsc -b",
"build:ci": "yarn build",
"test": "yarn run_mocha",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit",
"test:circleci": "yarn test:coverage",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.13",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.12",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.13 - _October 2, 2018_
* Dependencies updated
## v1.0.12 - _September 28, 2018_
* Dependencies updated

View File

@ -9,6 +9,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build": "tsc -b",
"build:ci": "yarn build",
"clean": "shx rm -rf lib test_temp",
"lint": "tslint --project .",
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",

View File

@ -1,4 +1,22 @@
[
{
"version": "2.0.0",
"changes": [
{
"note": "Expand AssetBuyer to work with multiple assets at once",
"pr": 1086
}
]
},
{
"timestamp": 1538475601,
"version": "1.0.3",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.2",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.3 - _October 2, 2018_
* Dependencies updated
## v1.0.2 - _September 28, 2018_
* Dependencies updated

View File

@ -1,6 +1,8 @@
## @0xproject/asset-buyer
Convenience package for buying assets represented on the Ethereum blockchain using 0x. In its simplest form, the package helps in the usage of the [0x forwarder contract](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md), which allows users to execute [Wrapped Ether](https://weth.io/) based 0x orders without having to set allowances, wrap Ether or buy ZRX, meaning they can buy tokens with Ether alone. Given some liquidity (0x signed orders), it helps estimate the Ether cost of buying a certain asset (giving a range) and then buying that asset.
**Warning: In Beta, has not been extensively tested.**
Convenience package for buying assets represented on the Ethereum blockchain using 0x. In its simplest form, the package helps in the usage of the [0x forwarder contract](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md), which allows users to execute [Wrapped Ether](https://weth.io/) based 0x orders without having to set allowances, wrap Ether or own ZRX, meaning they can buy tokens with Ether alone. Given some liquidity (0x signed orders), it helps estimate the Ether cost of buying a certain asset (giving a range) and then buying that asset.
In its more advanced and useful form, it integrates with the [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) and takes care of sourcing liquidity for you given an SRA compliant endpoint. The final result is a library that tells you what assets are available, provides an Ether based quote for any asset desired, and allows you to buy that asset using Ether alone.

View File

@ -4,7 +4,7 @@
"engines": {
"node": ">=6.12"
},
"description": "Convenience package for buying assets",
"description": "Convenience package for discovering and buying assets with Ether.",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
@ -18,6 +18,7 @@
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --exit",
"clean": "shx rm -rf lib test_temp scripts",
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"build:ci": "yarn build",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"config": {

View File

@ -1,6 +1,7 @@
import { ContractWrappers } from '@0xproject/contract-wrappers';
import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/order-utils';
import { ObjectMap } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
@ -11,11 +12,13 @@ import { BasicOrderProvider } from './order_providers/basic_order_provider';
import { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
import {
AssetBuyerError,
AssetBuyerOrdersAndFillableAmounts,
AssetBuyerOpts,
BuyQuote,
BuyQuoteExecutionOpts,
BuyQuoteRequestOpts,
OrderProvider,
OrderProviderResponse,
OrdersAndFillableAmounts,
} from './types';
import { assert } from './utils/assert';
@ -23,24 +26,26 @@ import { assetDataUtils } from './utils/asset_data_utils';
import { buyQuoteCalculator } from './utils/buy_quote_calculator';
import { orderProviderResponseProcessor } from './utils/order_provider_response_processor';
interface OrdersEntry {
ordersAndFillableAmounts: OrdersAndFillableAmounts;
lastRefreshTime: number;
}
export class AssetBuyer {
public readonly provider: Provider;
public readonly assetData: string;
public readonly orderProvider: OrderProvider;
public readonly networkId: number;
public readonly orderRefreshIntervalMs: number;
public readonly expiryBufferSeconds: number;
private readonly _contractWrappers: ContractWrappers;
private _lastRefreshTimeIfExists?: number;
private _currentOrdersAndFillableAmountsIfExists?: AssetBuyerOrdersAndFillableAmounts;
// cache of orders along with the time last updated keyed by assetData
private readonly _ordersEntryMap: ObjectMap<OrdersEntry> = {};
/**
* Instantiates a new AssetBuyer instance given existing liquidity in the form of orders and feeOrders.
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param orders A non-empty array of objects that conform to SignedOrder. All orders must have the same makerAssetData and takerAssetData (WETH).
* @param feeOrders A array of objects that conform to SignedOrder. All orders must have the same makerAssetData (ZRX) and takerAssetData (WETH). Defaults to an empty array.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
* @param options Initialization options for the AssetBuyer. See type definition for details.
*
* @return An instance of AssetBuyer
*/
@ -48,191 +53,137 @@ export class AssetBuyer {
provider: Provider,
orders: SignedOrder[],
feeOrders: SignedOrder[] = [],
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
options: Partial<AssetBuyerOpts> = {},
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
assert.doesConformToSchema('feeOrders', feeOrders, schemas.signedOrdersSchema);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
assert.areValidProvidedOrders('orders', orders);
assert.areValidProvidedOrders('feeOrders', feeOrders);
assert.assert(orders.length !== 0, `Expected orders to contain at least one order`);
const assetData = orders[0].makerAssetData;
const orderProvider = new BasicOrderProvider(_.concat(orders, feeOrders));
const assetBuyer = new AssetBuyer(
provider,
assetData,
orderProvider,
networkId,
orderRefreshIntervalMs,
expiryBufferSeconds,
);
const assetBuyer = new AssetBuyer(provider, orderProvider, options);
return assetBuyer;
}
/**
* Instantiates a new AssetBuyer instance given the desired assetData and a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) endpoint
* Instantiates a new AssetBuyer instance given a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) endpoint
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param assetData The assetData that identifies the desired asset to buy.
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
* @param options Initialization options for the AssetBuyer. See type definition for details.
*
* @return An instance of AssetBuyer
*/
public static getAssetBuyerForAssetData(
public static getAssetBuyerForStandardRelayerAPIUrl(
provider: Provider,
assetData: string,
sraApiUrl: string,
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
options: Partial<AssetBuyerOpts> = {},
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.isHexString('assetData', assetData);
assert.isWebUri('sraApiUrl', sraApiUrl);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
const orderProvider = new StandardRelayerAPIOrderProvider(sraApiUrl);
const assetBuyer = new AssetBuyer(
provider,
assetData,
orderProvider,
networkId,
orderRefreshIntervalMs,
expiryBufferSeconds,
);
return assetBuyer;
}
/**
* Instantiates a new AssetBuyer instance given the desired ERC20 token address and a [Standard Relayer API](https://github.com/0xProject/standard-relayer-api) endpoint
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param tokenAddress The ERC20 token address that identifies the desired asset to buy.
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
* @return An instance of AssetBuyer
*/
public static getAssetBuyerForERC20TokenAddress(
provider: Provider,
tokenAddress: string,
sraApiUrl: string,
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isWebUri('sraApiUrl', sraApiUrl);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
const assetBuyer = AssetBuyer.getAssetBuyerForAssetData(
provider,
assetData,
sraApiUrl,
networkId,
orderRefreshIntervalMs,
expiryBufferSeconds,
);
const assetBuyer = new AssetBuyer(provider, orderProvider, options);
return assetBuyer;
}
/**
* Instantiates a new AssetBuyer instance
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* @param orderProvider An object that conforms to OrderProvider, see type for definition.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param orderProvider An object that conforms to OrderProvider, see type for definition.
* @param options Initialization options for the AssetBuyer. See type definition for details.
*
* @return An instance of AssetBuyer
*/
constructor(
provider: Provider,
assetData: string,
orderProvider: OrderProvider,
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
) {
constructor(provider: Provider, orderProvider: OrderProvider, options: Partial<AssetBuyerOpts> = {}) {
const { networkId, orderRefreshIntervalMs, expiryBufferSeconds } = {
...constants.DEFAULT_ASSET_BUYER_OPTS,
...options,
};
assert.isWeb3Provider('provider', provider);
assert.isString('assetData', assetData);
assert.isValidOrderProvider('orderProvider', orderProvider);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
assert.isNumber('expiryBufferSeconds', expiryBufferSeconds);
this.provider = provider;
this.assetData = assetData;
this.orderProvider = orderProvider;
this.networkId = networkId;
this.expiryBufferSeconds = expiryBufferSeconds;
this.orderRefreshIntervalMs = orderRefreshIntervalMs;
this.expiryBufferSeconds = expiryBufferSeconds;
this._contractWrappers = new ContractWrappers(this.provider, {
networkId,
});
}
/**
* Get a `BuyQuote` containing all information relevant to fulfilling a buy.
* Get a `BuyQuote` containing all information relevant to fulfilling a buy given a desired assetData.
* You can then pass the `BuyQuote` to `executeBuyQuoteAsync` to execute the buy.
* @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* @param assetBuyAmount The amount of asset to buy.
* @param feePercentage The affiliate fee percentage. Defaults to 0.
* @param forceOrderRefresh If set to true, new orders and state will be fetched instead of waiting for
* the next orderRefreshIntervalMs. Defaults to false.
* @param options Options for the request. See type definition for more information.
*
* @return An object that conforms to BuyQuote that satisfies the request. See type definition for more information.
*/
public async getBuyQuoteAsync(assetBuyAmount: BigNumber, options: Partial<BuyQuoteRequestOpts>): Promise<BuyQuote> {
public async getBuyQuoteAsync(
assetData: string,
assetBuyAmount: BigNumber,
options: Partial<BuyQuoteRequestOpts>,
): Promise<BuyQuote> {
const { feePercentage, shouldForceOrderRefresh, slippagePercentage } = {
...options,
...constants.DEFAULT_BUY_QUOTE_REQUEST_OPTS,
...options,
};
assert.isString('assetData', assetData);
assert.isBigNumber('assetBuyAmount', assetBuyAmount);
assert.isValidPercentage('feePercentage', feePercentage);
assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh);
// we should refresh if:
// we do not have any orders OR
// we are forced to OR
// we have some last refresh time AND that time was sufficiently long ago
const shouldRefresh =
_.isUndefined(this._currentOrdersAndFillableAmountsIfExists) ||
shouldForceOrderRefresh ||
(!_.isUndefined(this._lastRefreshTimeIfExists) &&
this._lastRefreshTimeIfExists + this.orderRefreshIntervalMs < Date.now());
let ordersAndFillableAmounts: AssetBuyerOrdersAndFillableAmounts;
if (shouldRefresh) {
ordersAndFillableAmounts = await this._getLatestOrdersAndFillableAmountsAsync();
this._lastRefreshTimeIfExists = Date.now();
this._currentOrdersAndFillableAmountsIfExists = ordersAndFillableAmounts;
} else {
// it is safe to cast to AssetBuyerOrdersAndFillableAmounts because shouldRefresh catches the undefined case above
ordersAndFillableAmounts = this
._currentOrdersAndFillableAmountsIfExists as AssetBuyerOrdersAndFillableAmounts;
assert.isNumber('slippagePercentage', slippagePercentage);
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
const [ordersAndFillableAmounts, feeOrdersAndFillableAmounts] = await Promise.all([
this._getOrdersAndFillableAmountsAsync(assetData, shouldForceOrderRefresh),
this._getOrdersAndFillableAmountsAsync(zrxTokenAssetData, shouldForceOrderRefresh),
shouldForceOrderRefresh,
]);
if (ordersAndFillableAmounts.orders.length === 0) {
throw new Error(`${AssetBuyerError.AssetUnavailable}: For assetData ${assetData}`);
}
const buyQuote = buyQuoteCalculator.calculate(
ordersAndFillableAmounts,
feeOrdersAndFillableAmounts,
assetBuyAmount,
feePercentage,
slippagePercentage,
);
return buyQuote;
}
/**
* Get a `BuyQuote` containing all information relevant to fulfilling a buy given a desired ERC20 token address.
* You can then pass the `BuyQuote` to `executeBuyQuoteAsync` to execute the buy.
* @param tokenAddress The ERC20 token address.
* @param assetBuyAmount The amount of asset to buy.
* @param options Options for the request. See type definition for more information.
*
* @return An object that conforms to BuyQuote that satisfies the request. See type definition for more information.
*/
public async getBuyQuoteForERC20TokenAddressAsync(
tokenAddress: string,
assetBuyAmount: BigNumber,
options: Partial<BuyQuoteRequestOpts>,
): Promise<BuyQuote> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isBigNumber('assetBuyAmount', assetBuyAmount);
const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
const buyQuote = this.getBuyQuoteAsync(assetData, assetBuyAmount, options);
return buyQuote;
}
/**
* Given a BuyQuote and desired rate, attempt to execute the buy.
* @param buyQuote An object that conforms to BuyQuote. See type definition for more information.
* @param rate The desired rate to execute the buy at. Affects the amount of ETH sent with the transaction, defaults to buyQuote.maxRate.
* @param takerAddress The address to perform the buy. Defaults to the first available address from the provider.
* @param feeRecipient The address where affiliate fees are sent. Defaults to null address (0x000...000).
* @param options Options for the execution of the BuyQuote. See type definition for more information.
*
* @return A promise of the txHash.
*/
public async executeBuyQuoteAsync(
buyQuote: BuyQuote,
rate?: BigNumber,
takerAddress?: string,
feeRecipient: string = constants.NULL_ADDRESS,
): Promise<string> {
public async executeBuyQuoteAsync(buyQuote: BuyQuote, options: Partial<BuyQuoteExecutionOpts>): Promise<string> {
const { rate, takerAddress, feeRecipient } = {
...constants.DEFAULT_BUY_QUOTE_EXECUTION_OPTS,
...options,
};
assert.isValidBuyQuote('buyQuote', buyQuote);
if (!_.isUndefined(rate)) {
assert.isBigNumber('rate', rate);
@ -272,39 +223,55 @@ export class AssetBuyer {
return txHash;
}
/**
* Ask the order Provider for orders and process them.
* Grab orders from the map, if there is a miss or it is time to refresh, fetch and process the orders
*/
private async _getLatestOrdersAndFillableAmountsAsync(): Promise<AssetBuyerOrdersAndFillableAmounts> {
private async _getOrdersAndFillableAmountsAsync(
assetData: string,
shouldForceOrderRefresh: boolean,
): Promise<OrdersAndFillableAmounts> {
// try to get ordersEntry from the map
const ordersEntryIfExists = this._ordersEntryMap[assetData];
// we should refresh if:
// we do not have any orders OR
// we are forced to OR
// we have some last refresh time AND that time was sufficiently long ago
const shouldRefresh =
_.isUndefined(ordersEntryIfExists) ||
shouldForceOrderRefresh ||
// tslint:disable:restrict-plus-operands
ordersEntryIfExists.lastRefreshTime + this.orderRefreshIntervalMs < Date.now();
if (!shouldRefresh) {
const result = ordersEntryIfExists.ordersAndFillableAmounts;
return result;
}
const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow();
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
// construct order Provider requests
const targetOrderProviderRequest = {
makerAssetData: this.assetData,
// construct orderProvider request
const orderProviderRequest = {
makerAssetData: assetData,
takerAssetData: etherTokenAssetData,
networkId: this.networkId,
};
const feeOrderProviderRequest = {
makerAssetData: zrxTokenAssetData,
takerAssetData: etherTokenAssetData,
networkId: this.networkId,
};
const requests = [targetOrderProviderRequest, feeOrderProviderRequest];
// fetch orders and possible fillable amounts
const [targetOrderProviderResponse, feeOrderProviderResponse] = await Promise.all(
_.map(requests, async request => this.orderProvider.getOrdersAsync(request)),
);
const request = orderProviderRequest;
// get provider response
const response = await this.orderProvider.getOrdersAsync(request);
// since the order provider is an injected dependency, validate that it respects the API
// ie. it should only return maker/taker assetDatas that are specified
orderProviderResponseProcessor.throwIfInvalidResponse(targetOrderProviderResponse, targetOrderProviderRequest);
orderProviderResponseProcessor.throwIfInvalidResponse(feeOrderProviderResponse, feeOrderProviderRequest);
orderProviderResponseProcessor.throwIfInvalidResponse(response, request);
// process the responses into one object
const isMakerAssetZrxToken = assetData === zrxTokenAssetData;
const ordersAndFillableAmounts = await orderProviderResponseProcessor.processAsync(
targetOrderProviderResponse,
feeOrderProviderResponse,
zrxTokenAssetData,
response,
isMakerAssetZrxToken,
this.expiryBufferSeconds,
this._contractWrappers.orderValidator,
);
const lastRefreshTime = Date.now();
const updatedOrdersEntry = {
ordersAndFillableAmounts,
lastRefreshTime,
};
this._ordersEntryMap[assetData] = updatedOrdersEntry;
return ordersAndFillableAmounts;
}
/**

View File

@ -1,6 +1,15 @@
import { BigNumber } from '@0xproject/utils';
import { BuyQuoteRequestOpts } from './types';
import { AssetBuyerOpts, BuyQuoteExecutionOpts, BuyQuoteRequestOpts } from './types';
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
const MAINNET_NETWORK_ID = 1;
const DEFAULT_ASSET_BUYER_OPTS: AssetBuyerOpts = {
networkId: MAINNET_NETWORK_ID,
orderRefreshIntervalMs: 10000, // 10 seconds
expiryBufferSeconds: 15,
};
const DEFAULT_BUY_QUOTE_REQUEST_OPTS: BuyQuoteRequestOpts = {
feePercentage: 0,
@ -8,13 +17,18 @@ const DEFAULT_BUY_QUOTE_REQUEST_OPTS: BuyQuoteRequestOpts = {
slippagePercentage: 0.2, // 20% slippage protection
};
// Other default values are dynamically determined
const DEFAULT_BUY_QUOTE_EXECUTION_OPTS: BuyQuoteExecutionOpts = {
feeRecipient: NULL_ADDRESS,
};
export const constants = {
ZERO_AMOUNT: new BigNumber(0),
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
MAINNET_NETWORK_ID: 1,
DEFAULT_ORDER_REFRESH_INTERVAL_MS: 10000, // 10 seconds
NULL_ADDRESS,
MAINNET_NETWORK_ID,
ETHER_TOKEN_DECIMALS: 18,
DEFAULT_ASSET_BUYER_OPTS,
DEFAULT_BUY_QUOTE_EXECUTION_OPTS,
DEFAULT_BUY_QUOTE_REQUEST_OPTS,
MAX_PER_PAGE: 10000,
DEFAULT_EXPIRY_BUFFER_SECONDS: 15,
};

View File

@ -5,13 +5,14 @@ export { BigNumber } from '@0xproject/utils';
export { AssetBuyer } from './asset_buyer';
export { BasicOrderProvider } from './order_providers/basic_order_provider';
export { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
export { StandardRelayerAPIAssetBuyerManager } from './standard_relayer_api_asset_buyer_manager';
export {
AssetBuyerError,
AssetBuyerOpts,
BuyQuote,
BuyQuoteExecutionOpts,
BuyQuoteRequestOpts,
OrderProvider,
OrderProviderRequest,
OrderProviderResponse,
SignedOrderWithRemainingFillableMakerAssetAmount,
StandardRelayerApiAssetBuyerManagerError,
} from './types';

View File

@ -1,133 +0,0 @@
import { HttpClient } from '@0xproject/connect';
import { ContractWrappers } from '@0xproject/contract-wrappers';
import { ObjectMap } from '@0xproject/types';
import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
import { AssetBuyer } from './asset_buyer';
import { constants } from './constants';
import { assert } from './utils/assert';
import { assetDataUtils } from './utils/asset_data_utils';
import { OrderProvider, StandardRelayerApiAssetBuyerManagerError } from './types';
export class StandardRelayerAPIAssetBuyerManager {
// Map of assetData to AssetBuyer for that assetData
private readonly _assetBuyerMap: ObjectMap<AssetBuyer>;
/**
* Returns an array of all assetDatas available at the provided sraApiUrl
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
* @param pairedWithAssetData Optional filter argument to return assetDatas that only pair with this assetData value.
*
* @return An array of all assetDatas available at the provider sraApiUrl
*/
public static async getAllAvailableAssetDatasAsync(
sraApiUrl: string,
pairedWithAssetData?: string,
): Promise<string[]> {
const client = new HttpClient(sraApiUrl);
const params = {
assetDataA: pairedWithAssetData,
perPage: constants.MAX_PER_PAGE,
};
const assetPairsResponse = await client.getAssetPairsAsync(params);
return _.uniq(_.map(assetPairsResponse.records, pairsItem => pairsItem.assetDataB.assetData));
}
/**
* Instantiates a new StandardRelayerAPIAssetBuyerManager instance with all available assetDatas at the provided sraApiUrl
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
* @param orderProvider An object that conforms to OrderProvider, see type for definition.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states.
* Defaults to 10000ms (10s).
* @return An promise of an instance of StandardRelayerAPIAssetBuyerManager
*/
public static async getAssetBuyerManagerWithAllAvailableAssetDatasAsync(
provider: Provider,
sraApiUrl: string,
orderProvider: OrderProvider,
networkId: number = constants.MAINNET_NETWORK_ID,
orderRefreshIntervalMs?: number,
): Promise<StandardRelayerAPIAssetBuyerManager> {
const contractWrappers = new ContractWrappers(provider, { networkId });
const etherTokenAssetData = assetDataUtils.getEtherTokenAssetDataOrThrow(contractWrappers);
const assetDatas = await StandardRelayerAPIAssetBuyerManager.getAllAvailableAssetDatasAsync(
sraApiUrl,
etherTokenAssetData,
);
return new StandardRelayerAPIAssetBuyerManager(
provider,
assetDatas,
orderProvider,
networkId,
orderRefreshIntervalMs,
);
}
/**
* Instantiates a new StandardRelayerAPIAssetBuyerManager instance
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param assetDatas The assetDatas of the desired assets to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
* @param orderProvider An object that conforms to OrderProvider, see type for definition.
* @param networkId The ethereum network id. Defaults to 1 (mainnet).
* @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states.
* Defaults to 10000ms (10s).
* @return An instance of StandardRelayerAPIAssetBuyerManager
*/
constructor(
provider: Provider,
assetDatas: string[],
orderProvider: OrderProvider,
networkId?: number,
orderRefreshIntervalMs?: number,
) {
assert.assert(assetDatas.length > 0, `Expected 'assetDatas' to be a non-empty array.`);
this._assetBuyerMap = _.reduce(
assetDatas,
(accAssetBuyerMap: ObjectMap<AssetBuyer>, assetData: string) => {
accAssetBuyerMap[assetData] = new AssetBuyer(
provider,
assetData,
orderProvider,
networkId,
orderRefreshIntervalMs,
);
return accAssetBuyerMap;
},
{},
);
}
/**
* Get an AssetBuyer for the provided assetData
* @param assetData The desired assetData.
*
* @return An instance of AssetBuyer
*/
public getAssetBuyerFromAssetData(assetData: string): AssetBuyer {
const assetBuyer = this._assetBuyerMap[assetData];
if (_.isUndefined(assetBuyer)) {
throw new Error(
`${StandardRelayerApiAssetBuyerManagerError.AssetBuyerNotFound}: For assetData ${assetData}`,
);
}
return assetBuyer;
}
/**
* Get an AssetBuyer for the provided ERC20 tokenAddress
* @param tokenAddress The desired tokenAddress.
*
* @return An instance of AssetBuyer
*/
public getAssetBuyerFromERC20TokenAddress(tokenAddress: string): AssetBuyer {
const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
return this.getAssetBuyerFromAssetData(assetData);
}
/**
* Get a list of all the assetDatas that the instance supports
*
* @return An array of assetData strings
*/
public getAssetDatas(): string[] {
return _.keys(this._assetBuyerMap);
}
}

View File

@ -52,12 +52,39 @@ export interface BuyQuote {
feePercentage?: number;
}
/**
* feePercentage: The affiliate fee percentage. Defaults to 0.
* shouldForceOrderRefresh: If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs. Defaults to false.
* slippagePercentage: The percentage buffer to add to account for slippage. Affects max ETH price estimates. Defaults to 0.2 (20%).
*/
export interface BuyQuoteRequestOpts {
feePercentage: number;
shouldForceOrderRefresh: boolean;
slippagePercentage: number;
}
/**
* rate: The desired rate to execute the buy at. Affects the amount of ETH sent with the transaction, defaults to buyQuote.maxRate.
* takerAddress: The address to perform the buy. Defaults to the first available address from the provider.
* feeRecipient: The address where affiliate fees are sent. Defaults to null address (0x000...000).
*/
export interface BuyQuoteExecutionOpts {
rate?: BigNumber;
takerAddress?: string;
feeRecipient: string;
}
/**
* networkId: The ethereum network id. Defaults to 1 (mainnet).
* orderRefreshIntervalMs: The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
* expiryBufferSeconds: The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
*/
export interface AssetBuyerOpts {
networkId: number;
orderRefreshIntervalMs: number;
expiryBufferSeconds: number;
}
/**
* Possible errors thrown by an AssetBuyer instance or associated static methods.
*/
@ -69,18 +96,10 @@ export enum AssetBuyerError {
InsufficientZrxLiquidity = 'INSUFFICIENT_ZRX_LIQUIDITY',
NoAddressAvailable = 'NO_ADDRESS_AVAILABLE',
InvalidOrderProviderResponse = 'INVALID_ORDER_PROVIDER_RESPONSE',
AssetUnavailable = 'ASSET_UNAVAILABLE',
}
/**
* Possible errors thrown by an StandardRelayerApiAssetBuyerManager instance or associated static methods.
*/
export enum StandardRelayerApiAssetBuyerManagerError {
AssetBuyerNotFound = 'ASSET_BUYER_NOT_FOUND',
}
export interface AssetBuyerOrdersAndFillableAmounts {
export interface OrdersAndFillableAmounts {
orders: SignedOrder[];
feeOrders: SignedOrder[];
remainingFillableMakerAssetAmounts: BigNumber[];
remainingFillableFeeAmounts: BigNumber[];
}

View File

@ -3,24 +3,23 @@ import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { constants } from '../constants';
import { AssetBuyerError, AssetBuyerOrdersAndFillableAmounts, BuyQuote } from '../types';
import { AssetBuyerError, BuyQuote, OrdersAndFillableAmounts } from '../types';
import { orderUtils } from './order_utils';
// Calculates a buy quote for orders that have WETH as the takerAsset
export const buyQuoteCalculator = {
calculate(
ordersAndFillableAmounts: AssetBuyerOrdersAndFillableAmounts,
ordersAndFillableAmounts: OrdersAndFillableAmounts,
feeOrdersAndFillableAmounts: OrdersAndFillableAmounts,
assetBuyAmount: BigNumber,
feePercentage: number,
slippagePercentage: number,
): BuyQuote {
const {
orders,
feeOrders,
remainingFillableMakerAssetAmounts,
remainingFillableFeeAmounts,
} = ordersAndFillableAmounts;
const orders = ordersAndFillableAmounts.orders;
const remainingFillableMakerAssetAmounts = ordersAndFillableAmounts.remainingFillableMakerAssetAmounts;
const feeOrders = feeOrdersAndFillableAmounts.orders;
const remainingFillableFeeAmounts = feeOrdersAndFillableAmounts.remainingFillableMakerAssetAmounts;
const slippageBufferAmount = assetBuyAmount.mul(slippagePercentage).round();
const {
resultOrders,

View File

@ -8,19 +8,14 @@ import * as _ from 'lodash';
import { constants } from '../constants';
import {
AssetBuyerError,
AssetBuyerOrdersAndFillableAmounts,
OrderProviderRequest,
OrderProviderResponse,
OrdersAndFillableAmounts,
SignedOrderWithRemainingFillableMakerAssetAmount,
} from '../types';
import { orderUtils } from './order_utils';
interface OrdersAndRemainingFillableMakerAssetAmounts {
orders: SignedOrder[];
remainingFillableMakerAssetAmounts: BigNumber[];
}
export const orderProviderResponseProcessor = {
throwIfInvalidResponse(response: OrderProviderResponse, request: OrderProviderRequest): void {
const { makerAssetData, takerAssetData } = request;
@ -38,65 +33,40 @@ export const orderProviderResponseProcessor = {
* - Sort by rate
*/
async processAsync(
targetOrderProviderResponse: OrderProviderResponse,
feeOrderProviderResponse: OrderProviderResponse,
zrxTokenAssetData: string,
orderProviderResponse: OrderProviderResponse,
isMakerAssetZrxToken: boolean,
expiryBufferSeconds: number,
orderValidator?: OrderValidatorWrapper,
): Promise<AssetBuyerOrdersAndFillableAmounts> {
): Promise<OrdersAndFillableAmounts> {
// drop orders that are expired or not open
const filteredTargetOrders = filterOutExpiredAndNonOpenOrders(
targetOrderProviderResponse.orders,
expiryBufferSeconds,
);
const filteredFeeOrders = filterOutExpiredAndNonOpenOrders(
feeOrderProviderResponse.orders,
expiryBufferSeconds,
);
const filteredOrders = filterOutExpiredAndNonOpenOrders(orderProviderResponse.orders, expiryBufferSeconds);
// set the orders to be sorted equal to the filtered orders
let unsortedTargetOrders = filteredTargetOrders;
let unsortedFeeOrders = filteredFeeOrders;
let unsortedOrders = filteredOrders;
// if an orderValidator is provided, use on chain information to calculate remaining fillable makerAsset amounts
if (!_.isUndefined(orderValidator)) {
// TODO(bmillman): improvement
// try/catch these requests and throw a more domain specific error
// TODO(bmillman): optimization
// reduce this to once RPC call buy combining orders into one array and then splitting up the response
const [targetOrdersAndTradersInfo, feeOrdersAndTradersInfo] = await Promise.all(
_.map([filteredTargetOrders, filteredFeeOrders], ordersToBeValidated => {
const takerAddresses = _.map(ordersToBeValidated, () => constants.NULL_ADDRESS);
return orderValidator.getOrdersAndTradersInfoAsync(ordersToBeValidated, takerAddresses);
}),
// try/catch this request and throw a more domain specific error
const takerAddresses = _.map(filteredOrders, () => constants.NULL_ADDRESS);
const ordersAndTradersInfo = await orderValidator.getOrdersAndTradersInfoAsync(
filteredOrders,
takerAddresses,
);
// take orders + on chain information and find the valid orders and remaining fillable maker asset amounts
unsortedTargetOrders = getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
filteredTargetOrders,
targetOrdersAndTradersInfo,
zrxTokenAssetData,
);
// take orders + on chain information and find the valid orders and remaining fillable maker asset amounts
unsortedFeeOrders = getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
filteredFeeOrders,
feeOrdersAndTradersInfo,
zrxTokenAssetData,
unsortedOrders = getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
filteredOrders,
ordersAndTradersInfo,
isMakerAssetZrxToken,
);
}
// sort orders by rate
// TODO(bmillman): optimization
// provide a feeRate to the sorting function to more accurately sort based on the current market for ZRX tokens
const sortedTargetOrders = sortingUtils.sortOrdersByFeeAdjustedRate(unsortedTargetOrders);
const sortedFeeOrders = sortingUtils.sortFeeOrdersByFeeAdjustedRate(unsortedFeeOrders);
const sortedOrders = isMakerAssetZrxToken
? sortingUtils.sortFeeOrdersByFeeAdjustedRate(unsortedOrders)
: sortingUtils.sortOrdersByFeeAdjustedRate(unsortedOrders);
// unbundle orders and fillable amounts and compile final result
const targetOrdersAndRemainingFillableMakerAssetAmounts = unbundleOrdersWithAmounts(sortedTargetOrders);
const feeOrdersAndRemainingFillableMakerAssetAmounts = unbundleOrdersWithAmounts(sortedFeeOrders);
return {
orders: targetOrdersAndRemainingFillableMakerAssetAmounts.orders,
feeOrders: feeOrdersAndRemainingFillableMakerAssetAmounts.orders,
remainingFillableMakerAssetAmounts:
targetOrdersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
remainingFillableFeeAmounts:
feeOrdersAndRemainingFillableMakerAssetAmounts.remainingFillableMakerAssetAmounts,
};
const result = unbundleOrdersWithAmounts(sortedOrders);
return result;
},
};
@ -120,7 +90,7 @@ function filterOutExpiredAndNonOpenOrders(
function getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
inputOrders: SignedOrder[],
ordersAndTradersInfo: OrderAndTraderInfo[],
zrxAssetData: string,
isMakerAssetZrxToken: boolean,
): SignedOrderWithRemainingFillableMakerAssetAmount[] {
// iterate through the input orders and find the ones that are still fillable
// for the orders that are still fillable, calculate the remaining fillable maker asset amount
@ -147,7 +117,7 @@ function getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
const remainingFillableCalculator = new RemainingFillableCalculator(
order.makerFee,
order.makerAssetAmount,
order.makerAssetData === zrxAssetData,
isMakerAssetZrxToken,
transferrableAssetAmount,
transferrableFeeAssetAmount,
remainingMakerAssetAmount,
@ -175,7 +145,7 @@ function getValidOrdersWithRemainingFillableMakerAssetAmountsFromOnChain(
*/
function unbundleOrdersWithAmounts(
ordersWithAmounts: SignedOrderWithRemainingFillableMakerAssetAmount[],
): OrdersAndRemainingFillableMakerAssetAmounts {
): OrdersAndFillableAmounts {
const result = _.reduce(
ordersWithAmounts,
(acc, orderWithAmount) => {

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "3.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.0",
"changes": [

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.0.1 - _October 2, 2018_
* Dependencies updated
## v3.0.0 - _September 28, 2018_
* Change the way we detect BN to work with the newest ethers.js (#1069)

View File

@ -9,6 +9,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build": "tsc -b",
"build:ci": "yarn build",
"clean": "shx rm -rf lib",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "3.0.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "3.0.0",
"changes": [

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.0.1 - _October 2, 2018_
* Dependencies updated
## v3.0.0 - _September 28, 2018_
* Change /order_config request to a POST instead of GET (#1091)

View File

@ -16,6 +16,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build": "tsc -b",
"build:ci": "yarn build",
"clean": "shx rm -rf lib test_temp generated_docs",
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
"lint": "tslint --project .",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "2.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "2.0.1",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.0.2 - _October 2, 2018_
* Dependencies updated
## v2.0.1 - _September 28, 2018_
* Dependencies updated

View File

@ -12,6 +12,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s update_artifacts generate_contract_wrappers copy_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token|ZRXToken|ERC20Token|ERC721Token|WETH9|ERC20Proxy|ERC721Proxy|Forwarder|OrderValidator).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers",
"lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*",
@ -52,7 +53,6 @@
"@types/sinon": "^2.2.2",
"@types/uuid": "^3.4.2",
"@types/web3-provider-engine": "^14.0.0",
"awesome-typescript-loader": "^3.1.3",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",

View File

@ -58,7 +58,7 @@ export class ContractWrappers {
*/
public orderValidator: OrderValidatorWrapper;
private _web3Wrapper: Web3Wrapper;
private readonly _web3Wrapper: Web3Wrapper;
/**
* Instantiates a new ContractWrappers instance.
* @param provider The Provider instance you would like the 0x.js library to use for interacting with

View File

@ -3,7 +3,6 @@ import { AbstractOrderFilledCancelledFetcher } from '@0xproject/order-utils';
import { BigNumber } from '@0xproject/utils';
import { BlockParamLiteral } from 'ethereum-types';
import { ERC20TokenWrapper } from '../contract_wrappers/erc20_token_wrapper';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
export class OrderFilledCancelledFetcher implements AbstractOrderFilledCancelledFetcher {

View File

@ -1,7 +1,7 @@
import { assert as sharedAssert } from '@0xproject/assert';
// HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here
import { Schema } from '@0xproject/json-schemas'; // tslint:disable-line:no-unused-variable
import { signatureUtils, assetDataUtils } from '@0xproject/order-utils';
import { assetDataUtils, signatureUtils } from '@0xproject/order-utils';
import { Order } from '@0xproject/types'; // tslint:disable-line:no-unused-variable
import { BigNumber } from '@0xproject/utils'; // tslint:disable-line:no-unused-variable
import { Web3Wrapper } from '@0xproject/web3-wrapper';

View File

@ -1,4 +1,3 @@
import { RevertReason } from '@0xproject/types';
import * as _ from 'lodash';
import { AsyncMethod, ContractWrappersError, SyncMethod } from '../types';
@ -46,7 +45,7 @@ const asyncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
// tslint:disable-next-line:only-arrow-functions
descriptor.value = async function(...args: any[]): Promise<any> {
try {
const result = await originalMethod.apply(this, args);
const result = await originalMethod.apply(this, args); // tslint:disable-line:no-invalid-this
return result;
} catch (error) {
const transformedError = errorTransformer(error);
@ -73,7 +72,7 @@ const syncErrorHandlerFactory = (errorTransformer: ErrorTransformer) => {
// tslint:disable-next-line:only-arrow-functions
descriptor.value = function(...args: any[]): any {
try {
const result = originalMethod.apply(this, args);
const result = originalMethod.apply(this, args); // tslint:disable-line:no-invalid-this
return result;
} catch (error) {
const transformedError = errorTransformer(error);

View File

@ -34,7 +34,7 @@ const ERR_MSG_MAPPING = {
};
export class ExchangeTransferSimulator {
private _store: AbstractBalanceAndProxyAllowanceLazyStore;
private readonly _store: AbstractBalanceAndProxyAllowanceLazyStore;
private static _throwValidationError(
failureReason: FailureReason,
tradeSide: TradeSide,

View File

@ -1,4 +1,4 @@
import { ConstructorAbi, ContractAbi, EventAbi, FallbackAbi, FilterObject, LogEntry, MethodAbi } from 'ethereum-types';
import { ContractAbi, EventAbi, FilterObject, LogEntry } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as jsSHA3 from 'js-sha3';
import * as _ from 'lodash';

View File

@ -23,7 +23,7 @@ const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = {
* can submit this to the blockchain. The Exchange context executes as if UserA had directly submitted this transaction.
*/
export class TransactionEncoder {
private _exchangeInstance: ExchangeContract;
private readonly _exchangeInstance: ExchangeContract;
constructor(exchangeInstance: ExchangeContract) {
this._exchangeInstance = exchangeInstance;
}

View File

@ -3,7 +3,6 @@ import * as chai from 'chai';
import * as _ from 'lodash';
import 'mocha';
import { assert } from '../src/utils/assert';
import { calldataOptimizationUtils } from '../src/utils/calldata_optimization_utils';
import { constants } from '../src/utils/constants';

View File

@ -229,11 +229,17 @@ describe('ERC721Wrapper', () => {
it('should set the proxy approval', async () => {
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const approvalBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync(tokenAddress, tokenId);
expect(approvalBeforeSet).to.be.false();
const isProxyApprovedBeforeSet = await contractWrappers.erc721Token.isProxyApprovedAsync(
tokenAddress,
tokenId,
);
expect(isProxyApprovedBeforeSet).to.be.false();
await contractWrappers.erc721Token.setProxyApprovalAsync(tokenAddress, tokenId);
const approvalAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync(tokenAddress, tokenId);
expect(approvalAfterSet).to.be.true();
const isProxyApprovedAfterSet = await contractWrappers.erc721Token.isProxyApprovedAsync(
tokenAddress,
tokenId,
);
expect(isProxyApprovedAfterSet).to.be.true();
});
});
describe('#subscribe', () => {
@ -357,7 +363,6 @@ describe('ERC721Wrapper', () => {
);
contractWrappers.erc721Token.unsubscribe(subscriptionToken);
const tokenId = await tokenUtils.mintDummyERC721Async(tokenAddress, ownerAddress);
const isApproved = true;
await web3Wrapper.awaitTransactionSuccessAsync(
await contractWrappers.erc721Token.setApprovalForAllAsync(
@ -373,15 +378,11 @@ describe('ERC721Wrapper', () => {
});
});
describe('#getLogsAsync', () => {
let tokenTransferProxyAddress: string;
const blockRange: BlockRange = {
fromBlock: 0,
toBlock: BlockParamLiteral.Latest,
};
let txHash: string;
before(() => {
tokenTransferProxyAddress = contractWrappers.erc721Proxy.getContractAddress();
});
it('should get logs with decoded args emitted by ApprovalForAll', async () => {
const isApprovedForAll = true;
txHash = await contractWrappers.erc721Token.setApprovalForAllAsync(

View File

@ -344,7 +344,7 @@ describe('EtherTokenWrapper', () => {
etherTokenAddress = tokenUtils.getWethTokenAddress();
erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
// Start the block range after all migrations to avoid unexpected logs
const currentBlock = await web3Wrapper.getBlockNumberAsync();
const currentBlock: number = await web3Wrapper.getBlockNumberAsync();
const fromBlock = currentBlock + 1;
blockRange = {
fromBlock,

View File

@ -1,14 +1,12 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { DoneCallback, SignedOrder } from '@0xproject/types';
import { assetDataUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { BlockParamLiteral } from 'ethereum-types';
import 'mocha';
import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src';
import { DecodedLogEvent } from '../src/types';
import { ContractWrappers, OrderStatus } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';

View File

@ -1,15 +1,14 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { DoneCallback, SignedOrder } from '@0xproject/types';
import { assetDataUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { BlockParamLiteral } from 'ethereum-types';
import * as _ from 'lodash';
import 'mocha';
import { ContractWrappers, ExchangeCancelEventArgs, ExchangeEvents, ExchangeFillEventArgs, OrderStatus } from '../src';
import { DecodedLogEvent, OrderInfo, TraderInfo } from '../src/types';
import { ContractWrappers, OrderStatus } from '../src';
import { OrderInfo, TraderInfo } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
@ -26,7 +25,6 @@ describe('OrderValidator', () => {
blockPollingIntervalMs: 0,
};
const fillableAmount = new BigNumber(5);
const partialFillAmount = new BigNumber(2);
let contractWrappers: ContractWrappers;
let fillScenarios: FillScenarios;
let exchangeContractAddress: string;

View File

@ -1,6 +1,5 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import 'mocha';
import * as Sinon from 'sinon';
@ -18,17 +17,11 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('SubscriptionTest', () => {
let contractWrappers: ContractWrappers;
let userAddresses: string[];
let coinbase: string;
let addressWithoutFunds: string;
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
};
before(async () => {
contractWrappers = new ContractWrappers(provider, config);
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
coinbase = userAddresses[0];
addressWithoutFunds = userAddresses[1];
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@ -39,7 +32,6 @@ describe('SubscriptionTest', () => {
describe('#subscribe', () => {
const indexFilterValues = {};
let tokenAddress: string;
const allowanceAmount = new BigNumber(42);
let stubs: Sinon.SinonStub[] = [];
before(() => {
const tokenAddresses = tokenUtils.getDummyERC20TokenAddresses();
@ -53,7 +45,7 @@ describe('SubscriptionTest', () => {
it('Should allow unsubscribeAll to be called successfully after an error', (done: DoneCallback) => {
(async () => {
const callback = (err: Error | null, _logEvent?: DecodedLogEvent<ERC20TokenApprovalEventArgs>) =>
_.noop;
_.noop.bind(_);
contractWrappers.erc20Token.subscribe(
tokenAddress,
ERC20TokenEvents.Approval,

View File

@ -12,6 +12,7 @@
},
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s compile copy_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles -u 4 '../migrations/artifacts/development/**/*' ./lib/artifacts;",
"test": "yarn run_mocha",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.12",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.11",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.12 - _October 2, 2018_
* Dependencies updated
## v1.0.11 - _September 28, 2018_
* Dependencies updated

View File

@ -9,6 +9,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build": "tsc -b",
"build:ci": "yarn build",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test",
"test:circleci": "yarn test:coverage",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.10",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.9",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.10 - _October 2, 2018_
* Dependencies updated
## v1.0.9 - _September 28, 2018_
* Dependencies updated

View File

@ -1,6 +1,6 @@
{
"name": "ethereum-types",
"version": "1.0.9",
"version": "1.0.10",
"engines": {
"node": ">=6.12"
},
@ -9,6 +9,7 @@
"types": "lib/index.d.ts",
"scripts": {
"build": "tsc -b",
"build:ci": "yarn build",
"clean": "shx rm -rf lib generated_docs",
"lint": "tslint --project .",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"

View File

@ -497,4 +497,4 @@ export interface CompilerOptions {
compilerSettings?: CompilerSettings;
contracts?: string[] | '*';
solcVersion?: string;
}
} // tslint:disable-line:max-file-line-count

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.6",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.7 - _October 2, 2018_
* Dependencies updated
## v1.0.6 - _September 28, 2018_
* Dependencies updated

View File

@ -6,6 +6,7 @@
"types": "lib/index.d.ts",
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s update_artifacts generate_contract_wrappers",
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-trimmed/$i.json lib/artifacts; done;",
"generate_contract_wrappers": "abi-gen --abis 'lib/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",

2
packages/instant/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
public/main.bundle.js
public/main.bundle.js.map

View File

@ -0,0 +1 @@
[]

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,99 @@
## @0xproject/instant
## Installation
```bash
yarn add @0xproject/instant
```
**Import**
**CommonJS module**
```typescript
import { ZeroExInstant } from '@0xproject/instant';
```
or
```javascript
var ZeroExInstant = require('@0xproject/instant').ZeroExInstant;
```
If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`:
```json
"compilerOptions": {
"typeRoots": ["node_modules/@0xproject/typescript-typings/types", "node_modules/@types"],
}
```
**UMD Module**
The package is also available as a UMD module named `zeroExInstant`.
```html
<head>
<script type="text/javascript" src="[zeroExInstantUMDPath]" charset="utf-8"></script>
</head>
<body>
<div id="zeroExInstantContainer"></div>
<script>
zeroExInstant.render({
// Initialization options
}, '#zeroExInstantContainer');
</script>
</body>
```
## 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=@0xproject/instant yarn build
```
Or continuously rebuild on change:
```bash
PKG=@0xproject/instant yarn watch
```
### Clean
```bash
yarn clean
```
### Lint
```bash
yarn lint
```
### Run Tests
```bash
yarn test
```

View File

@ -0,0 +1,10 @@
module.exports = {
roots: ['<rootDir>/test'],
coverageDirectory: 'coverage',
transform: {
'.*.tsx?$': 'ts-jest',
},
testRegex: '(/__test__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/index.tsx'],
};

View File

@ -0,0 +1,84 @@
{
"name": "@0xproject/instant",
"version": "0.0.1",
"engines": {
"node": ">=6.12"
},
"private": true,
"description": "0x Instant React Component",
"main": "lib/src/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"build": "yarn build:all",
"build:all": "run-p build:umd:prod build:commonjs",
"build:umd:prod": "webpack --mode production",
"build:commonjs": "tsc -b",
"build:ci": "yarn build",
"watch_without_deps": "tsc -w",
"dev": "webpack-dev-server --mode development",
"lint": "tslint --project .",
"test": "jest",
"test:coverage": "jest --coverage",
"rebuild_and_test": "run-s clean build test",
"test:circleci": "yarn test:coverage",
"clean": "shx rm -rf lib coverage scripts",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
},
"config": {
"postpublish": {
"assets": [
"packages/instant/public/index.js",
"packages/instant/public/index.min.js"
]
}
},
"repository": {
"type": "git",
"url": "https://github.com/0xProject/0x-monorepo.git"
},
"author": "Francesco Agosti",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/0xProject/0x-monorepo/issues"
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
"dependencies": {
"@0xproject/connect": "^2.0.4",
"@0xproject/types": "^1.1.1",
"@0xproject/typescript-typings": "^2.0.2",
"@0xproject/utils": "^1.0.11",
"@0xproject/web3-wrapper": "^3.0.1",
"ethereum-types": "^1.0.8",
"lodash": "^4.17.10",
"react": "^16.5.2",
"react-dom": "^16.5.2"
},
"devDependencies": {
"@0xproject/tslint-config": "^1.0.7",
"@types/enzyme": "^3.1.14",
"@types/enzyme-adapter-react-16": "^1.0.3",
"@types/lodash": "^4.14.116",
"@types/node": "*",
"@types/react": "16.4.7",
"@types/react-dom": "^16.0.8",
"awesome-typescript-loader": "^5.2.1",
"copyfiles": "^1.2.0",
"enzyme": "^3.6.0",
"enzyme-adapter-react-16": "^1.5.0",
"jest": "^23.6.0",
"make-promises-safe": "^1.1.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.0.1",
"shx": "^0.2.2",
"ts-jest": "^23.10.3",
"tslint": "5.11.0",
"typedoc": "0.12.0",
"typescript": "3.0.1",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.1.9"
},
"publishConfig": {
"access": "private"
}
}

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>0x Instant Dev Environment</title>
<script type="text/javascript" src="/main.bundle.js" charset="utf-8"></script>
</head>
<body>
<div id="zeroExInstantContainer"></div>
<script>
zeroExInstant.render({
});
</script>
</body>
</html>

View File

@ -0,0 +1,5 @@
import * as React from 'react';
export interface ZeroExInstantProps {}
export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = () => <div>ZeroExInstant</div>;

6
packages/instant/src/globals.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
declare module '*.json' {
const json: any;
/* tslint:disable */
export default json;
/* tslint:enable */
}

View File

@ -0,0 +1 @@
export { ZeroExInstant, ZeroExInstantProps } from './components/zero_ex_instant';

View File

@ -0,0 +1,10 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ZeroExInstant } from './index';
export interface ZeroExInstantOptions {}
export const render = (props: ZeroExInstantOptions, selector: string = '#zeroExInstantContainer') => {
ReactDOM.render(React.createElement(ZeroExInstant, props), document.querySelector(selector));
};

View File

@ -0,0 +1,13 @@
import { configure, shallow } from 'enzyme';
import * as Adapter from 'enzyme-adapter-react-16';
import * as React from 'react';
configure({ adapter: new Adapter() });
import { ZeroExInstant } from '../../src';
describe('<ZeroExInstant />', () => {
it('shallow renders without crashing', () => {
shallow(<ZeroExInstant />);
});
});

View File

@ -0,0 +1,17 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib",
"rootDir": ".",
"jsx": "react",
"allowSyntheticDefaultImports": true,
"noImplicitAny": true,
"module": "ESNext",
"moduleResolution": "node",
"lib": ["es2015", "dom"],
"target": "es5",
"sourceMap": true
},
"include": ["./src/**/*", "./test/**/*"],
"exclude": ["./src/index.umd.ts"]
}

View File

@ -0,0 +1,3 @@
{
"extends": ["@0xproject/tslint-config"]
}

View File

@ -0,0 +1,7 @@
{
"extends": "../../typedoc-tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@ -0,0 +1,28 @@
const path = require('path');
// The common js bundle (not this one) is built using tsc.
// The umd bundle (this one) has a different entrypoint.
module.exports = {
entry: './src/index.umd.ts',
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'public'),
library: 'zeroExInstant',
libraryTarget: 'umd',
},
devtool: 'source-map',
resolve: {
extensions: ['.js', '.json', '.ts', '.tsx'],
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: 'awesome-typescript-loader',
},
],
},
devServer: {
contentBase: path.join(__dirname, 'public'),
port: 5000,
},
};

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.5",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.6 - _October 2, 2018_
* Dependencies updated
## v1.0.5 - _September 28, 2018_
* Dependencies updated

View File

@ -1,6 +1,6 @@
{
"name": "@0xproject/json-schemas",
"version": "1.0.5",
"version": "1.0.6",
"engines": {
"node": ">=6.12"
},
@ -9,6 +9,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build": "tsc -b",
"build:ci": "yarn build",
"lint": "tslint --project .",
"test": "yarn run_mocha",
"rebuild_and_test": "run-s clean build test",

View File

@ -9,6 +9,7 @@
"scripts": {
"lint": "tslint --project . --exclude **/src/contract_wrappers/**/*",
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s compile generate_contract_wrappers copy_artifacts",
"clean": "shx rm -rf lib artifacts src/contract_wrappers",
"copy_artifacts": "copyfiles './artifacts/**/*' './contracts/**/*' ./lib",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.13",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.14 - _October 2, 2018_
* Dependencies updated
## v1.0.13 - _September 28, 2018_
* Dependencies updated

View File

@ -9,6 +9,7 @@
"types": "lib/index.d.ts",
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s copy_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles 'artifacts/**/*' ./lib",
"clean": "shx rm -rf lib src/1.0.0/contract_wrappers src/2.0.0-testnet/contract_wrappers src/2.0.0/contract_wrappers artifacts/development",

View File

@ -10,6 +10,7 @@
"types": "lib/index.d.ts",
"scripts": {
"build": "tsc -b",
"build:ci": "yarn build",
"lint": "tslint --project .",
"clean": "shx rm -rf lib",
"test:publish": "run-s build script:publish",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.7",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "1.0.6",
"changes": [

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.7 - _October 2, 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)

View File

@ -9,6 +9,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s update_artifacts generate_contract_wrappers",
"generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|IWallet|IValidator|DummyERC20Token|ERC20Proxy|ERC20Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
"update_artifacts": "for i in ${npm_package_config_contracts_v2}; do copyfiles -u 4 ../migrations/artifacts/2.0.0-trimmed/$i.json lib/src/artifacts; done;",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "2.1.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"version": "2.1.0",
"changes": [

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.1.1 - _October 2, 2018_
* Dependencies updated
## v2.1.0 - _September 28, 2018_
* Export ExpirationWatcher (#1097)

View File

@ -13,6 +13,7 @@
"types": "lib/src/index.d.ts",
"scripts": {
"build": "yarn pre_build && tsc -b",
"build:ci": "yarn build",
"pre_build": "run-s update_artifacts copy_artifacts generate_contract_wrappers",
"lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
"generate_contract_wrappers": "abi-gen --abis 'src/artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
@ -51,13 +52,11 @@
"@types/mocha": "^2.2.42",
"@types/node": "*",
"@types/sinon": "^2.2.2",
"awesome-typescript-loader": "^3.1.3",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^2.0.1",
"copyfiles": "^2.0.0",
"dirty-chai": "^2.0.1",
"json-loader": "^0.5.4",
"make-promises-safe": "^1.1.0",
"mocha": "^4.1.0",
"npm-run-all": "^4.1.2",

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.13",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.12",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.13 - _October 2, 2018_
* Dependencies updated
## v1.0.12 - _September 28, 2018_
* Dependencies updated

View File

@ -10,6 +10,7 @@
"scripts": {
"lint": "tslint --project .",
"build": "tsc -b",
"build:ci": "yarn build",
"clean": "shx rm -rf lib"
},
"author": "Fabio Berger",

View File

@ -218,11 +218,11 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
_.isEmpty(docSection.events);
const sortedTypes = _.sortBy(docSection.types, 'name');
const typeDefs = _.map(sortedTypes, customType => {
const typeDefs = _.map(sortedTypes, (customType, i) => {
return (
<TypeDefinition
sectionName={sectionName}
key={`type-${customType.name}`}
key={`type-${customType.name}-${i}`}
customType={customType}
docsInfo={this.props.docsInfo}
typeDefinitionByName={typeDefinitionByName}
@ -353,7 +353,7 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
key={`badge-${networkName}-${sectionName}`}
href={linkIfExists}
target="_blank"
style={{ color: colors.white, textDecoration: 'none' }}
style={{ color: colors.white, textDecoration: 'none', marginTop: 8 }}
>
<Badge title={networkName} backgroundColor={networkNameToColor[networkName]} />
</a>

View File

@ -20,9 +20,9 @@ export interface InterfaceProps {
export const Interface: React.SFC<InterfaceProps> = (props: InterfaceProps): any => {
const type = props.type;
const properties = _.map(type.children, property => {
const properties = _.map(type.children, (property, i) => {
return (
<span key={`property-${property.name}-${property.type}-${type.name}`}>
<span key={`property-${property.name}-${property.type}-${type.name}-${i}`}>
{property.name}:{' '}
{property.type && !_.isUndefined(property.type.method) ? (
<Signature

View File

@ -19,12 +19,14 @@ export interface SignatureProps {
callPath?: string;
docsInfo: DocsInfo;
isInPopover: boolean;
isFallback?: boolean;
}
const defaultProps = {
shouldHideMethodName: false,
shouldUseArrowSyntax: false,
callPath: '',
isFallback: false,
};
export const Signature: React.SFC<SignatureProps> = (props: SignatureProps) => {
@ -34,6 +36,7 @@ export const Signature: React.SFC<SignatureProps> = (props: SignatureProps) => {
props.docsInfo,
sectionName,
props.isInPopover,
props.name,
props.typeDefinitionByName,
);
const paramStringArray: any[] = [];
@ -75,7 +78,7 @@ export const Signature: React.SFC<SignatureProps> = (props: SignatureProps) => {
return (
<span style={{ fontSize: 15 }}>
{props.callPath}
{methodName}
{props.isFallback ? '' : methodName}
{typeParameterIfExists}({hasMoreThenTwoParams && <br />}
{paramStringArray})
{props.returnType && (
@ -101,9 +104,10 @@ function renderParameters(
docsInfo: DocsInfo,
sectionName: string,
isInPopover: boolean,
name: string,
typeDefinitionByName?: TypeDefinitionByName,
): React.ReactNode[] {
const params = _.map(parameters, (p: Parameter) => {
const params = _.map(parameters, (p: Parameter, i: number) => {
const isOptional = p.isOptional;
const hasDefaultValue = !_.isUndefined(p.defaultValue);
const type = (
@ -116,9 +120,14 @@ function renderParameters(
/>
);
return (
<span key={`param-${p.type}-${p.name}`}>
{p.name}
{isOptional && '?'}: {type}
<span key={`param-${JSON.stringify(p.type)}-${name}-${i}`}>
{!_.isEmpty(p.name) && (
<span>
{p.name}
{isOptional && '?'}:{' '}
</span>
)}
{type}
{hasDefaultValue && ` = ${p.defaultValue}`}
</span>
);

View File

@ -32,7 +32,6 @@ export interface SignatureBlockState {
const styles: Styles = {
chip: {
fontSize: 13,
backgroundColor: colors.lightBlueA700,
color: colors.white,
height: 11,
borderRadius: 14,
@ -50,6 +49,8 @@ export class SignatureBlock extends React.Component<SignatureBlockProps, Signatu
public render(): React.ReactNode {
const method = this.props.method;
const isFallback = (method as SolidityMethod).isFallback;
const hasExclusivelyNamedParams = !_.isUndefined(_.find(method.parameters, p => !_.isEmpty(p.name)));
return (
<div
id={`${this.props.sectionName}-${method.name}`}
@ -63,10 +64,11 @@ export class SignatureBlock extends React.Component<SignatureBlockProps, Signatu
{(method as TypescriptMethod).isStatic && this._renderChip('Static')}
{(method as SolidityMethod).isConstant && this._renderChip('Constant')}
{(method as SolidityMethod).isPayable && this._renderChip('Payable')}
{isFallback && this._renderChip('Fallback', colors.lightGreenA700)}
<div style={{ lineHeight: 1.3 }}>
<AnchorTitle
headerSize={HeaderSizes.H3}
title={method.name}
title={isFallback ? '' : method.name}
id={`${this.props.sectionName}-${method.name}`}
shouldShowAnchor={this.state.shouldShowAnchor}
/>
@ -84,6 +86,7 @@ export class SignatureBlock extends React.Component<SignatureBlockProps, Signatu
typeDefinitionByName={this.props.typeDefinitionByName}
docsInfo={this.props.docsInfo}
isInPopover={false}
isFallback={isFallback}
/>
</code>
{(method as TypescriptMethod).source && (
@ -95,12 +98,13 @@ export class SignatureBlock extends React.Component<SignatureBlockProps, Signatu
)}
{method.comment && <Comment comment={method.comment} className="py2" />}
{method.parameters &&
!_.isEmpty(method.parameters) && (
!_.isEmpty(method.parameters) &&
hasExclusivelyNamedParams && (
<div>
<h4 className="pb1 thin" style={{ borderBottom: '1px solid #e1e8ed' }}>
ARGUMENTS
</h4>
{this._renderParameterDescriptions(method.parameters)}
{this._renderParameterDescriptions(method.parameters, method.name)}
</div>
)}
{method.returnComment && (
@ -114,19 +118,19 @@ export class SignatureBlock extends React.Component<SignatureBlockProps, Signatu
</div>
);
}
private _renderChip(text: string): React.ReactNode {
private _renderChip(text: string, backgroundColor: string = colors.lightBlueA700): React.ReactNode {
return (
<div className="p1 mr1" style={styles.chip}>
<div className="p1 mr1" style={{ ...styles.chip, backgroundColor }}>
{text}
</div>
);
}
private _renderParameterDescriptions(parameters: Parameter[]): React.ReactNode {
const descriptions = _.map(parameters, parameter => {
private _renderParameterDescriptions(parameters: Parameter[], name: string): React.ReactNode {
const descriptions = _.map(parameters, (parameter: Parameter, i: number) => {
const isOptional = parameter.isOptional;
return (
<div
key={`param-description-${parameter.name}`}
key={`param-description-${parameter.name}-${name}-${i}`}
className="flex pb1 mb2"
style={{ borderBottom: '1px solid #f0f4f7' }}
>

View File

@ -7,12 +7,12 @@ import { Link as ScrollLink } from 'react-scroll';
import * as ReactTooltip from 'react-tooltip';
import { DocsInfo } from '../docs_info';
import { constants } from '../utils/constants';
import { Signature } from './signature';
import { TypeDefinition } from './type_definition';
const basicJsTypes = ['string', 'number', 'undefined', 'null', 'boolean'];
const basicSolidityTypes = ['bytes', 'bytes4', 'bytes32', 'uint8', 'uint256', 'address'];
const defaultProps = {};
@ -80,7 +80,7 @@ export const Type: React.SFC<TypeProps> = (props: TypeProps): any => {
case TypeDocTypes.Array:
typeName = type.elementType.name;
if (_.includes(basicJsTypes, typeName)) {
if (_.includes(basicJsTypes, typeName) || _.includes(basicSolidityTypes, typeName)) {
typeNameColor = colors.orange;
}
break;
@ -168,10 +168,10 @@ export const Type: React.SFC<TypeProps> = (props: TypeProps): any => {
break;
case TypeDocTypes.Tuple:
const tupleTypes = _.map(type.tupleElements, t => {
const tupleTypes = _.map(type.tupleElements, (t, i) => {
return (
<Type
key={`type-tuple-${t.name}-${t.typeDocType}`}
key={`type-tuple-${t.name}-${t.typeDocType}-${i}`}
type={t}
sectionName={props.sectionName}
typeDefinitionByName={props.typeDefinitionByName}
@ -221,7 +221,7 @@ export const Type: React.SFC<TypeProps> = (props: TypeProps): any => {
const id = Math.random().toString();
const typeDefinitionAnchorId = isExportedClassReference
? props.type.name
: `${constants.TYPES_SECTION_NAME}-${typeName}`;
: `${props.docsInfo.typeSectionName}-${typeName}`;
typeName = (
<ScrollLink
to={typeDefinitionAnchorId}

View File

@ -5,7 +5,7 @@ import * as _ from 'lodash';
import * as React from 'react';
import { DocsInfo } from '../docs_info';
import { KindString } from '../types';
import { KindString, SupportedDocJson } from '../types';
import { constants } from '../utils/constants';
import { Comment } from './comment';
@ -46,7 +46,7 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
let codeSnippet: React.ReactNode;
switch (customType.kindString) {
case KindString.Interface:
typePrefix = 'Interface';
typePrefix = this.props.docsInfo.type === SupportedDocJson.SolDoc ? 'Struct' : 'Interface';
codeSnippet = (
<Interface
type={customType}

View File

@ -18,6 +18,7 @@ export class DocsInfo {
public packageName: string;
public packageUrl: string;
public menu: DocsMenu;
public typeSectionName: string;
public sections: SectionsMap;
public sectionNameToMarkdownByVersion: SectionNameToMarkdownByVersion;
public contractsByVersionByNetworkId?: ContractsByVersionByNetworkId;
@ -28,6 +29,7 @@ export class DocsInfo {
this.displayName = config.displayName;
this.packageName = config.packageName;
this.packageUrl = config.packageUrl;
this.typeSectionName = config.type === SupportedDocJson.SolDoc ? 'structs' : 'types';
this.sections = config.markdownSections;
this.sectionNameToMarkdownByVersion = config.sectionNameToMarkdownByVersion;
this.contractsByVersionByNetworkId = config.contractsByVersionByNetworkId;
@ -53,7 +55,7 @@ export class DocsInfo {
_.isEmpty(docSection.properties) &&
_.isEmpty(docSection.events);
if (!_.isUndefined(this.sections.types) && sectionName === this.sections.types) {
if (sectionName === this.typeSectionName) {
const sortedTypesNames = _.sortBy(docSection.types, 'name');
const typeNames = _.map(sortedTypesNames, t => t.name);
menuSubsectionsBySection[sectionName] = typeNames;
@ -82,12 +84,12 @@ export class DocsInfo {
return menuSubsectionsBySection;
}
public getTypeDefinitionsByName(docAgnosticFormat: DocAgnosticFormat): { [name: string]: TypeDefinitionByName } {
if (_.isUndefined(this.sections.types)) {
if (_.isUndefined(docAgnosticFormat[this.typeSectionName])) {
return {};
}
const typeDocSection = docAgnosticFormat[this.sections.types];
const typeDefinitionByName = _.keyBy(typeDocSection.types, 'name') as any;
const section = docAgnosticFormat[this.typeSectionName];
const typeDefinitionByName = _.keyBy(section.types, 'name') as any;
return typeDefinitionByName;
}
}

View File

@ -1,4 +1,13 @@
[
{
"timestamp": 1538475601,
"version": "1.0.14",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1538157789,
"version": "1.0.13",

View File

@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.14 - _October 2, 2018_
* Dependencies updated
## v1.0.13 - _September 28, 2018_
* Dependencies updated

View File

@ -1,6 +1,6 @@
{
"name": "@0xproject/react-shared",
"version": "1.0.13",
"version": "1.0.14",
"engines": {
"node": ">=6.12"
},
@ -10,6 +10,7 @@
"scripts": {
"lint": "tslint --project .",
"build": "tsc",
"build:ci": "yarn build",
"watch_without_deps": "tsc -w",
"clean": "shx rm -rf lib"
},

Some files were not shown because too many files have changed in this diff Show More