aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-10-11 20:23:45 +0800
committerFabio Berger <me@fabioberger.com>2018-10-11 20:23:45 +0800
commit1cfcc82ea9869e14c1a1b78e1376c89fdbeb91f4 (patch)
tree48ef8716485c1b961b2494071f5a64f60ff42f29
parent6c9f7839c3948e60f2987f474bb2ad6457588fa3 (diff)
parent8941b6cee5b56fab6d3b89ac8a899f21d5c86350 (diff)
downloaddexon-sol-tools-1cfcc82ea9869e14c1a1b78e1376c89fdbeb91f4.tar.gz
dexon-sol-tools-1cfcc82ea9869e14c1a1b78e1376c89fdbeb91f4.tar.zst
dexon-sol-tools-1cfcc82ea9869e14c1a1b78e1376c89fdbeb91f4.zip
Merge branch 'development' into dev-section-redesign
* development: (62 commits) Fix linter error Upgrade ethereum-types Lint and update deps Be more explicit with falsiness Add type to cssRuleIfExists Fix issue where we throw if non-numeric characters are used in input Upgrade to more recent types, fix yarn.lock [fix]: [testnet-faucet] Exit 1 on build fail Explains tools we want them to use Add note about button Add dev-tools-pages bundles to gitignore Improve README Fix button and center Increase max bundle size for instant Add stuff Initial project scaffolding Change tslint config to remove conflicts with prettier fix: [testnet-faucet] Signing of orders Update the CHANGELOG Add comments for expiryBuffer ...
-rw-r--r--.circleci/config.yml2
-rw-r--r--.gitignore1
-rw-r--r--package.json28
-rw-r--r--packages/0x.js/CHANGELOG.json19
-rw-r--r--packages/0x.js/package.json2
-rw-r--r--packages/0x.js/src/index.ts10
-rw-r--r--packages/asset-buyer/CHANGELOG.json8
-rw-r--r--packages/asset-buyer/src/asset_buyer.ts6
-rw-r--r--packages/asset-buyer/src/constants.ts2
-rw-r--r--packages/asset-buyer/src/types.ts6
-rw-r--r--packages/asset-buyer/src/utils/buy_quote_calculator.ts10
-rw-r--r--packages/asset-buyer/src/utils/order_utils.ts2
-rw-r--r--packages/asset-buyer/test/buy_quote_calculator_test.ts24
-rw-r--r--packages/base-contract/package.json2
-rw-r--r--packages/base-contract/src/index.ts8
-rw-r--r--packages/contract-wrappers/package.json2
-rw-r--r--packages/contract-wrappers/src/index.ts1
-rw-r--r--packages/contract-wrappers/src/utils/transaction_encoder.ts22
-rw-r--r--packages/contract-wrappers/test/transaction_encoder_test.ts9
-rw-r--r--packages/contract_templates/contract.handlebars2
-rw-r--r--packages/contracts/package.json2
-rw-r--r--packages/contracts/test/exchange/libs.ts18
-rw-r--r--packages/contracts/test/exchange/signature_validator.ts12
-rw-r--r--packages/contracts/test/utils/transaction_factory.ts22
-rw-r--r--packages/dev-tools-pages/README.md88
-rw-r--r--packages/dev-tools-pages/less/all.less0
-rw-r--r--packages/dev-tools-pages/package.json58
-rw-r--r--packages/dev-tools-pages/public/css/basscss_responsive_custom.css85
-rw-r--r--packages/dev-tools-pages/public/css/basscss_responsive_margin.css453
-rw-r--r--packages/dev-tools-pages/public/css/basscss_responsive_padding.css134
-rw-r--r--packages/dev-tools-pages/public/css/basscss_responsive_type_scale.css35
-rwxr-xr-xpackages/dev-tools-pages/public/images/favicon/favicon-2-16x16.pngbin0 -> 684 bytes
-rwxr-xr-xpackages/dev-tools-pages/public/images/favicon/favicon-2-32x32.pngbin0 -> 1567 bytes
-rwxr-xr-xpackages/dev-tools-pages/public/images/favicon/favicon.icobin0 -> 5430 bytes
-rw-r--r--packages/dev-tools-pages/public/index.html26
-rw-r--r--packages/dev-tools-pages/ts/components/meta_tags.tsx25
-rw-r--r--packages/dev-tools-pages/ts/components/ui/button.tsx59
-rw-r--r--packages/dev-tools-pages/ts/components/ui/container.tsx55
-rw-r--r--packages/dev-tools-pages/ts/components/ui/text.tsx74
-rw-r--r--packages/dev-tools-pages/ts/globals.d.ts9
-rw-r--r--packages/dev-tools-pages/ts/index.tsx17
-rw-r--r--packages/dev-tools-pages/ts/pages/landing.tsx27
-rw-r--r--packages/dev-tools-pages/ts/utils/utils.ts32
-rw-r--r--packages/dev-tools-pages/tsconfig.json22
-rw-r--r--packages/dev-tools-pages/tslint.json10
-rw-r--r--packages/dev-tools-pages/webpack.config.js86
-rw-r--r--packages/ethereum-types/CHANGELOG.json9
-rw-r--r--packages/ethereum-types/src/index.ts6
-rw-r--r--packages/fill-scenarios/package.json2
-rw-r--r--packages/instant/package.json14
-rw-r--r--packages/instant/public/index.html13
-rw-r--r--packages/instant/src/components/amount_input.tsx47
-rw-r--r--packages/instant/src/components/buy_button.tsx19
-rw-r--r--packages/instant/src/components/instant_heading.tsx45
-rw-r--r--packages/instant/src/components/order_details.tsx62
-rw-r--r--packages/instant/src/components/ui/button.tsx60
-rw-r--r--packages/instant/src/components/ui/container.tsx64
-rw-r--r--packages/instant/src/components/ui/flex.tsx37
-rw-r--r--packages/instant/src/components/ui/index.ts5
-rw-r--r--packages/instant/src/components/ui/input.tsx40
-rw-r--r--packages/instant/src/components/ui/text.tsx80
-rw-r--r--packages/instant/src/components/zero_ex_instant.tsx17
-rw-r--r--packages/instant/src/components/zero_ex_instant_container.tsx20
-rw-r--r--packages/instant/src/containers/selected_asset_amount_input.tsx36
-rw-r--r--packages/instant/src/redux/reducer.ts31
-rw-r--r--packages/instant/src/redux/store.ts6
-rw-r--r--packages/instant/src/style/fonts.ts10
-rw-r--r--packages/instant/src/style/theme.ts27
-rw-r--r--packages/instant/src/style/util.ts11
-rw-r--r--packages/instant/src/types.ts9
-rw-r--r--packages/instant/tslint.json6
-rw-r--r--packages/json-schemas/schemas/eip712_typed_data.ts28
-rw-r--r--packages/json-schemas/schemas/zero_ex_transaction_schema.ts10
-rw-r--r--packages/json-schemas/src/schemas.ts4
-rw-r--r--packages/metacoin/package.json2
-rw-r--r--packages/migrations/package.json2
-rw-r--r--packages/order-utils/CHANGELOG.json18
-rw-r--r--packages/order-utils/package.json2
-rw-r--r--packages/order-utils/src/constants.ts35
-rw-r--r--packages/order-utils/src/eip712_utils.ts162
-rw-r--r--packages/order-utils/src/index.ts23
-rw-r--r--packages/order-utils/src/order_factory.ts9
-rw-r--r--packages/order-utils/src/order_hash.ts33
-rw-r--r--packages/order-utils/src/signature_utils.ts163
-rw-r--r--packages/order-utils/src/types.ts19
-rw-r--r--packages/order-utils/test/eip712_utils_test.ts44
-rw-r--r--packages/order-utils/test/order_hash_test.ts14
-rw-r--r--packages/order-utils/test/signature_utils_test.ts221
-rw-r--r--packages/order-watcher/package.json2
-rw-r--r--packages/order-watcher/src/index.ts8
-rw-r--r--packages/sol-cov/src/index.ts8
-rw-r--r--packages/subproviders/CHANGELOG.json13
-rw-r--r--packages/subproviders/package.json2
-rw-r--r--packages/subproviders/src/index.ts18
-rw-r--r--packages/subproviders/src/subproviders/base_wallet_subprovider.ts14
-rw-r--r--packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts37
-rw-r--r--packages/subproviders/src/subproviders/ledger.ts10
-rw-r--r--packages/subproviders/src/subproviders/metamask_subprovider.ts126
-rw-r--r--packages/subproviders/src/subproviders/mnemonic_wallet.ts28
-rw-r--r--packages/subproviders/src/subproviders/private_key_wallet.ts29
-rw-r--r--packages/subproviders/src/subproviders/signer.ts15
-rw-r--r--packages/subproviders/src/types.ts2
-rw-r--r--packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts21
-rw-r--r--packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts21
-rw-r--r--packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts21
-rw-r--r--packages/subproviders/test/utils/fixture_data.ts31
-rw-r--r--packages/testnet-faucets/gulpfile.js35
-rw-r--r--packages/testnet-faucets/src/ts/handler.ts4
-rw-r--r--packages/types/CHANGELOG.json13
-rw-r--r--packages/types/src/index.ts41
-rw-r--r--packages/utils/package.json2
-rw-r--r--packages/utils/src/abi_decoder.ts6
-rw-r--r--packages/utils/src/index.ts1
-rw-r--r--packages/utils/src/sign_typed_data_utils.ts82
-rw-r--r--packages/utils/test/sign_typed_data_utils_test.ts140
-rw-r--r--packages/web3-wrapper/CHANGELOG.json14
-rw-r--r--packages/web3-wrapper/package.json2
-rw-r--r--packages/web3-wrapper/src/index.ts1
-rw-r--r--packages/web3-wrapper/src/web3_wrapper.ts18
-rw-r--r--packages/web3-wrapper/test/web3_wrapper_test.ts15
-rw-r--r--packages/website/ts/blockchain.ts30
-rw-r--r--yarn.lock1081
122 files changed, 3478 insertions, 1393 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 31954c608..b50039aa3 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -172,7 +172,7 @@ jobs:
- run: yarn lerna run lint
- run: yarn prettier:ci
- run: cd packages/0x.js && yarn build:umd:prod
- - run: yarn bundlesize
+ - run: yarn bundlewatch
submit-coverage:
docker:
- image: circleci/node:9
diff --git a/.gitignore b/.gitignore
index dd022825d..1ae1b412d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -72,6 +72,7 @@ TODO.md
.vscode
packages/website/public/bundle*
+packages/dev-tools-pages/public/bundle*
packages/react-docs/example/public/bundle*
# server cli
diff --git a/package.json b/package.json
index 8eb736cc4..920afaf29 100644
--- a/package.json
+++ b/package.json
@@ -36,27 +36,35 @@
"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",
+ "bundlewatch": "bundlewatch",
"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"
+ "bundlewatch" : {
+ "files": [
+ {
+ "path": "packages/0x.js/_bundles/index.min.js",
+ "maxSize": "700kB"
+ },
+ {
+ "path": "packages/instant/public/main.bundle.js",
+ "maxSize": "350kB"
+ }
+ ],
+ "ci": {
+ "trackBranches": ["master", "development"],
+ "repoBranchBase": "development"
}
- ],
+ },
"devDependencies": {
"@0x-lerna-fork/lerna": "3.0.0-beta.25",
"async-child-process": "^1.1.1",
- "bundlesize": "^0.17.0",
+ "bundlewatch": "^0.2.1",
"coveralls": "^3.0.0",
- "ganache-cli": "6.1.3",
+ "ganache-cli": "6.1.8",
"lcov-result-merger": "^3.0.0",
"npm-cli-login": "^0.0.10",
"npm-run-all": "^4.1.2",
diff --git a/packages/0x.js/CHANGELOG.json b/packages/0x.js/CHANGELOG.json
index 1d6f08760..6dfcc3d33 100644
--- a/packages/0x.js/CHANGELOG.json
+++ b/packages/0x.js/CHANGELOG.json
@@ -1,5 +1,24 @@
[
{
+ "version": "2.0.0",
+ "changes": [
+ {
+ "note": "Add support for `eth_signTypedData`.",
+ "pr": 1102
+ },
+ {
+ "note":
+ "Added `MetamaskSubprovider` to handle inconsistencies in Metamask's signing JSON RPC endpoints.",
+ "pr": 1102
+ },
+ {
+ "note":
+ "Removed `SignerType` (including `SignerType.Metamask`). Please use the `MetamaskSubprovider` to wrap `web3.currentProvider`.",
+ "pr": 1102
+ }
+ ]
+ },
+ {
"version": "1.0.8",
"changes": [
{
diff --git a/packages/0x.js/package.json b/packages/0x.js/package.json
index 6a3074d26..1a57edd45 100644
--- a/packages/0x.js/package.json
+++ b/packages/0x.js/package.json
@@ -84,7 +84,7 @@
"@0xproject/utils": "^2.0.2",
"@0xproject/web3-wrapper": "^3.0.3",
"ethereum-types": "^1.0.11",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"lodash": "^4.17.5",
"web3-provider-engine": "14.0.6"
},
diff --git a/packages/0x.js/src/index.ts b/packages/0x.js/src/index.ts
index d07bfcfc8..6eb1fd8ee 100644
--- a/packages/0x.js/src/index.ts
+++ b/packages/0x.js/src/index.ts
@@ -53,7 +53,13 @@ export { OrderWatcher, OnOrderStateChangeCallback, OrderWatcherConfig } from '@0
export import Web3ProviderEngine = require('web3-provider-engine');
-export { RPCSubprovider, Callback, JSONRPCRequestPayloadWithMethod, ErrorCallback } from '@0xproject/subproviders';
+export {
+ RPCSubprovider,
+ Callback,
+ JSONRPCRequestPayloadWithMethod,
+ ErrorCallback,
+ MetamaskSubprovider,
+} from '@0xproject/subproviders';
export { AbiDecoder } from '@0xproject/utils';
@@ -68,7 +74,6 @@ export {
OrderStateInvalid,
OrderState,
AssetProxyId,
- SignerType,
ERC20AssetData,
ERC721AssetData,
SignatureType,
@@ -85,6 +90,7 @@ export {
JSONRPCRequestPayload,
JSONRPCResponsePayload,
JSONRPCErrorCallback,
+ JSONRPCResponseError,
LogEntry,
DecodedLogArgs,
LogEntryEvent,
diff --git a/packages/asset-buyer/CHANGELOG.json b/packages/asset-buyer/CHANGELOG.json
index d50a564dc..dbb801b69 100644
--- a/packages/asset-buyer/CHANGELOG.json
+++ b/packages/asset-buyer/CHANGELOG.json
@@ -1,5 +1,13 @@
[
{
+ "version": "2.1.0",
+ "changes": [
+ {
+ "note": "Add `gasLimit` and `gasPrice` as optional properties on `BuyQuoteExecutionOpts`"
+ }
+ ]
+ },
+ {
"version": "2.0.0",
"changes": [
{
diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts
index 7ec39e012..50343efde 100644
--- a/packages/asset-buyer/src/asset_buyer.ts
+++ b/packages/asset-buyer/src/asset_buyer.ts
@@ -183,7 +183,7 @@ export class AssetBuyer {
buyQuote: BuyQuote,
options: Partial<BuyQuoteExecutionOpts> = {},
): Promise<string> {
- const { ethAmount, takerAddress, feeRecipient } = {
+ const { ethAmount, takerAddress, feeRecipient, gasLimit, gasPrice } = {
...constants.DEFAULT_BUY_QUOTE_EXECUTION_OPTS,
...options,
};
@@ -219,6 +219,10 @@ export class AssetBuyer {
feeOrders,
feePercentage,
feeRecipient,
+ {
+ gasLimit,
+ gasPrice,
+ },
);
return txHash;
}
diff --git a/packages/asset-buyer/src/constants.ts b/packages/asset-buyer/src/constants.ts
index e1056e39b..e095dee06 100644
--- a/packages/asset-buyer/src/constants.ts
+++ b/packages/asset-buyer/src/constants.ts
@@ -8,7 +8,7 @@ const MAINNET_NETWORK_ID = 1;
const DEFAULT_ASSET_BUYER_OPTS: AssetBuyerOpts = {
networkId: MAINNET_NETWORK_ID,
orderRefreshIntervalMs: 10000, // 10 seconds
- expiryBufferSeconds: 15,
+ expiryBufferSeconds: 300, // 5 minutes
};
const DEFAULT_BUY_QUOTE_REQUEST_OPTS: BuyQuoteRequestOpts = {
diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts
index b96795bb6..6218f4ba4 100644
--- a/packages/asset-buyer/src/types.ts
+++ b/packages/asset-buyer/src/types.ts
@@ -77,18 +77,22 @@ export interface BuyQuoteRequestOpts {
/**
* ethAmount: The desired amount of eth to spend. Defaults to buyQuote.worstCaseQuoteInfo.totalEthAmount.
* takerAddress: The address to perform the buy. Defaults to the first available address from the provider.
+ * gasLimit: The amount of gas to send with a transaction (in Gwei). Defaults to an eth_estimateGas rpc call.
+ * gasPrice: Gas price in Wei to use for a transaction
* feeRecipient: The address where affiliate fees are sent. Defaults to null address (0x000...000).
*/
export interface BuyQuoteExecutionOpts {
ethAmount?: BigNumber;
takerAddress?: string;
+ gasLimit?: number;
+ gasPrice?: BigNumber;
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.
+ * expiryBufferSeconds: The number of seconds to add when calculating whether an order is expired or not. Defaults to 300s (5m).
*/
export interface AssetBuyerOpts {
networkId: number;
diff --git a/packages/asset-buyer/src/utils/buy_quote_calculator.ts b/packages/asset-buyer/src/utils/buy_quote_calculator.ts
index cb0fd128c..a1d334eef 100644
--- a/packages/asset-buyer/src/utils/buy_quote_calculator.ts
+++ b/packages/asset-buyer/src/utils/buy_quote_calculator.ts
@@ -72,7 +72,6 @@ export const buyQuoteCalculator = {
assetBuyAmount,
feePercentage,
);
-
return {
assetData,
orders: resultOrders,
@@ -98,13 +97,14 @@ function calculateQuoteInfo(
);
// find the total eth needed to buy fees
const ethAmountToBuyFees = findEthAmountNeededToBuyFees(feeOrdersAndFillableAmounts, zrxAmountToBuyAsset);
- const ethAmountBeforeAffiliateFee = ethAmountToBuyAsset.plus(ethAmountToBuyFees);
- const totalEthAmount = ethAmountBeforeAffiliateFee.mul(feePercentage + 1);
+ const affiliateFeeEthAmount = ethAmountToBuyAsset.mul(feePercentage);
+ const totalEthAmountWithoutAffiliateFee = ethAmountToBuyAsset.plus(ethAmountToBuyFees);
+ const totalEthAmount = totalEthAmountWithoutAffiliateFee.plus(affiliateFeeEthAmount);
// divide into the assetBuyAmount in order to find rate of makerAsset / WETH
- const ethPerAssetPrice = ethAmountBeforeAffiliateFee.div(assetBuyAmount);
+ const ethPerAssetPrice = totalEthAmountWithoutAffiliateFee.div(assetBuyAmount);
return {
totalEthAmount,
- feeEthAmount: totalEthAmount.minus(ethAmountBeforeAffiliateFee),
+ feeEthAmount: affiliateFeeEthAmount,
ethPerAssetPrice,
};
}
diff --git a/packages/asset-buyer/src/utils/order_utils.ts b/packages/asset-buyer/src/utils/order_utils.ts
index 62166eb76..cfc13a8a1 100644
--- a/packages/asset-buyer/src/utils/order_utils.ts
+++ b/packages/asset-buyer/src/utils/order_utils.ts
@@ -10,7 +10,7 @@ export const orderUtils = {
willOrderExpire(order: SignedOrder, secondsFromNow: number): boolean {
const millisecondsInSecond = 1000;
const currentUnixTimestampSec = new BigNumber(Date.now() / millisecondsInSecond).round();
- return order.expirationTimeSeconds.lessThan(currentUnixTimestampSec.minus(secondsFromNow));
+ return order.expirationTimeSeconds.lessThan(currentUnixTimestampSec.plus(secondsFromNow));
},
calculateRemainingMakerAssetAmount(order: SignedOrder, remainingTakerAssetAmount: BigNumber): BigNumber {
if (remainingTakerAssetAmount.eq(0)) {
diff --git a/packages/asset-buyer/test/buy_quote_calculator_test.ts b/packages/asset-buyer/test/buy_quote_calculator_test.ts
index b987b45a8..fda6958cd 100644
--- a/packages/asset-buyer/test/buy_quote_calculator_test.ts
+++ b/packages/asset-buyer/test/buy_quote_calculator_test.ts
@@ -103,9 +103,11 @@ describe('buyQuoteCalculator', () => {
expect(buyQuote.feeOrders).to.deep.equal([smallFeeOrderAndFillableAmount.orders[0]]);
// test if rates are correct
// 50 eth to fill the first order + 100 eth for fees
- const expectedFillEthAmount = new BigNumber(150);
- const expectedTotalEthAmount = expectedFillEthAmount.mul(feePercentage + 1);
- const expectedFeeEthAmount = expectedTotalEthAmount.minus(expectedFillEthAmount);
+ const expectedEthAmountForAsset = new BigNumber(50);
+ const expectedEthAmountForZrxFees = new BigNumber(100);
+ const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees);
+ const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
+ const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
const expectedEthPerAssetPrice = expectedFillEthAmount.div(assetBuyAmount);
expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
@@ -138,17 +140,21 @@ describe('buyQuoteCalculator', () => {
expect(buyQuote.feeOrders).to.deep.equal(allFeeOrdersAndFillableAmounts.orders);
// test if rates are correct
// 50 eth to fill the first order + 100 eth for fees
- const expectedFillEthAmount = new BigNumber(150);
- const expectedTotalEthAmount = expectedFillEthAmount.mul(feePercentage + 1);
- const expectedFeeEthAmount = expectedTotalEthAmount.minus(expectedFillEthAmount);
+ const expectedEthAmountForAsset = new BigNumber(50);
+ const expectedEthAmountForZrxFees = new BigNumber(100);
+ const expectedFillEthAmount = expectedEthAmountForAsset.plus(expectedEthAmountForZrxFees);
+ const expectedFeeEthAmount = expectedEthAmountForAsset.mul(feePercentage);
+ const expectedTotalEthAmount = expectedFillEthAmount.plus(expectedFeeEthAmount);
const expectedEthPerAssetPrice = expectedFillEthAmount.div(assetBuyAmount);
expect(buyQuote.bestCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedFeeEthAmount);
expect(buyQuote.bestCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedTotalEthAmount);
expect(buyQuote.bestCaseQuoteInfo.ethPerAssetPrice).to.bignumber.equal(expectedEthPerAssetPrice);
// 100 eth to fill the first order + 200 eth for fees
- const expectedWorstFillEthAmount = new BigNumber(300);
- const expectedWorstTotalEthAmount = expectedWorstFillEthAmount.mul(feePercentage + 1);
- const expectedWorstFeeEthAmount = expectedWorstTotalEthAmount.minus(expectedWorstFillEthAmount);
+ const expectedWorstEthAmountForAsset = new BigNumber(100);
+ const expectedWorstEthAmountForZrxFees = new BigNumber(200);
+ const expectedWorstFillEthAmount = expectedWorstEthAmountForAsset.plus(expectedWorstEthAmountForZrxFees);
+ const expectedWorstFeeEthAmount = expectedWorstEthAmountForAsset.mul(feePercentage);
+ const expectedWorstTotalEthAmount = expectedWorstFillEthAmount.plus(expectedWorstFeeEthAmount);
const expectedWorstEthPerAssetPrice = expectedWorstFillEthAmount.div(assetBuyAmount);
expect(buyQuote.worstCaseQuoteInfo.feeEthAmount).to.bignumber.equal(expectedWorstFeeEthAmount);
expect(buyQuote.worstCaseQuoteInfo.totalEthAmount).to.bignumber.equal(expectedWorstTotalEthAmount);
diff --git a/packages/base-contract/package.json b/packages/base-contract/package.json
index 7aac46ab9..4ee471219 100644
--- a/packages/base-contract/package.json
+++ b/packages/base-contract/package.json
@@ -45,7 +45,7 @@
"@0xproject/utils": "^2.0.2",
"@0xproject/web3-wrapper": "^3.0.3",
"ethereum-types": "^1.0.11",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"lodash": "^4.17.5"
},
"publishConfig": {
diff --git a/packages/base-contract/src/index.ts b/packages/base-contract/src/index.ts
index 981e6fca6..a8e4ad2e2 100644
--- a/packages/base-contract/src/index.ts
+++ b/packages/base-contract/src/index.ts
@@ -17,7 +17,7 @@ import * as _ from 'lodash';
import { formatABIDataItem } from './utils';
export interface EthersInterfaceByFunctionSignature {
- [key: string]: ethers.Interface;
+ [key: string]: ethers.utils.Interface;
}
const REVERT_ERROR_SELECTOR = '08c379a0';
@@ -101,7 +101,7 @@ export class BaseContract {
// if it overflows the corresponding Solidity type, there is a bug in the
// encoder, or the encoder performs unsafe type coercion.
public static strictArgumentEncodingCheck(inputAbi: DataItem[], args: any[]): void {
- const coder = new ethers.AbiCoder();
+ const coder = new ethers.utils.AbiCoder();
const params = abiUtils.parseEthersParams(inputAbi);
const rawEncoded = coder.encode(inputAbi, args);
const rawDecoded = coder.decode(inputAbi, rawEncoded);
@@ -117,7 +117,7 @@ export class BaseContract {
}
}
}
- protected _lookupEthersInterface(functionSignature: string): ethers.Interface {
+ protected _lookupEthersInterface(functionSignature: string): ethers.utils.Interface {
const ethersInterface = this._ethersInterfacesByFunctionSignature[functionSignature];
if (_.isUndefined(ethersInterface)) {
throw new Error(`Failed to lookup method with function signature '${functionSignature}'`);
@@ -154,7 +154,7 @@ export class BaseContract {
this._ethersInterfacesByFunctionSignature = {};
_.each(methodAbis, methodAbi => {
const functionSignature = abiUtils.getFunctionSignature(methodAbi);
- this._ethersInterfacesByFunctionSignature[functionSignature] = new ethers.Interface([methodAbi]);
+ this._ethersInterfacesByFunctionSignature[functionSignature] = new ethers.utils.Interface([methodAbi]);
});
}
}
diff --git a/packages/contract-wrappers/package.json b/packages/contract-wrappers/package.json
index e83caad97..35f27d77c 100644
--- a/packages/contract-wrappers/package.json
+++ b/packages/contract-wrappers/package.json
@@ -84,7 +84,7 @@
"ethereum-types": "^1.0.11",
"ethereumjs-blockstream": "6.0.0",
"ethereumjs-util": "^5.1.1",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"js-sha3": "^0.7.0",
"lodash": "^4.17.5",
"uuid": "^3.1.0"
diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts
index 2fcdd2ddb..e8a53170e 100644
--- a/packages/contract-wrappers/src/index.ts
+++ b/packages/contract-wrappers/src/index.ts
@@ -39,6 +39,7 @@ export {
JSONRPCRequestPayload,
JSONRPCResponsePayload,
JSONRPCErrorCallback,
+ JSONRPCResponseError,
AbiDefinition,
LogWithDecodedArgs,
FunctionAbi,
diff --git a/packages/contract-wrappers/src/utils/transaction_encoder.ts b/packages/contract-wrappers/src/utils/transaction_encoder.ts
index 87cbb43fd..33086944b 100644
--- a/packages/contract-wrappers/src/utils/transaction_encoder.ts
+++ b/packages/contract-wrappers/src/utils/transaction_encoder.ts
@@ -1,22 +1,13 @@
import { schemas } from '@0xproject/json-schemas';
-import { EIP712Schema, EIP712Types, eip712Utils } from '@0xproject/order-utils';
+import { eip712Utils } from '@0xproject/order-utils';
import { Order, SignedOrder } from '@0xproject/types';
-import { BigNumber } from '@0xproject/utils';
+import { BigNumber, signTypedDataUtils } from '@0xproject/utils';
import _ = require('lodash');
import { ExchangeContract } from '../contract_wrappers/generated/exchange';
import { assert } from './assert';
-const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = {
- name: 'ZeroExTransaction',
- parameters: [
- { name: 'salt', type: EIP712Types.Uint256 },
- { name: 'signerAddress', type: EIP712Types.Address },
- { name: 'data', type: EIP712Types.Bytes },
- ],
-};
-
/**
* Transaction Encoder. Transaction messages exist for the purpose of calling methods on the Exchange contract
* in the context of another address. For example, UserA can encode and sign a fillOrder transaction and UserB
@@ -41,12 +32,9 @@ export class TransactionEncoder {
signerAddress,
data,
};
- const executeTransactionHashBuff = eip712Utils.structHash(
- EIP712_ZEROEX_TRANSACTION_SCHEMA,
- executeTransactionData,
- );
- const eip721MessageBuffer = eip712Utils.createEIP712Message(executeTransactionHashBuff, exchangeAddress);
- const messageHex = `0x${eip721MessageBuffer.toString('hex')}`;
+ const typedData = eip712Utils.createZeroExTransactionTypedData(executeTransactionData, exchangeAddress);
+ const eip712MessageBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
+ const messageHex = `0x${eip712MessageBuffer.toString('hex')}`;
return messageHex;
}
/**
diff --git a/packages/contract-wrappers/test/transaction_encoder_test.ts b/packages/contract-wrappers/test/transaction_encoder_test.ts
index a397e43a8..9da8fe2ca 100644
--- a/packages/contract-wrappers/test/transaction_encoder_test.ts
+++ b/packages/contract-wrappers/test/transaction_encoder_test.ts
@@ -1,7 +1,7 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils, signatureUtils } from '@0xproject/order-utils';
-import { SignedOrder, SignerType } from '@0xproject/types';
+import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import 'mocha';
@@ -80,12 +80,7 @@ describe('TransactionEncoder', () => {
): Promise<void> => {
const salt = generatePseudoRandomSalt();
const encodedTransaction = encoder.getTransactionHex(data, salt, signerAddress);
- const signature = await signatureUtils.ecSignOrderHashAsync(
- provider,
- encodedTransaction,
- signerAddress,
- SignerType.Default,
- );
+ const signature = await signatureUtils.ecSignHashAsync(provider, encodedTransaction, signerAddress);
txHash = await contractWrappers.exchange.executeTransactionAsync(
salt,
signerAddress,
diff --git a/packages/contract_templates/contract.handlebars b/packages/contract_templates/contract.handlebars
index 9ae39f44f..41e5c8630 100644
--- a/packages/contract_templates/contract.handlebars
+++ b/packages/contract_templates/contract.handlebars
@@ -65,7 +65,7 @@ export class {{contractName}}Contract extends BaseContract {
[{{> params inputs=ctor.inputs}}],
BaseContract._bigNumberToString,
);
- const iface = new ethers.Interface(abi);
+ const iface = new ethers.utils.Interface(abi);
const deployInfo = iface.deployFunction;
const txData = deployInfo.encode(bytecode, [{{> params inputs=ctor.inputs}}]);
const web3Wrapper = new Web3Wrapper(provider);
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 081e5f8ee..01d04e645 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -84,7 +84,7 @@
"ethereum-types": "^1.0.11",
"ethereumjs-abi": "0.6.5",
"ethereumjs-util": "^5.1.1",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"js-combinatorics": "^0.5.3",
"lodash": "^4.17.5"
}
diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts
index 37234489e..049b7f37a 100644
--- a/packages/contracts/test/exchange/libs.ts
+++ b/packages/contracts/test/exchange/libs.ts
@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
-import { assetDataUtils, eip712Utils, orderHashUtils } from '@0xproject/order-utils';
+import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -126,22 +126,6 @@ describe('Exchange libs', () => {
});
describe('LibOrder', () => {
- describe('getOrderSchema', () => {
- it('should output the correct order schema hash', async () => {
- const orderSchema = await libs.getOrderSchemaHash.callAsync();
- const schemaHashBuffer = orderHashUtils._getOrderSchemaBuffer();
- const schemaHashHex = `0x${schemaHashBuffer.toString('hex')}`;
- expect(schemaHashHex).to.be.equal(orderSchema);
- });
- });
- describe('getDomainSeparatorSchema', () => {
- it('should output the correct domain separator schema hash', async () => {
- const domainSeparatorSchema = await libs.getDomainSeparatorSchemaHash.callAsync();
- const domainSchemaBuffer = eip712Utils._getDomainSeparatorSchemaBuffer();
- const schemaHashHex = `0x${domainSchemaBuffer.toString('hex')}`;
- expect(schemaHashHex).to.be.equal(domainSeparatorSchema);
- });
- });
describe('getOrderHash', () => {
it('should output the correct orderHash', async () => {
signedOrder = await orderFactory.newSignedOrderAsync();
diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts
index 5cc62e777..192ed3ca9 100644
--- a/packages/contracts/test/exchange/signature_validator.ts
+++ b/packages/contracts/test/exchange/signature_validator.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetDataUtils, orderHashUtils, signatureUtils } from '@0xproject/order-utils';
-import { RevertReason, SignatureType, SignedOrder, SignerType } from '@0xproject/types';
+import { RevertReason, SignatureType, SignedOrder } from '@0xproject/types';
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util');
@@ -231,10 +231,7 @@ describe('MixinSignatureValidator', () => {
it('should return true when SignatureType=EthSign and signature is valid', async () => {
// Create EthSign signature
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
- const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix(
- orderHashHex,
- SignerType.Default,
- );
+ const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix(orderHashHex);
const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
// Create 0x signature from EthSign signature
@@ -257,10 +254,7 @@ describe('MixinSignatureValidator', () => {
it('should return false when SignatureType=EthSign and signature is invalid', async () => {
// Create EthSign signature
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
- const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix(
- orderHashHex,
- SignerType.Default,
- );
+ const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix(orderHashHex);
const orderHashWithEthSignPrefixBuffer = ethUtil.toBuffer(orderHashWithEthSignPrefixHex);
const ecSignature = ethUtil.ecsign(orderHashWithEthSignPrefixBuffer, signerPrivateKey);
// Create 0x signature from EthSign signature
diff --git a/packages/contracts/test/utils/transaction_factory.ts b/packages/contracts/test/utils/transaction_factory.ts
index 8465a6a30..9ed4c5a31 100644
--- a/packages/contracts/test/utils/transaction_factory.ts
+++ b/packages/contracts/test/utils/transaction_factory.ts
@@ -1,19 +1,11 @@
-import { EIP712Schema, EIP712Types, eip712Utils, generatePseudoRandomSalt } from '@0xproject/order-utils';
+import { eip712Utils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { SignatureType } from '@0xproject/types';
+import { signTypedDataUtils } from '@0xproject/utils';
import * as ethUtil from 'ethereumjs-util';
import { signingUtils } from './signing_utils';
import { SignedTransaction } from './types';
-const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = {
- name: 'ZeroExTransaction',
- parameters: [
- { name: 'salt', type: EIP712Types.Uint256 },
- { name: 'signerAddress', type: EIP712Types.Address },
- { name: 'data', type: EIP712Types.Bytes },
- ],
-};
-
export class TransactionFactory {
private readonly _signerBuff: Buffer;
private readonly _exchangeAddress: string;
@@ -31,12 +23,10 @@ export class TransactionFactory {
signerAddress,
data,
};
- const executeTransactionHashBuff = eip712Utils.structHash(
- EIP712_ZEROEX_TRANSACTION_SCHEMA,
- executeTransactionData,
- );
- const txHash = eip712Utils.createEIP712Message(executeTransactionHashBuff, this._exchangeAddress);
- const signature = signingUtils.signMessage(txHash, this._privateKey, signatureType);
+
+ const typedData = eip712Utils.createZeroExTransactionTypedData(executeTransactionData, this._exchangeAddress);
+ const eip712MessageBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
+ const signature = signingUtils.signMessage(eip712MessageBuffer, this._privateKey, signatureType);
const signedTx = {
exchangeAddress: this._exchangeAddress,
signature: `0x${signature.toString('hex')}`,
diff --git a/packages/dev-tools-pages/README.md b/packages/dev-tools-pages/README.md
new file mode 100644
index 000000000..39fe70a25
--- /dev/null
+++ b/packages/dev-tools-pages/README.md
@@ -0,0 +1,88 @@
+## Dev tools pages
+
+This repository contains our dev tools pages.
+
+## Local Dev Setup
+
+Requires Node version 6.9.5 or higher & yarn v1.9.4
+
+### 1. Install dependencies for monorepo:
+
+Make sure you install Yarn v1.9.4 (npm won't work!). We rely on our `yarn.lock` file and on Yarn's support for `workspaces` in our monorepo setup.
+
+```bash
+yarn install
+```
+
+### 2. Initial setup
+
+To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
+
+```bash
+PKG=@0xproject/dev-tools-pages yarn build
+```
+
+Note: Ignore the `WARNING in asset size limit` and `WARNING in entrypoint size limit` warnings.
+
+### 3. Run dev server
+
+```bash
+cd packages/dev-tools-pages
+yarn dev
+```
+
+Visit [http://localhost:3572/](http://localhost:3572/) in your browser.
+
+The webpage will refresh when source code is changed.
+
+### 4. Code!
+
+There are some basic primitives we'd like you to use:
+
+1. `<Container>Stuff</Container>`: Use containers instead of divs,spans,etc... and use it's props instead of inline styles (e.g `style={{margin: 3}}` should be `margin="3px"`
+
+2. `<Text>Look ma, text!</Text>`: Use text components whenever rendering text. It has props for manipulating texts, so again no in-line styles. Use `fontColor="red"`, not `style={{color: 'red'}}`.
+
+3. Styled-components: See the `ui/button.tsx` file for an example of how to use these.
+
+4. BassCss: This library gives you access to a bunch of [classes](http://basscss.com/) that apply styles in a browser-compatible way, has affordances for responsiveness and alleviates the need for inline styles or LESS/CSS files.
+
+With the above 4 tools and following the React paradigm, you shouldn't need CSS/LESS files. IF there are special occasions where you do, these is a `all.less` file, but this is a solution of last resort. Use it sparingly.
+
+### Clean
+
+```bash
+yarn clean
+```
+
+### Lint
+
+```bash
+yarn lint
+```
+
+### Prettier
+
+Run from the monorepo root directory:
+
+```
+yarn prettier
+```
+
+### Resources
+
+##### Toolkit
+
+* [Styled Components](https://www.styled-components.com/)
+* [BassCSS](http://basscss.com/)
+
+##### Recommended Atom packages:
+
+* [atom-typescript](https://atom.io/packages/atom-typescript)
+* [linter-tslint](https://atom.io/packages/linter-tslint)
+
+## Contributing
+
+We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
+
+Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
diff --git a/packages/dev-tools-pages/less/all.less b/packages/dev-tools-pages/less/all.less
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/dev-tools-pages/less/all.less
diff --git a/packages/dev-tools-pages/package.json b/packages/dev-tools-pages/package.json
new file mode 100644
index 000000000..f73260544
--- /dev/null
+++ b/packages/dev-tools-pages/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "@0xproject/dev-tools-pages",
+ "version": "0.0.1",
+ "engines": {
+ "node": ">=6.12"
+ },
+ "private": true,
+ "description": "0x Dev tools pages",
+ "scripts": {
+ "build": "node --max_old_space_size=8192 ../../node_modules/.bin/webpack --mode production",
+ "build:ci": "yarn build",
+ "build:dev": "../../node_modules/.bin/webpack --mode development",
+ "clean": "shx rm -f public/bundle*",
+ "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'",
+ "dev": "webpack-dev-server --mode development --content-base public"
+ },
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@0xproject/react-shared": "^1.0.15",
+ "basscss": "^8.0.3",
+ "bowser": "^1.9.3",
+ "less": "^2.7.2",
+ "lodash": "^4.17.5",
+ "polished": "^1.9.2",
+ "react": "^16.4.2",
+ "react-document-title": "^2.0.3",
+ "react-dom": "^16.4.2",
+ "react-helmet": "^5.2.0",
+ "styled-components": "^3.3.0"
+ },
+ "devDependencies": {
+ "@types/lodash": "4.14.104",
+ "@types/node": "*",
+ "@types/react": "^16.4.2",
+ "@types/react-dom": "^16.0.7",
+ "@types/react-helmet": "^5.0.6",
+ "@types/react-router-dom": "^4.0.4",
+ "@types/react-tap-event-plugin": "0.0.30",
+ "@types/styled-components": "^4.0.0",
+ "awesome-typescript-loader": "^5.2.1",
+ "copyfiles": "^2.0.0",
+ "css-loader": "0.23.x",
+ "less-loader": "^4.1.0",
+ "make-promises-safe": "^1.1.0",
+ "raw-loader": "^0.5.1",
+ "shx": "^0.2.2",
+ "source-map-loader": "^0.2.4",
+ "style-loader": "0.23.x",
+ "terser-webpack-plugin": "^1.1.0",
+ "tslint": "5.11.0",
+ "tslint-config-0xproject": "^0.0.2",
+ "typescript": "3.0.1",
+ "uglifyjs-webpack-plugin": "^2.0.1",
+ "webpack": "^4.20.2",
+ "webpack-cli": "3.1.2",
+ "webpack-dev-server": "^3.1.9"
+ }
+}
diff --git a/packages/dev-tools-pages/public/css/basscss_responsive_custom.css b/packages/dev-tools-pages/public/css/basscss_responsive_custom.css
new file mode 100644
index 000000000..5f8bd9117
--- /dev/null
+++ b/packages/dev-tools-pages/public/css/basscss_responsive_custom.css
@@ -0,0 +1,85 @@
+/* Custom Basscss Responsive Utilities */
+
+@media (max-width: 52em) {
+ .sm-center {
+ text-align: center;
+ }
+ .sm-align-middle {
+ vertical-align: middle;
+ }
+ .sm-align-top {
+ vertical-align: top;
+ }
+ .sm-left-align {
+ text-align: left;
+ }
+ .sm-right-align {
+ text-align: right;
+ }
+ .sm-table-cell {
+ display: table-cell;
+ }
+ .sm-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .sm-right {
+ float: right;
+ }
+}
+
+@media (min-width: 52em) {
+ .md-center {
+ text-align: center;
+ }
+ .md-align-middle {
+ vertical-align: middle;
+ }
+ .md-align-top {
+ vertical-align: top;
+ }
+ .md-left-align {
+ text-align: left;
+ }
+ .md-right-align {
+ text-align: right;
+ }
+ .md-table-cell {
+ display: table-cell;
+ }
+ .md-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .md-right {
+ float: right;
+ }
+}
+
+@media (min-width: 64em) {
+ .lg-center {
+ text-align: center;
+ }
+ .lg-align-middle {
+ vertical-align: middle;
+ }
+ .lg-align-top {
+ vertical-align: top;
+ }
+ .lg-left-align {
+ text-align: left;
+ }
+ .lg-right-align {
+ text-align: right;
+ }
+ .lg-table-cell {
+ display: table-cell;
+ }
+ .lg-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .lg-right {
+ float: right;
+ }
+}
diff --git a/packages/dev-tools-pages/public/css/basscss_responsive_margin.css b/packages/dev-tools-pages/public/css/basscss_responsive_margin.css
new file mode 100644
index 000000000..c9f3e855c
--- /dev/null
+++ b/packages/dev-tools-pages/public/css/basscss_responsive_margin.css
@@ -0,0 +1,453 @@
+/* Basscss Responsive Margin */
+
+@media (max-width: 52em) {
+ /* Modified by Fabio Berger to max-width from min-width */
+
+ .sm-m0 {
+ margin: 0;
+ }
+ .sm-mt0 {
+ margin-top: 0;
+ }
+ .sm-mr0 {
+ margin-right: 0;
+ }
+ .sm-mb0 {
+ margin-bottom: 0;
+ }
+ .sm-ml0 {
+ margin-left: 0;
+ }
+ .sm-mx0 {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .sm-my0 {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ .sm-m1 {
+ margin: 0.5rem;
+ }
+ .sm-mt1 {
+ margin-top: 0.5rem;
+ }
+ .sm-mr1 {
+ margin-right: 0.5rem;
+ }
+ .sm-mb1 {
+ margin-bottom: 0.5rem;
+ }
+ .sm-ml1 {
+ margin-left: 0.5rem;
+ }
+ .sm-mx1 {
+ margin-left: 0.5rem;
+ margin-right: 0.5rem;
+ }
+ .sm-my1 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .sm-m2 {
+ margin: 1rem;
+ }
+ .sm-mt2 {
+ margin-top: 1rem;
+ }
+ .sm-mr2 {
+ margin-right: 1rem;
+ }
+ .sm-mb2 {
+ margin-bottom: 1rem;
+ }
+ .sm-ml2 {
+ margin-left: 1rem;
+ }
+ .sm-mx2 {
+ margin-left: 1rem;
+ margin-right: 1rem;
+ }
+ .sm-my2 {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .sm-m3 {
+ margin: 2rem;
+ }
+ .sm-mt3 {
+ margin-top: 2rem;
+ }
+ .sm-mr3 {
+ margin-right: 2rem;
+ }
+ .sm-mb3 {
+ margin-bottom: 2rem;
+ }
+ .sm-ml3 {
+ margin-left: 2rem;
+ }
+ .sm-mx3 {
+ margin-left: 2rem;
+ margin-right: 2rem;
+ }
+ .sm-my3 {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ }
+
+ .sm-m4 {
+ margin: 4rem;
+ }
+ .sm-mt4 {
+ margin-top: 4rem;
+ }
+ .sm-mr4 {
+ margin-right: 4rem;
+ }
+ .sm-mb4 {
+ margin-bottom: 4rem;
+ }
+ .sm-ml4 {
+ margin-left: 4rem;
+ }
+ .sm-mx4 {
+ margin-left: 4rem;
+ margin-right: 4rem;
+ }
+ .sm-my4 {
+ margin-top: 4rem;
+ margin-bottom: 4rem;
+ }
+
+ .sm-mxn1 {
+ margin-left: -0.5rem;
+ margin-right: -0.5rem;
+ }
+ .sm-mxn2 {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+ .sm-mxn3 {
+ margin-left: -2rem;
+ margin-right: -2rem;
+ }
+ .sm-mxn4 {
+ margin-left: -4rem;
+ margin-right: -4rem;
+ }
+
+ .sm-ml-auto {
+ margin-left: auto;
+ }
+ .sm-mr-auto {
+ margin-right: auto;
+ }
+ .sm-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+
+@media (min-width: 52em) {
+ .md-m0 {
+ margin: 0;
+ }
+ .md-mt0 {
+ margin-top: 0;
+ }
+ .md-mr0 {
+ margin-right: 0;
+ }
+ .md-mb0 {
+ margin-bottom: 0;
+ }
+ .md-ml0 {
+ margin-left: 0;
+ }
+ .md-mx0 {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .md-my0 {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ .md-m1 {
+ margin: 0.5rem;
+ }
+ .md-mt1 {
+ margin-top: 0.5rem;
+ }
+ .md-mr1 {
+ margin-right: 0.5rem;
+ }
+ .md-mb1 {
+ margin-bottom: 0.5rem;
+ }
+ .md-ml1 {
+ margin-left: 0.5rem;
+ }
+ .md-mx1 {
+ margin-left: 0.5rem;
+ margin-right: 0.5rem;
+ }
+ .md-my1 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .md-m2 {
+ margin: 1rem;
+ }
+ .md-mt2 {
+ margin-top: 1rem;
+ }
+ .md-mr2 {
+ margin-right: 1rem;
+ }
+ .md-mb2 {
+ margin-bottom: 1rem;
+ }
+ .md-ml2 {
+ margin-left: 1rem;
+ }
+ .md-mx2 {
+ margin-left: 1rem;
+ margin-right: 1rem;
+ }
+ .md-my2 {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .md-m3 {
+ margin: 2rem;
+ }
+ .md-mt3 {
+ margin-top: 2rem;
+ }
+ .md-mr3 {
+ margin-right: 2rem;
+ }
+ .md-mb3 {
+ margin-bottom: 2rem;
+ }
+ .md-ml3 {
+ margin-left: 2rem;
+ }
+ .md-mx3 {
+ margin-left: 2rem;
+ margin-right: 2rem;
+ }
+ .md-my3 {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ }
+
+ .md-m4 {
+ margin: 4rem;
+ }
+ .md-mt4 {
+ margin-top: 4rem;
+ }
+ .md-mr4 {
+ margin-right: 4rem;
+ }
+ .md-mb4 {
+ margin-bottom: 4rem;
+ }
+ .md-ml4 {
+ margin-left: 4rem;
+ }
+ .md-mx4 {
+ margin-left: 4rem;
+ margin-right: 4rem;
+ }
+ .md-my4 {
+ margin-top: 4rem;
+ margin-bottom: 4rem;
+ }
+
+ .md-mxn1 {
+ margin-left: -0.5rem;
+ margin-right: -0.5rem;
+ }
+ .md-mxn2 {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+ .md-mxn3 {
+ margin-left: -2rem;
+ margin-right: -2rem;
+ }
+ .md-mxn4 {
+ margin-left: -4rem;
+ margin-right: -4rem;
+ }
+
+ .md-ml-auto {
+ margin-left: auto;
+ }
+ .md-mr-auto {
+ margin-right: auto;
+ }
+ .md-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+
+@media (min-width: 64em) {
+ .lg-m0 {
+ margin: 0;
+ }
+ .lg-mt0 {
+ margin-top: 0;
+ }
+ .lg-mr0 {
+ margin-right: 0;
+ }
+ .lg-mb0 {
+ margin-bottom: 0;
+ }
+ .lg-ml0 {
+ margin-left: 0;
+ }
+ .lg-mx0 {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .lg-my0 {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ .lg-m1 {
+ margin: 0.5rem;
+ }
+ .lg-mt1 {
+ margin-top: 0.5rem;
+ }
+ .lg-mr1 {
+ margin-right: 0.5rem;
+ }
+ .lg-mb1 {
+ margin-bottom: 0.5rem;
+ }
+ .lg-ml1 {
+ margin-left: 0.5rem;
+ }
+ .lg-mx1 {
+ margin-left: 0.5rem;
+ margin-right: 0.5rem;
+ }
+ .lg-my1 {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .lg-m2 {
+ margin: 1rem;
+ }
+ .lg-mt2 {
+ margin-top: 1rem;
+ }
+ .lg-mr2 {
+ margin-right: 1rem;
+ }
+ .lg-mb2 {
+ margin-bottom: 1rem;
+ }
+ .lg-ml2 {
+ margin-left: 1rem;
+ }
+ .lg-mx2 {
+ margin-left: 1rem;
+ margin-right: 1rem;
+ }
+ .lg-my2 {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ .lg-m3 {
+ margin: 2rem;
+ }
+ .lg-mt3 {
+ margin-top: 2rem;
+ }
+ .lg-mr3 {
+ margin-right: 2rem;
+ }
+ .lg-mb3 {
+ margin-bottom: 2rem;
+ }
+ .lg-ml3 {
+ margin-left: 2rem;
+ }
+ .lg-mx3 {
+ margin-left: 2rem;
+ margin-right: 2rem;
+ }
+ .lg-my3 {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ }
+
+ .lg-m4 {
+ margin: 4rem;
+ }
+ .lg-mt4 {
+ margin-top: 4rem;
+ }
+ .lg-mr4 {
+ margin-right: 4rem;
+ }
+ .lg-mb4 {
+ margin-bottom: 4rem;
+ }
+ .lg-ml4 {
+ margin-left: 4rem;
+ }
+ .lg-mx4 {
+ margin-left: 4rem;
+ margin-right: 4rem;
+ }
+ .lg-my4 {
+ margin-top: 4rem;
+ margin-bottom: 4rem;
+ }
+
+ .lg-mxn1 {
+ margin-left: -0.5rem;
+ margin-right: -0.5rem;
+ }
+ .lg-mxn2 {
+ margin-left: -1rem;
+ margin-right: -1rem;
+ }
+ .lg-mxn3 {
+ margin-left: -2rem;
+ margin-right: -2rem;
+ }
+ .lg-mxn4 {
+ margin-left: -4rem;
+ margin-right: -4rem;
+ }
+
+ .lg-ml-auto {
+ margin-left: auto;
+ }
+ .lg-mr-auto {
+ margin-right: auto;
+ }
+ .lg-mx-auto {
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
diff --git a/packages/dev-tools-pages/public/css/basscss_responsive_padding.css b/packages/dev-tools-pages/public/css/basscss_responsive_padding.css
new file mode 100644
index 000000000..e027c2d65
--- /dev/null
+++ b/packages/dev-tools-pages/public/css/basscss_responsive_padding.css
@@ -0,0 +1,134 @@
+/* Basscss Responsive Padding */
+/* Modified by Fabio Berger to include xs prefix */
+
+@media (max-width: 52em) { /* Modified by Fabio Berger to max-width from min-width */
+
+ .sm-p0 { padding: 0 }
+ .sm-pt0 { padding-top: 0 }
+ .sm-pr0 { padding-right: 0 }
+ .sm-pb0 { padding-bottom: 0 }
+ .sm-pl0 { padding-left: 0 }
+ .sm-px0 { padding-left: 0; padding-right: 0 }
+ .sm-py0 { padding-top: 0; padding-bottom: 0 }
+
+ .sm-p1 { padding: .5rem }
+ .sm-pt1 { padding-top: .5rem }
+ .sm-pr1 { padding-right: .5rem }
+ .sm-pb1 { padding-bottom: .5rem }
+ .sm-pl1 { padding-left: .5rem }
+ .sm-px1 { padding-left: .5rem; padding-right: .5rem }
+ .sm-py1 { padding-top: .5rem; padding-bottom: .5rem }
+
+ .sm-p2 { padding: 1rem }
+ .sm-pt2 { padding-top: 1rem }
+ .sm-pr2 { padding-right: 1rem }
+ .sm-pb2 { padding-bottom: 1rem }
+ .sm-pl2 { padding-left: 1rem }
+ .sm-px2 { padding-left: 1rem; padding-right: 1rem }
+ .sm-py2 { padding-top: 1rem; padding-bottom: 1rem }
+
+ .sm-p3 { padding: 2rem }
+ .sm-pt3 { padding-top: 2rem }
+ .sm-pr3 { padding-right: 2rem }
+ .sm-pb3 { padding-bottom: 2rem }
+ .sm-pl3 { padding-left: 2rem }
+ .sm-px3 { padding-left: 2rem; padding-right: 2rem }
+ .sm-py3 { padding-top: 2rem; padding-bottom: 2rem }
+
+ .sm-p4 { padding: 4rem }
+ .sm-pt4 { padding-top: 4rem }
+ .sm-pr4 { padding-right: 4rem }
+ .sm-pb4 { padding-bottom: 4rem }
+ .sm-pl4 { padding-left: 4rem }
+ .sm-px4 { padding-left: 4rem; padding-right: 4rem }
+ .sm-py4 { padding-top: 4rem; padding-bottom: 4rem }
+
+}
+
+@media (min-width: 52em) {
+
+ .md-p0 { padding: 0 }
+ .md-pt0 { padding-top: 0 }
+ .md-pr0 { padding-right: 0 }
+ .md-pb0 { padding-bottom: 0 }
+ .md-pl0 { padding-left: 0 }
+ .md-px0 { padding-left: 0; padding-right: 0 }
+ .md-py0 { padding-top: 0; padding-bottom: 0 }
+
+ .md-p1 { padding: .5rem }
+ .md-pt1 { padding-top: .5rem }
+ .md-pr1 { padding-right: .5rem }
+ .md-pb1 { padding-bottom: .5rem }
+ .md-pl1 { padding-left: .5rem }
+ .md-px1 { padding-left: .5rem; padding-right: .5rem }
+ .md-py1 { padding-top: .5rem; padding-bottom: .5rem }
+
+ .md-p2 { padding: 1rem }
+ .md-pt2 { padding-top: 1rem }
+ .md-pr2 { padding-right: 1rem }
+ .md-pb2 { padding-bottom: 1rem }
+ .md-pl2 { padding-left: 1rem }
+ .md-px2 { padding-left: 1rem; padding-right: 1rem }
+ .md-py2 { padding-top: 1rem; padding-bottom: 1rem }
+
+ .md-p3 { padding: 2rem }
+ .md-pt3 { padding-top: 2rem }
+ .md-pr3 { padding-right: 2rem }
+ .md-pb3 { padding-bottom: 2rem }
+ .md-pl3 { padding-left: 2rem }
+ .md-px3 { padding-left: 2rem; padding-right: 2rem }
+ .md-py3 { padding-top: 2rem; padding-bottom: 2rem }
+
+ .md-p4 { padding: 4rem }
+ .md-pt4 { padding-top: 4rem }
+ .md-pr4 { padding-right: 4rem }
+ .md-pb4 { padding-bottom: 4rem }
+ .md-pl4 { padding-left: 4rem }
+ .md-px4 { padding-left: 4rem; padding-right: 4rem }
+ .md-py4 { padding-top: 4rem; padding-bottom: 4rem }
+
+}
+
+@media (min-width: 64em) {
+
+ .lg-p0 { padding: 0 }
+ .lg-pt0 { padding-top: 0 }
+ .lg-pr0 { padding-right: 0 }
+ .lg-pb0 { padding-bottom: 0 }
+ .lg-pl0 { padding-left: 0 }
+ .lg-px0 { padding-left: 0; padding-right: 0 }
+ .lg-py0 { padding-top: 0; padding-bottom: 0 }
+
+ .lg-p1 { padding: .5rem }
+ .lg-pt1 { padding-top: .5rem }
+ .lg-pr1 { padding-right: .5rem }
+ .lg-pb1 { padding-bottom: .5rem }
+ .lg-pl1 { padding-left: .5rem }
+ .lg-px1 { padding-left: .5rem; padding-right: .5rem }
+ .lg-py1 { padding-top: .5rem; padding-bottom: .5rem }
+
+ .lg-p2 { padding: 1rem }
+ .lg-pt2 { padding-top: 1rem }
+ .lg-pr2 { padding-right: 1rem }
+ .lg-pb2 { padding-bottom: 1rem }
+ .lg-pl2 { padding-left: 1rem }
+ .lg-px2 { padding-left: 1rem; padding-right: 1rem }
+ .lg-py2 { padding-top: 1rem; padding-bottom: 1rem }
+
+ .lg-p3 { padding: 2rem }
+ .lg-pt3 { padding-top: 2rem }
+ .lg-pr3 { padding-right: 2rem }
+ .lg-pb3 { padding-bottom: 2rem }
+ .lg-pl3 { padding-left: 2rem }
+ .lg-px3 { padding-left: 2rem; padding-right: 2rem }
+ .lg-py3 { padding-top: 2rem; padding-bottom: 2rem }
+
+ .lg-p4 { padding: 4rem }
+ .lg-pt4 { padding-top: 4rem }
+ .lg-pr4 { padding-right: 4rem }
+ .lg-pb4 { padding-bottom: 4rem }
+ .lg-pl4 { padding-left: 4rem }
+ .lg-px4 { padding-left: 4rem; padding-right: 4rem }
+ .lg-py4 { padding-top: 4rem; padding-bottom: 4rem }
+
+}
diff --git a/packages/dev-tools-pages/public/css/basscss_responsive_type_scale.css b/packages/dev-tools-pages/public/css/basscss_responsive_type_scale.css
new file mode 100644
index 000000000..cae23b4e7
--- /dev/null
+++ b/packages/dev-tools-pages/public/css/basscss_responsive_type_scale.css
@@ -0,0 +1,35 @@
+/* Basscss Responsive Type Scale */
+/* Modified by Fabio Berger to include xs prefix */
+
+@media (max-width: 52em) { /* Modified by Fabio Berger to max-width from min-width */
+ .sm-h00 { font-size: 4rem }
+ .sm-h0 { font-size: 3rem }
+ .sm-h1 { font-size: 2rem }
+ .sm-h2 { font-size: 1.5rem }
+ .sm-h3 { font-size: 1.25rem }
+ .sm-h4 { font-size: 1rem }
+ .sm-h5 { font-size: .875rem }
+ .sm-h6 { font-size: .75rem }
+}
+
+@media (min-width: 52em) {
+ .md-h00 { font-size: 4rem }
+ .md-h0 { font-size: 3rem }
+ .md-h1 { font-size: 2rem }
+ .md-h2 { font-size: 1.5rem }
+ .md-h3 { font-size: 1.25rem }
+ .md-h4 { font-size: 1rem }
+ .md-h5 { font-size: .875rem }
+ .md-h6 { font-size: .75rem }
+}
+
+@media (min-width: 64em) {
+ .lg-h00 { font-size: 4rem }
+ .lg-h0 { font-size: 3rem }
+ .lg-h1 { font-size: 2rem }
+ .lg-h2 { font-size: 1.5rem }
+ .lg-h3 { font-size: 1.25rem }
+ .lg-h4 { font-size: 1rem }
+ .lg-h5 { font-size: .875rem }
+ .lg-h6 { font-size: .75rem }
+}
diff --git a/packages/dev-tools-pages/public/images/favicon/favicon-2-16x16.png b/packages/dev-tools-pages/public/images/favicon/favicon-2-16x16.png
new file mode 100755
index 000000000..68c493c4f
--- /dev/null
+++ b/packages/dev-tools-pages/public/images/favicon/favicon-2-16x16.png
Binary files differ
diff --git a/packages/dev-tools-pages/public/images/favicon/favicon-2-32x32.png b/packages/dev-tools-pages/public/images/favicon/favicon-2-32x32.png
new file mode 100755
index 000000000..a5abb0eb3
--- /dev/null
+++ b/packages/dev-tools-pages/public/images/favicon/favicon-2-32x32.png
Binary files differ
diff --git a/packages/dev-tools-pages/public/images/favicon/favicon.ico b/packages/dev-tools-pages/public/images/favicon/favicon.ico
new file mode 100755
index 000000000..b7ada2a1c
--- /dev/null
+++ b/packages/dev-tools-pages/public/images/favicon/favicon.ico
Binary files differ
diff --git a/packages/dev-tools-pages/public/index.html b/packages/dev-tools-pages/public/index.html
new file mode 100644
index 000000000..f62d7b255
--- /dev/null
+++ b/packages/dev-tools-pages/public/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="description" content="" />
+ <meta property="og:type" content="website" />
+ <meta property="og:title" content="0x" />
+ <meta property="og:description" content="" />
+ <meta property="og:image" content="/images/og_image.png" />
+ <title>0x: The Protocol for Trading Tokens</title>
+ <link rel="icon" type="image/png" href="/images/favicon/favicon-2-32x32.png" sizes="32x32" />
+ <link rel="icon" type="image/png" href="/images/favicon/favicon-2-16x16.png" sizes="16x16" />
+ <link rel="stylesheet" href="/css/basscss_responsive_custom.css">
+ <link rel="stylesheet" href="/css/basscss_responsive_padding.css">
+ <link rel="stylesheet" href="/css/basscss_responsive_margin.css">
+ <link rel="stylesheet" href="/css/basscss_responsive_type_scale.css">
+</head>
+
+<body style="margin: 0px; min-width: 355px;">
+ <div id="app"></div>
+ <script type="text/javascript" crossorigin="anonymous" src="/bundle.js" charset="utf-8"></script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/packages/dev-tools-pages/ts/components/meta_tags.tsx b/packages/dev-tools-pages/ts/components/meta_tags.tsx
new file mode 100644
index 000000000..f6c43d23f
--- /dev/null
+++ b/packages/dev-tools-pages/ts/components/meta_tags.tsx
@@ -0,0 +1,25 @@
+import * as React from 'react';
+import { Helmet } from 'react-helmet';
+
+export interface MetaTagsProps {
+ title: string;
+ description: string;
+ imgSrc?: string;
+}
+
+export const MetaTags: React.StatelessComponent<MetaTagsProps> = ({ title, description, imgSrc }) => (
+ <Helmet>
+ <title>{title}</title>
+ <meta name="description" content={description} />
+ <meta property="og:title" content={title} />
+ <meta property="og:description" content={description} />
+ <meta property="og:type" content="website" />
+ <meta property="og:image" content={imgSrc} />
+ <meta name="twitter:site" content="@0xproject" />
+ <meta name="twitter:image" content={imgSrc} />
+ </Helmet>
+);
+
+MetaTags.defaultProps = {
+ imgSrc: '/images/og_image.png',
+};
diff --git a/packages/dev-tools-pages/ts/components/ui/button.tsx b/packages/dev-tools-pages/ts/components/ui/button.tsx
new file mode 100644
index 000000000..754eca40e
--- /dev/null
+++ b/packages/dev-tools-pages/ts/components/ui/button.tsx
@@ -0,0 +1,59 @@
+import { darken, saturate } from 'polished';
+import * as React from 'react';
+import styled from 'styled-components';
+
+/**
+ * AN EXAMPLE OF HOW TO CREATE A STYLED COMPONENT USING STYLED-COMPONENTS
+ * SEE: https://www.styled-components.com/docs/basics#coming-from-css
+ */
+export interface ButtonProps {
+ backgroundColor?: string;
+ borderColor?: string;
+ width?: string;
+ padding?: string;
+ type?: string;
+ isDisabled?: boolean;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ className?: string;
+}
+
+const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
+ <button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}>
+ {children}
+ </button>
+);
+
+const darkenOnHoverAmount = 0.1;
+const darkenOnActiveAmount = 0.2;
+const saturateOnFocusAmount = 0.2;
+export const Button = styled(PlainButton)`
+ cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
+ transition: background-color, opacity 0.5s ease;
+ padding: ${props => props.padding};
+ border-radius: 3px;
+ outline: none;
+ width: ${props => props.width};
+ background-color: ${props => (props.backgroundColor ? props.backgroundColor : 'none')};
+ border: ${props => (props.borderColor ? `1px solid ${props.backgroundColor}` : 'none')};
+ &:hover {
+ background-color: ${props =>
+ !props.isDisabled ? darken(darkenOnHoverAmount, props.backgroundColor) : ''} !important;
+ }
+ &:active {
+ background-color: ${props => (!props.isDisabled ? darken(darkenOnActiveAmount, props.backgroundColor) : '')};
+ }
+ &:disabled {
+ opacity: 0.5;
+ }
+ &:focus {
+ background-color: ${props => saturate(saturateOnFocusAmount, props.backgroundColor)};
+ }
+`;
+
+Button.defaultProps = {
+ backgroundColor: 'red',
+ width: 'auto',
+ isDisabled: false,
+ padding: '1em 2.2em',
+};
+Button.displayName = 'Button';
diff --git a/packages/dev-tools-pages/ts/components/ui/container.tsx b/packages/dev-tools-pages/ts/components/ui/container.tsx
new file mode 100644
index 000000000..f2ae68b70
--- /dev/null
+++ b/packages/dev-tools-pages/ts/components/ui/container.tsx
@@ -0,0 +1,55 @@
+import * as React from 'react';
+
+type StringOrNum = string | number;
+
+export type ContainerTag = 'div' | 'span';
+
+export interface ContainerProps {
+ marginTop?: StringOrNum;
+ marginBottom?: StringOrNum;
+ marginRight?: StringOrNum;
+ marginLeft?: StringOrNum;
+ padding?: StringOrNum;
+ paddingTop?: StringOrNum;
+ paddingBottom?: StringOrNum;
+ paddingRight?: StringOrNum;
+ paddingLeft?: StringOrNum;
+ backgroundColor?: string;
+ borderRadius?: StringOrNum;
+ maxWidth?: StringOrNum;
+ maxHeight?: StringOrNum;
+ width?: StringOrNum;
+ height?: StringOrNum;
+ minWidth?: StringOrNum;
+ minHeight?: StringOrNum;
+ isHidden?: boolean;
+ className?: string;
+ position?: 'absolute' | 'fixed' | 'relative' | 'unset';
+ display?: 'inline-block' | 'block' | 'inline-flex' | 'inline';
+ top?: string;
+ left?: string;
+ right?: string;
+ bottom?: string;
+ zIndex?: number;
+ Tag?: ContainerTag;
+ cursor?: string;
+ id?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ overflowX?: 'scroll' | 'hidden' | 'auto' | 'visible';
+}
+
+export const Container: React.StatelessComponent<ContainerProps> = props => {
+ const { children, className, Tag, isHidden, id, onClick, ...style } = props;
+ const visibility = isHidden ? 'hidden' : undefined;
+ return (
+ <Tag id={id} style={{ ...style, visibility }} className={className} onClick={onClick}>
+ {children}
+ </Tag>
+ );
+};
+
+Container.defaultProps = {
+ Tag: 'div',
+};
+
+Container.displayName = 'Container';
diff --git a/packages/dev-tools-pages/ts/components/ui/text.tsx b/packages/dev-tools-pages/ts/components/ui/text.tsx
new file mode 100644
index 000000000..8e314beae
--- /dev/null
+++ b/packages/dev-tools-pages/ts/components/ui/text.tsx
@@ -0,0 +1,74 @@
+import { colors } from '@0xproject/react-shared';
+import { darken } from 'polished';
+import * as React from 'react';
+import styled from 'styled-components';
+
+export type TextTag = 'p' | 'div' | 'span' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'i';
+
+export interface TextProps {
+ className?: string;
+ Tag?: TextTag;
+ fontSize?: string;
+ fontFamily?: string;
+ fontStyle?: string;
+ fontColor?: string;
+ lineHeight?: string;
+ minHeight?: string;
+ center?: boolean;
+ fontWeight?: number | string;
+ textDecorationLine?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ hoverColor?: string;
+ noWrap?: boolean;
+ display?: string;
+}
+
+const PlainText: React.StatelessComponent<TextProps> = ({ children, className, onClick, Tag }) => (
+ <Tag className={className} onClick={onClick}>
+ {children}
+ </Tag>
+);
+
+export const Text = styled(PlainText)`
+ font-family: ${props => props.fontFamily};
+ font-style: ${props => props.fontStyle};
+ font-weight: ${props => props.fontWeight};
+ font-size: ${props => props.fontSize};
+ text-decoration-line: ${props => props.textDecorationLine};
+ ${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
+ ${props => (props.center ? 'text-align: center' : '')};
+ color: ${props => props.fontColor};
+ ${props => (props.minHeight ? `min-height: ${props.minHeight}` : '')};
+ ${props => (props.onClick ? 'cursor: pointer' : '')};
+ transition: color 0.5s ease;
+ ${props => (props.noWrap ? 'white-space: nowrap' : '')};
+ ${props => (props.display ? `display: ${props.display}` : '')};
+ &:hover {
+ ${props => (props.onClick ? `color: ${props.hoverColor || darken(0.3, props.fontColor || 'black')}` : '')};
+ }
+`;
+
+Text.defaultProps = {
+ fontFamily: 'Roboto',
+ fontStyle: 'normal',
+ fontWeight: 400,
+ fontColor: colors.black,
+ fontSize: '15px',
+ lineHeight: '1.5em',
+ textDecorationLine: 'none',
+ Tag: 'div',
+ noWrap: false,
+};
+
+Text.displayName = 'Text';
+
+export const Title: React.StatelessComponent<TextProps> = props => <Text {...props} />;
+
+Title.defaultProps = {
+ Tag: 'h2',
+ fontSize: '20px',
+ fontWeight: 600,
+ fontColor: colors.black,
+};
+
+Title.displayName = 'Title';
diff --git a/packages/dev-tools-pages/ts/globals.d.ts b/packages/dev-tools-pages/ts/globals.d.ts
new file mode 100644
index 000000000..d0890161c
--- /dev/null
+++ b/packages/dev-tools-pages/ts/globals.d.ts
@@ -0,0 +1,9 @@
+declare module 'whatwg-fetch';
+declare module 'react-document-title';
+
+declare module '*.json' {
+ const json: any;
+ /* tslint:disable */
+ export default json;
+ /* tslint:enable */
+}
diff --git a/packages/dev-tools-pages/ts/index.tsx b/packages/dev-tools-pages/ts/index.tsx
new file mode 100644
index 000000000..4591c6d76
--- /dev/null
+++ b/packages/dev-tools-pages/ts/index.tsx
@@ -0,0 +1,17 @@
+import * as React from 'react';
+import { render } from 'react-dom';
+import { MetaTags } from 'ts/components/meta_tags';
+import { Landing } from 'ts/pages/landing';
+
+import 'basscss/css/basscss.css';
+
+const DOCUMENT_TITLE = '';
+const DOCUMENT_DESCRIPTION = '';
+
+render(
+ <div>
+ <MetaTags title={DOCUMENT_TITLE} description={DOCUMENT_DESCRIPTION} />
+ <Landing />
+ </div>,
+ document.getElementById('app'),
+);
diff --git a/packages/dev-tools-pages/ts/pages/landing.tsx b/packages/dev-tools-pages/ts/pages/landing.tsx
new file mode 100644
index 000000000..a70a9de46
--- /dev/null
+++ b/packages/dev-tools-pages/ts/pages/landing.tsx
@@ -0,0 +1,27 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Button } from '../components/ui/button';
+import { Container } from '../components/ui/container';
+import { Text } from '../components/ui/text';
+
+interface LandingProps {}
+
+interface LandingState {}
+
+export class Landing extends React.Component<LandingProps, LandingState> {
+ constructor(props: LandingProps) {
+ super(props);
+ }
+ public render(): React.ReactNode {
+ return (
+ <Container id="landing" className="clearfix">
+ <Container className="mx-auto p4" width="200px">
+ <Button>
+ <Text fontColor="white">Click me!</Text>
+ </Button>
+ </Container>
+ </Container>
+ );
+ }
+}
diff --git a/packages/dev-tools-pages/ts/utils/utils.ts b/packages/dev-tools-pages/ts/utils/utils.ts
new file mode 100644
index 000000000..b274706a2
--- /dev/null
+++ b/packages/dev-tools-pages/ts/utils/utils.ts
@@ -0,0 +1,32 @@
+import * as bowser from 'bowser';
+import * as _ from 'lodash';
+
+export const utils = {
+ getColSize(items: number): number {
+ const bassCssGridSize = 12; // Source: http://basscss.com/#basscss-grid
+ const colSize = bassCssGridSize / items;
+ if (!_.isInteger(colSize)) {
+ throw new Error(`Number of cols must be divisible by ${bassCssGridSize}`);
+ }
+ return colSize;
+ },
+ getCurrentBaseUrl(): string {
+ const port = window.location.port;
+ const hasPort = !_.isUndefined(port);
+ const baseUrl = `https://${window.location.hostname}${hasPort ? `:${port}` : ''}`;
+ return baseUrl;
+ },
+ onPageLoadPromise: new Promise<void>((resolve, _reject) => {
+ if (document.readyState === 'complete') {
+ resolve();
+ return;
+ }
+ window.onload = () => resolve();
+ }),
+ openUrl(url: string): void {
+ window.open(url, '_blank');
+ },
+ isMobileOperatingSystem(): boolean {
+ return bowser.mobile;
+ },
+};
diff --git a/packages/dev-tools-pages/tsconfig.json b/packages/dev-tools-pages/tsconfig.json
new file mode 100644
index 000000000..6421cd459
--- /dev/null
+++ b/packages/dev-tools-pages/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "extends": "../../tsconfig",
+ "compilerOptions": {
+ "allowSyntheticDefaultImports": true,
+ "outDir": "./transpiled/",
+ "jsx": "react",
+ "baseUrl": "./",
+ "allowJs": true,
+ "strictNullChecks": false,
+ "noImplicitThis": false,
+ // tsconfig.json at the monorepo root contains some options required for
+ // project references which do not work for website. We override those
+ // options here.
+ "declaration": false,
+ "declarationMap": false,
+ "composite": false,
+ "paths": {
+ "*": ["node_modules/@types/*", "*"]
+ }
+ },
+ "include": ["./ts/**/*"]
+}
diff --git a/packages/dev-tools-pages/tslint.json b/packages/dev-tools-pages/tslint.json
new file mode 100644
index 000000000..b55ffe90f
--- /dev/null
+++ b/packages/dev-tools-pages/tslint.json
@@ -0,0 +1,10 @@
+{
+ "extends": ["@0xproject/tslint-config"],
+ "rules": {
+ "no-implicit-dependencies": false,
+ "no-object-literal-type-assertion": false,
+ "completed-docs": false,
+ "prefer-function-over-method": false,
+ "custom-no-magic-numbers": false
+ }
+}
diff --git a/packages/dev-tools-pages/webpack.config.js b/packages/dev-tools-pages/webpack.config.js
new file mode 100644
index 000000000..6dfcf74e7
--- /dev/null
+++ b/packages/dev-tools-pages/webpack.config.js
@@ -0,0 +1,86 @@
+const path = require('path');
+const webpack = require('webpack');
+const TerserPlugin = require('terser-webpack-plugin');
+const childProcess = require('child_process');
+
+const config = {
+ entry: ['./ts/index.tsx'],
+ output: {
+ path: path.join(__dirname, '/public'),
+ filename: 'bundle.js',
+ chunkFilename: 'bundle-[name].js',
+ publicPath: '/',
+ },
+ devtool: 'source-map',
+ resolve: {
+ modules: [path.join(__dirname, '/ts'), 'node_modules'],
+ extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
+ alias: {
+ ts: path.join(__dirname, '/ts'),
+ less: path.join(__dirname, '/less'),
+ },
+ },
+ module: {
+ rules: [
+ {
+ test: /\.js$/,
+ loader: 'source-map-loader',
+ exclude: [
+ // instead of /\/node_modules\//
+ path.join(process.cwd(), 'node_modules'),
+ path.join(process.cwd(), '../..', 'node_modules'),
+ ],
+ },
+ {
+ test: /\.tsx?$/,
+ loader: 'awesome-typescript-loader',
+ },
+ {
+ test: /\.md$/,
+ use: 'raw-loader',
+ },
+ {
+ test: /\.less$/,
+ loader: 'style-loader!css-loader!less-loader',
+ exclude: /node_modules/,
+ },
+ {
+ test: /\.css$/,
+ loaders: ['style-loader', 'css-loader'],
+ },
+ ],
+ },
+ optimization: {
+ minimizer: [
+ new TerserPlugin({
+ sourceMap: true,
+ }),
+ ],
+ },
+ devServer: {
+ port: 3572,
+ disableHostCheck: true,
+ },
+};
+
+module.exports = (_env, argv) => {
+ let plugins = [];
+ if (argv.mode === 'development') {
+ config.mode = 'development';
+ } else {
+ config.mode = 'production';
+ plugins = plugins.concat([
+ new webpack.DefinePlugin({
+ 'process.env': {
+ NODE_ENV: JSON.stringify(process.env.NODE_ENV),
+ },
+ }),
+ ]);
+ }
+ console.log('i ï½¢atlï½£: Mode: ', config.mode);
+
+ config.plugins = plugins;
+ console.log('i ï½¢atlï½£: Plugin Count: ', config.plugins.length);
+
+ return config;
+};
diff --git a/packages/ethereum-types/CHANGELOG.json b/packages/ethereum-types/CHANGELOG.json
index e955f4d04..60fb8c806 100644
--- a/packages/ethereum-types/CHANGELOG.json
+++ b/packages/ethereum-types/CHANGELOG.json
@@ -1,5 +1,14 @@
[
{
+ "version": "1.1.0",
+ "changes": [
+ {
+ "note": "Add `JSONRPCResponseError` and error field on `JSONRPCResponsePayload`.",
+ "pr": 1102
+ }
+ ]
+ },
+ {
"timestamp": 1538693146,
"version": "1.0.11",
"changes": [
diff --git a/packages/ethereum-types/src/index.ts b/packages/ethereum-types/src/index.ts
index 7e8b9de3e..ddd472010 100644
--- a/packages/ethereum-types/src/index.ts
+++ b/packages/ethereum-types/src/index.ts
@@ -113,10 +113,16 @@ export interface JSONRPCRequestPayload {
jsonrpc: string;
}
+export interface JSONRPCResponseError {
+ message: string;
+ code: number;
+}
+
export interface JSONRPCResponsePayload {
result: any;
id: number;
jsonrpc: string;
+ error?: JSONRPCResponseError;
}
export interface AbstractBlock {
diff --git a/packages/fill-scenarios/package.json b/packages/fill-scenarios/package.json
index 0616454d6..dd6ede3e0 100644
--- a/packages/fill-scenarios/package.json
+++ b/packages/fill-scenarios/package.json
@@ -45,7 +45,7 @@
"@0xproject/utils": "^2.0.2",
"@0xproject/web3-wrapper": "^3.0.3",
"ethereum-types": "^1.0.11",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"lodash": "^4.17.5"
},
"publishConfig": {
diff --git a/packages/instant/package.json b/packages/instant/package.json
index 26c370e4c..ff40ba2ea 100644
--- a/packages/instant/package.json
+++ b/packages/instant/package.json
@@ -43,15 +43,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md",
"dependencies": {
- "@0xproject/connect": "^2.0.4",
+ "@0xproject/asset-buyer": "^2.0.0",
"@0xproject/types": "^1.1.4",
"@0xproject/typescript-typings": "^2.0.2",
- "@0xproject/utils": "^1.0.11",
+ "@0xproject/utils": "^2.0.2",
"@0xproject/web3-wrapper": "^3.0.3",
"ethereum-types": "^1.0.11",
"lodash": "^4.17.10",
+ "polished": "^2.2.0",
"react": "^16.5.2",
- "react-dom": "^16.5.2"
+ "react-dom": "^16.5.2",
+ "react-redux": "^5.0.7",
+ "redux": "^4.0.0",
+ "styled-components": "^3.4.9"
},
"devDependencies": {
"@0xproject/tslint-config": "^1.0.8",
@@ -59,8 +63,10 @@
"@types/enzyme-adapter-react-16": "^1.0.3",
"@types/lodash": "^4.14.116",
"@types/node": "*",
- "@types/react": "16.4.7",
+ "@types/react": "^16.4.16",
"@types/react-dom": "^16.0.8",
+ "@types/react-redux": "^6.0.9",
+ "@types/redux": "^3.6.0",
"awesome-typescript-loader": "^5.2.1",
"copyfiles": "^1.2.0",
"enzyme": "^3.6.0",
diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html
index 45968a3c9..fb041745e 100644
--- a/packages/instant/public/index.html
+++ b/packages/instant/public/index.html
@@ -6,6 +6,19 @@
<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>
+ <style>
+ #zeroExInstantContainer {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ }
+
+ body {
+ margin: 0;
+ background-color: rgba(0, 0, 0, 0.2);
+ }
+ </style>
</head>
<body>
diff --git a/packages/instant/src/components/amount_input.tsx b/packages/instant/src/components/amount_input.tsx
new file mode 100644
index 000000000..38810063d
--- /dev/null
+++ b/packages/instant/src/components/amount_input.tsx
@@ -0,0 +1,47 @@
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { Container, Input } from './ui';
+
+export interface AmountInputProps {
+ fontColor?: ColorOption;
+ fontSize?: string;
+ value?: BigNumber;
+ onChange?: (value?: BigNumber) => void;
+}
+
+export class AmountInput extends React.Component<AmountInputProps> {
+ public render(): React.ReactNode {
+ const { fontColor, fontSize, value } = this.props;
+ return (
+ <Container borderBottom="1px solid rgba(255,255,255,0.3)" display="inline-block">
+ <Input
+ fontColor={fontColor}
+ fontSize={fontSize}
+ onChange={this._handleChange}
+ value={!_.isUndefined(value) ? value.toString() : ''}
+ placeholder="0.00"
+ width="2em"
+ />
+ </Container>
+ );
+ }
+ private readonly _handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
+ const value = event.target.value;
+ let bigNumberValue;
+ if (!_.isEmpty(value)) {
+ try {
+ bigNumberValue = new BigNumber(event.target.value);
+ } catch {
+ // We don't want to allow values that can't be a BigNumber, so don't even call onChange.
+ return;
+ }
+ }
+ if (!_.isUndefined(this.props.onChange)) {
+ this.props.onChange(bigNumberValue);
+ }
+ };
+}
diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx
new file mode 100644
index 000000000..5a32b9575
--- /dev/null
+++ b/packages/instant/src/components/buy_button.tsx
@@ -0,0 +1,19 @@
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { Button, Container, Text } from './ui';
+
+export interface BuyButtonProps {}
+
+export const BuyButton: React.StatelessComponent<BuyButtonProps> = props => (
+ <Container padding="20px" width="100%">
+ <Button width="100%">
+ <Text fontColor={ColorOption.white} fontWeight={600} fontSize="20px">
+ Buy
+ </Text>
+ </Button>
+ </Container>
+);
+
+BuyButton.displayName = 'BuyButton';
diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx
new file mode 100644
index 000000000..be0414b8d
--- /dev/null
+++ b/packages/instant/src/components/instant_heading.tsx
@@ -0,0 +1,45 @@
+import * as React from 'react';
+
+import { SelectedAssetAmountInput } from '../containers/selected_asset_amount_input';
+import { ColorOption } from '../style/theme';
+
+import { Container, Flex, Text } from './ui';
+
+export interface InstantHeadingProps {}
+
+export const InstantHeading: React.StatelessComponent<InstantHeadingProps> = props => (
+ <Container backgroundColor={ColorOption.primaryColor} padding="20px" width="100%" borderRadius="3px 3px 0px 0px">
+ <Container marginBottom="5px">
+ <Text
+ letterSpacing="1px"
+ fontColor={ColorOption.white}
+ opacity={0.7}
+ fontWeight={500}
+ textTransform="uppercase"
+ fontSize="12px"
+ >
+ I want to buy
+ </Text>
+ </Container>
+ <Flex direction="row" justify="space-between">
+ <Container>
+ <SelectedAssetAmountInput fontSize="45px" />
+ <Container display="inline-block" marginLeft="10px">
+ <Text fontSize="45px" fontColor={ColorOption.white} textTransform="uppercase">
+ rep
+ </Text>
+ </Container>
+ </Container>
+ <Flex direction="column" justify="space-between">
+ <Container marginBottom="5px">
+ <Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}>
+ 0 ETH
+ </Text>
+ </Container>
+ <Text fontSize="16px" fontColor={ColorOption.white} opacity={0.7}>
+ $0.00
+ </Text>
+ </Flex>
+ </Flex>
+ </Container>
+);
diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx
new file mode 100644
index 000000000..dbf2c1f0b
--- /dev/null
+++ b/packages/instant/src/components/order_details.tsx
@@ -0,0 +1,62 @@
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { Container, Flex, Text } from './ui';
+
+export interface OrderDetailsProps {}
+
+export const OrderDetails: React.StatelessComponent<OrderDetailsProps> = props => (
+ <Container padding="20px" width="100%">
+ <Container marginBottom="10px">
+ <Text
+ letterSpacing="1px"
+ fontColor={ColorOption.primaryColor}
+ fontWeight={600}
+ textTransform="uppercase"
+ fontSize="14px"
+ >
+ Order Details
+ </Text>
+ </Container>
+ <OrderDetailsRow name="Token Price" primaryValue=".013 ETH" secondaryValue="$24.32" />
+ <OrderDetailsRow name="Fee" primaryValue=".005 ETH" secondaryValue="$1.04" />
+ <OrderDetailsRow name="Total Cost" primaryValue="1.66 ETH" secondaryValue="$589.56" shouldEmphasize={true} />
+ </Container>
+);
+
+OrderDetails.displayName = 'OrderDetails';
+
+export interface OrderDetailsRowProps {
+ name: string;
+ primaryValue: string;
+ secondaryValue: string;
+ shouldEmphasize?: boolean;
+}
+
+export const OrderDetailsRow: React.StatelessComponent<OrderDetailsRowProps> = props => {
+ const fontWeight = props.shouldEmphasize ? 700 : 400;
+ return (
+ <Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
+ <Flex justify="space-between">
+ <Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
+ {props.name}
+ </Text>
+ <Container>
+ <Container marginRight="3px" display="inline-block">
+ <Text fontColor={ColorOption.lightGrey}>({props.secondaryValue}) </Text>
+ </Container>
+ <Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
+ {props.primaryValue}
+ </Text>
+ </Container>
+ </Flex>
+ </Container>
+ );
+};
+
+OrderDetailsRow.defaultProps = {
+ shouldEmphasize: false,
+};
+
+OrderDetailsRow.displayName = 'OrderDetailsRow';
diff --git a/packages/instant/src/components/ui/button.tsx b/packages/instant/src/components/ui/button.tsx
new file mode 100644
index 000000000..1fcb2591c
--- /dev/null
+++ b/packages/instant/src/components/ui/button.tsx
@@ -0,0 +1,60 @@
+import { darken, saturate } from 'polished';
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+
+export interface ButtonProps {
+ backgroundColor?: ColorOption;
+ borderColor?: ColorOption;
+ width?: string;
+ padding?: string;
+ type?: string;
+ isDisabled?: boolean;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ className?: string;
+}
+
+const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => (
+ <button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}>
+ {children}
+ </button>
+);
+
+const darkenOnHoverAmount = 0.1;
+const darkenOnActiveAmount = 0.2;
+const saturateOnFocusAmount = 0.2;
+export const Button = styled(PlainButton)`
+ cursor: ${props => (props.isDisabled ? 'default' : 'pointer')};
+ transition: background-color, opacity 0.5s ease;
+ padding: ${props => props.padding};
+ border-radius: 3px;
+ outline: none;
+ width: ${props => props.width};
+ background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
+ border: ${props => (props.borderColor ? `1px solid ${props.theme[props.borderColor]}` : 'none')};
+ &:hover {
+ background-color: ${props =>
+ !props.isDisabled
+ ? darken(darkenOnHoverAmount, props.theme[props.backgroundColor || 'white'])
+ : ''} !important;
+ }
+ &:active {
+ background-color: ${props =>
+ !props.isDisabled ? darken(darkenOnActiveAmount, props.theme[props.backgroundColor || 'white']) : ''};
+ }
+ &:disabled {
+ opacity: 0.5;
+ }
+ &:focus {
+ background-color: ${props => saturate(saturateOnFocusAmount, props.theme[props.backgroundColor || 'white'])};
+ }
+`;
+
+Button.defaultProps = {
+ backgroundColor: ColorOption.primaryColor,
+ width: 'auto',
+ isDisabled: false,
+ padding: '1em 2.2em',
+};
+
+Button.displayName = 'Button';
diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx
new file mode 100644
index 000000000..c45f6e5e9
--- /dev/null
+++ b/packages/instant/src/components/ui/container.tsx
@@ -0,0 +1,64 @@
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+import { cssRuleIfExists } from '../../style/util';
+
+export interface ContainerProps {
+ display?: string;
+ position?: string;
+ top?: string;
+ right?: string;
+ bottom?: string;
+ left?: string;
+ width?: string;
+ maxWidth?: string;
+ margin?: string;
+ marginTop?: string;
+ marginRight?: string;
+ marginBottom?: string;
+ marginLeft?: string;
+ padding?: string;
+ borderRadius?: string;
+ border?: string;
+ borderColor?: ColorOption;
+ borderTop?: string;
+ borderBottom?: string;
+ className?: string;
+ backgroundColor?: ColorOption;
+ hasBoxShadow?: boolean;
+}
+
+const PlainContainer: React.StatelessComponent<ContainerProps> = ({ children, className }) => (
+ <div className={className}>{children}</div>
+);
+
+export const Container = styled(PlainContainer)`
+ box-sizing: border-box;
+ ${props => cssRuleIfExists(props, 'display')}
+ ${props => cssRuleIfExists(props, 'position')}
+ ${props => cssRuleIfExists(props, 'top')}
+ ${props => cssRuleIfExists(props, 'right')}
+ ${props => cssRuleIfExists(props, 'bottom')}
+ ${props => cssRuleIfExists(props, 'left')}
+ ${props => cssRuleIfExists(props, 'width')}
+ ${props => cssRuleIfExists(props, 'max-width')}
+ ${props => cssRuleIfExists(props, 'margin')}
+ ${props => cssRuleIfExists(props, 'margin-top')}
+ ${props => cssRuleIfExists(props, 'margin-right')}
+ ${props => cssRuleIfExists(props, 'margin-bottom')}
+ ${props => cssRuleIfExists(props, 'margin-left')}
+ ${props => cssRuleIfExists(props, 'padding')}
+ ${props => cssRuleIfExists(props, 'border-radius')}
+ ${props => cssRuleIfExists(props, 'border')}
+ ${props => cssRuleIfExists(props, 'border-top')}
+ ${props => cssRuleIfExists(props, 'border-bottom')}
+ ${props => (props.hasBoxShadow ? `box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)` : '')};
+ background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
+ border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')};
+`;
+
+Container.defaultProps = {
+ display: 'block',
+};
+
+Container.displayName = 'Container';
diff --git a/packages/instant/src/components/ui/flex.tsx b/packages/instant/src/components/ui/flex.tsx
new file mode 100644
index 000000000..327e91926
--- /dev/null
+++ b/packages/instant/src/components/ui/flex.tsx
@@ -0,0 +1,37 @@
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+import { cssRuleIfExists } from '../../style/util';
+
+export interface FlexProps {
+ direction?: 'row' | 'column';
+ flexWrap?: 'wrap' | 'nowrap';
+ justify?: 'flex-start' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'flex-end';
+ align?: 'flex-start' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'flex-end';
+ width?: string;
+ backgroundColor?: ColorOption;
+ className?: string;
+}
+
+const PlainFlex: React.StatelessComponent<FlexProps> = ({ children, className }) => (
+ <div className={className}>{children}</div>
+);
+
+export const Flex = styled(PlainFlex)`
+ display: flex;
+ flex-direction: ${props => props.direction};
+ flex-wrap: ${props => props.flexWrap};
+ justify-content: ${props => props.justify};
+ align-items: ${props => props.align};
+ ${props => cssRuleIfExists(props, 'width')}
+ background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')};
+`;
+
+Flex.defaultProps = {
+ direction: 'row',
+ flexWrap: 'nowrap',
+ justify: 'center',
+ align: 'center',
+};
+
+Flex.displayName = 'Flex';
diff --git a/packages/instant/src/components/ui/index.ts b/packages/instant/src/components/ui/index.ts
new file mode 100644
index 000000000..bf5f6c700
--- /dev/null
+++ b/packages/instant/src/components/ui/index.ts
@@ -0,0 +1,5 @@
+export { Text, Title } from './text';
+export { Button } from './button';
+export { Flex } from './flex';
+export { Container } from './container';
+export { Input } from './input';
diff --git a/packages/instant/src/components/ui/input.tsx b/packages/instant/src/components/ui/input.tsx
new file mode 100644
index 000000000..f8c6b6ef6
--- /dev/null
+++ b/packages/instant/src/components/ui/input.tsx
@@ -0,0 +1,40 @@
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+
+export interface InputProps {
+ className?: string;
+ value?: string;
+ width?: string;
+ fontSize?: string;
+ fontColor?: ColorOption;
+ placeholder?: string;
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
+}
+
+const PlainInput: React.StatelessComponent<InputProps> = ({ value, className, placeholder, onChange }) => (
+ <input className={className} value={value} onChange={onChange} placeholder={placeholder} />
+);
+
+export const Input = styled(PlainInput)`
+ font-size: ${props => props.fontSize};
+ width: ${props => props.width};
+ padding: 0.1em 0em;
+ font-family: 'Inter UI';
+ color: ${props => props.theme[props.fontColor || 'white']};
+ background: transparent;
+ outline: none;
+ border: none;
+ &::placeholder {
+ color: ${props => props.theme[props.fontColor || 'white']};
+ opacity: 0.5;
+ }
+`;
+
+Input.defaultProps = {
+ width: 'auto',
+ fontColor: ColorOption.white,
+ fontSize: '12px',
+};
+
+Input.displayName = 'Input';
diff --git a/packages/instant/src/components/ui/text.tsx b/packages/instant/src/components/ui/text.tsx
new file mode 100644
index 000000000..9fb8ea26f
--- /dev/null
+++ b/packages/instant/src/components/ui/text.tsx
@@ -0,0 +1,80 @@
+import { darken } from 'polished';
+import * as React from 'react';
+
+import { ColorOption, styled } from '../../style/theme';
+
+export interface TextProps {
+ fontColor?: ColorOption;
+ fontFamily?: string;
+ fontStyle?: string;
+ fontSize?: string;
+ opacity?: number;
+ letterSpacing?: string;
+ textTransform?: string;
+ lineHeight?: string;
+ className?: string;
+ minHeight?: string;
+ center?: boolean;
+ fontWeight?: number | string;
+ textDecorationLine?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+ hoverColor?: string;
+ noWrap?: boolean;
+ display?: string;
+}
+
+const PlainText: React.StatelessComponent<TextProps> = ({ children, className, onClick }) => (
+ <div className={className} onClick={onClick}>
+ {children}
+ </div>
+);
+
+const darkenOnHoverAmount = 0.3;
+export const Text = styled(PlainText)`
+ font-family: ${props => props.fontFamily};
+ font-style: ${props => props.fontStyle};
+ font-weight: ${props => props.fontWeight};
+ font-size: ${props => props.fontSize};
+ opacity: ${props => props.opacity};
+ text-decoration-line: ${props => props.textDecorationLine};
+ ${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
+ ${props => (props.center ? 'text-align: center' : '')};
+ color: ${props => props.fontColor && props.theme[props.fontColor]};
+ ${props => (props.minHeight ? `min-height: ${props.minHeight}` : '')};
+ ${props => (props.onClick ? 'cursor: pointer' : '')};
+ transition: color 0.5s ease;
+ ${props => (props.noWrap ? 'white-space: nowrap' : '')};
+ ${props => (props.display ? `display: ${props.display}` : '')};
+ ${props => (props.letterSpacing ? `letter-spacing: ${props.letterSpacing}` : '')};
+ ${props => (props.textTransform ? `text-transform: ${props.textTransform}` : '')};
+ &:hover {
+ ${props =>
+ props.onClick
+ ? `color: ${props.hoverColor || darken(darkenOnHoverAmount, props.theme[props.fontColor || 'white'])}`
+ : ''};
+ }
+`;
+
+Text.defaultProps = {
+ fontFamily: 'Inter UI',
+ fontStyle: 'normal',
+ fontWeight: 400,
+ fontColor: ColorOption.black,
+ fontSize: '15px',
+ textDecorationLine: 'none',
+ noWrap: false,
+ display: 'inline-block',
+};
+
+Text.displayName = 'Text';
+
+export const Title: React.StatelessComponent<TextProps> = props => <Text {...props} />;
+
+Title.defaultProps = {
+ fontSize: '20px',
+ fontWeight: 600,
+ opacity: 1,
+ fontColor: ColorOption.primaryColor,
+};
+
+Title.displayName = 'Title';
diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx
index 67e1b683d..0e6230d1b 100644
--- a/packages/instant/src/components/zero_ex_instant.tsx
+++ b/packages/instant/src/components/zero_ex_instant.tsx
@@ -1,5 +1,20 @@
import * as React from 'react';
+import { Provider } from 'react-redux';
+
+import { store } from '../redux/store';
+import { fonts } from '../style/fonts';
+import { theme, ThemeProvider } from '../style/theme';
+
+import { ZeroExInstantContainer } from './zero_ex_instant_container';
+
+fonts.include();
export interface ZeroExInstantProps {}
-export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = () => <div>ZeroExInstant</div>;
+export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = () => (
+ <Provider store={store}>
+ <ThemeProvider theme={theme}>
+ <ZeroExInstantContainer />
+ </ThemeProvider>
+ </Provider>
+);
diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx
new file mode 100644
index 000000000..716227b51
--- /dev/null
+++ b/packages/instant/src/components/zero_ex_instant_container.tsx
@@ -0,0 +1,20 @@
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { BuyButton } from './buy_button';
+import { InstantHeading } from './instant_heading';
+import { OrderDetails } from './order_details';
+import { Container, Flex } from './ui';
+
+export interface ZeroExInstantContainerProps {}
+
+export const ZeroExInstantContainer: React.StatelessComponent<ZeroExInstantContainerProps> = props => (
+ <Container hasBoxShadow={true} width="350px" backgroundColor={ColorOption.white} borderRadius="3px">
+ <Flex direction="column" justify="flex-start">
+ <InstantHeading />
+ <OrderDetails />
+ <BuyButton />
+ </Flex>
+ </Container>
+);
diff --git a/packages/instant/src/containers/selected_asset_amount_input.tsx b/packages/instant/src/containers/selected_asset_amount_input.tsx
new file mode 100644
index 000000000..800a4c568
--- /dev/null
+++ b/packages/instant/src/containers/selected_asset_amount_input.tsx
@@ -0,0 +1,36 @@
+import { BigNumber } from '@0xproject/utils';
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+
+import { State } from '../redux/reducer';
+import { ColorOption } from '../style/theme';
+import { Action, ActionTypes } from '../types';
+
+import { AmountInput } from '../components/amount_input';
+
+export interface SelectedAssetAmountInputProps {
+ fontColor?: ColorOption;
+ fontSize?: string;
+}
+
+interface ConnectedState {
+ value?: BigNumber;
+}
+
+interface ConnectedDispatch {
+ onChange?: (value?: BigNumber) => void;
+}
+
+const mapStateToProps = (state: State, _ownProps: SelectedAssetAmountInputProps): ConnectedState => ({
+ value: state.selectedAssetAmount,
+});
+
+const mapDispatchToProps = (dispatch: Dispatch<Action>): ConnectedDispatch => ({
+ onChange: value => dispatch({ type: ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT, data: value }),
+});
+
+export const SelectedAssetAmountInput: React.ComponentClass<SelectedAssetAmountInputProps> = connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(AmountInput);
diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts
new file mode 100644
index 000000000..5026895ae
--- /dev/null
+++ b/packages/instant/src/redux/reducer.ts
@@ -0,0 +1,31 @@
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+
+import { Action, ActionTypes } from '../types';
+
+export interface State {
+ ethUsdPrice?: string;
+ selectedAssetAmount?: BigNumber;
+}
+
+export const INITIAL_STATE: State = {
+ ethUsdPrice: undefined,
+ selectedAssetAmount: undefined,
+};
+
+export const reducer = (state: State = INITIAL_STATE, action: Action): State => {
+ switch (action.type) {
+ case ActionTypes.UPDATE_ETH_USD_PRICE:
+ return {
+ ...state,
+ ethUsdPrice: action.data,
+ };
+ case ActionTypes.UPDATE_SELECTED_ASSET_AMOUNT:
+ return {
+ ...state,
+ selectedAssetAmount: action.data,
+ };
+ default:
+ return state;
+ }
+};
diff --git a/packages/instant/src/redux/store.ts b/packages/instant/src/redux/store.ts
new file mode 100644
index 000000000..fcd19f9a8
--- /dev/null
+++ b/packages/instant/src/redux/store.ts
@@ -0,0 +1,6 @@
+import * as _ from 'lodash';
+import { createStore, Store as ReduxStore } from 'redux';
+
+import { reducer, State } from './reducer';
+
+export const store: ReduxStore<State> = createStore(reducer);
diff --git a/packages/instant/src/style/fonts.ts b/packages/instant/src/style/fonts.ts
new file mode 100644
index 000000000..975a30a61
--- /dev/null
+++ b/packages/instant/src/style/fonts.ts
@@ -0,0 +1,10 @@
+import { injectGlobal } from './theme';
+
+export const fonts = {
+ include: () => {
+ // Inject the inter-ui font into the page
+ return injectGlobal`
+ @import url('https://rsms.me/inter/inter-ui.css');
+ `;
+ },
+};
diff --git a/packages/instant/src/style/theme.ts b/packages/instant/src/style/theme.ts
new file mode 100644
index 000000000..cf9da5378
--- /dev/null
+++ b/packages/instant/src/style/theme.ts
@@ -0,0 +1,27 @@
+import * as styledComponents from 'styled-components';
+
+const { default: styled, css, injectGlobal, keyframes, ThemeProvider } = styledComponents;
+
+export type Theme = { [key in ColorOption]: string };
+
+export enum ColorOption {
+ primaryColor = 'primaryColor',
+ black = 'black',
+ lightGrey = 'lightGrey',
+ grey = 'grey',
+ feintGrey = 'feintGrey',
+ darkGrey = 'darkGrey',
+ white = 'white',
+}
+
+export const theme: Theme = {
+ primaryColor: '#512D80',
+ black: 'black',
+ lightGrey: '#999999',
+ grey: '#666666',
+ feintGrey: '#DEDEDE',
+ darkGrey: '#333333',
+ white: 'white',
+};
+
+export { styled, css, injectGlobal, keyframes, ThemeProvider };
diff --git a/packages/instant/src/style/util.ts b/packages/instant/src/style/util.ts
new file mode 100644
index 000000000..c9df0f834
--- /dev/null
+++ b/packages/instant/src/style/util.ts
@@ -0,0 +1,11 @@
+import { ObjectMap } from '@0xproject/types';
+import * as _ from 'lodash';
+
+export const cssRuleIfExists = (props: ObjectMap<any>, rule: string): string => {
+ const camelCaseRule = _.camelCase(rule);
+ const ruleValueIfExists = props[camelCaseRule];
+ if (!_.isUndefined(ruleValueIfExists)) {
+ return `${rule}: ${ruleValueIfExists};`;
+ }
+ return '';
+};
diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts
new file mode 100644
index 000000000..d150bd8ab
--- /dev/null
+++ b/packages/instant/src/types.ts
@@ -0,0 +1,9 @@
+export enum ActionTypes {
+ UPDATE_ETH_USD_PRICE,
+ UPDATE_SELECTED_ASSET_AMOUNT,
+}
+
+export interface Action {
+ type: ActionTypes;
+ data?: any;
+}
diff --git a/packages/instant/tslint.json b/packages/instant/tslint.json
index ffaefe83a..f71532e5d 100644
--- a/packages/instant/tslint.json
+++ b/packages/instant/tslint.json
@@ -1,3 +1,7 @@
{
- "extends": ["@0xproject/tslint-config"]
+ "extends": ["@0xproject/tslint-config"],
+ "rules": {
+ "custom-no-magic-numbers": false,
+ "semicolon": [true, "always", "ignore-bound-class-methods"]
+ }
}
diff --git a/packages/json-schemas/schemas/eip712_typed_data.ts b/packages/json-schemas/schemas/eip712_typed_data.ts
new file mode 100644
index 000000000..31ad74610
--- /dev/null
+++ b/packages/json-schemas/schemas/eip712_typed_data.ts
@@ -0,0 +1,28 @@
+export const eip712TypedDataSchema = {
+ id: '/eip712TypedData',
+ type: 'object',
+ properties: {
+ types: {
+ type: 'object',
+ properties: {
+ EIP712Domain: { type: 'array' },
+ },
+ additionalProperties: {
+ type: 'array',
+ items: {
+ type: 'object',
+ properties: {
+ name: { type: 'string' },
+ type: { type: 'string' },
+ },
+ required: ['name', 'type'],
+ },
+ },
+ required: ['EIP712Domain'],
+ },
+ primaryType: { type: 'string' },
+ domain: { type: 'object' },
+ message: { type: 'object' },
+ },
+ required: ['types', 'primaryType', 'domain', 'message'],
+};
diff --git a/packages/json-schemas/schemas/zero_ex_transaction_schema.ts b/packages/json-schemas/schemas/zero_ex_transaction_schema.ts
new file mode 100644
index 000000000..7f729b724
--- /dev/null
+++ b/packages/json-schemas/schemas/zero_ex_transaction_schema.ts
@@ -0,0 +1,10 @@
+export const zeroExTransactionSchema = {
+ id: '/zeroExTransactionSchema',
+ properties: {
+ data: { $ref: '/hexSchema' },
+ signerAddress: { $ref: '/addressSchema' },
+ salt: { $ref: '/numberSchema' },
+ },
+ required: ['data', 'salt', 'signerAddress'],
+ type: 'object',
+};
diff --git a/packages/json-schemas/src/schemas.ts b/packages/json-schemas/src/schemas.ts
index 3bc37f96b..4eb96092d 100644
--- a/packages/json-schemas/src/schemas.ts
+++ b/packages/json-schemas/src/schemas.ts
@@ -2,6 +2,7 @@ import { addressSchema, hexSchema, numberSchema } from '../schemas/basic_type_sc
import { blockParamSchema, blockRangeSchema } from '../schemas/block_range_schema';
import { callDataSchema } from '../schemas/call_data_schema';
import { ecSignatureParameterSchema, ecSignatureSchema } from '../schemas/ec_signature_schema';
+import { eip712TypedDataSchema } from '../schemas/eip712_typed_data';
import { indexFilterValuesSchema } from '../schemas/index_filter_values_schema';
import { orderCancellationRequestsSchema } from '../schemas/order_cancel_schema';
import { orderFillOrKillRequestsSchema } from '../schemas/order_fill_or_kill_requests_schema';
@@ -31,6 +32,7 @@ import { relayerApiOrdersSchema } from '../schemas/relayer_api_orders_schema';
import { signedOrdersSchema } from '../schemas/signed_orders_schema';
import { tokenSchema } from '../schemas/token_schema';
import { jsNumber, txDataSchema } from '../schemas/tx_data_schema';
+import { zeroExTransactionSchema } from '../schemas/zero_ex_transaction_schema';
export const schemas = {
numberSchema,
@@ -39,6 +41,7 @@ export const schemas = {
hexSchema,
ecSignatureParameterSchema,
ecSignatureSchema,
+ eip712TypedDataSchema,
indexFilterValuesSchema,
orderCancellationRequestsSchema,
orderFillOrKillRequestsSchema,
@@ -68,4 +71,5 @@ export const schemas = {
relayerApiOrdersChannelUpdateSchema,
relayerApiOrdersResponseSchema,
relayerApiAssetDataPairsSchema,
+ zeroExTransactionSchema,
};
diff --git a/packages/metacoin/package.json b/packages/metacoin/package.json
index 83082d964..58fc0b848 100644
--- a/packages/metacoin/package.json
+++ b/packages/metacoin/package.json
@@ -41,7 +41,7 @@
"@types/mocha": "^5.2.2",
"copyfiles": "^2.0.0",
"ethereum-types": "^1.0.11",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"lodash": "^4.17.5",
"run-s": "^0.0.0"
},
diff --git a/packages/migrations/package.json b/packages/migrations/package.json
index dcae2c562..2d1b7bfc2 100644
--- a/packages/migrations/package.json
+++ b/packages/migrations/package.json
@@ -54,7 +54,7 @@
"@0xproject/web3-wrapper": "^3.0.3",
"@ledgerhq/hw-app-eth": "^4.3.0",
"ethereum-types": "^1.0.11",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"lodash": "^4.17.5"
},
"optionalDependencies": {
diff --git a/packages/order-utils/CHANGELOG.json b/packages/order-utils/CHANGELOG.json
index 3e841c43c..5a0c0db47 100644
--- a/packages/order-utils/CHANGELOG.json
+++ b/packages/order-utils/CHANGELOG.json
@@ -1,5 +1,23 @@
[
{
+ "version": "2.0.0",
+ "changes": [
+ {
+ "note":
+ "Added `ecSignOrderAsync` to first sign an order using `eth_signTypedData` and fallback to `eth_sign`.",
+ "pr": 1102
+ },
+ {
+ "note": "Added `ecSignTypedDataOrderAsync` to sign an order exclusively using `eth_signTypedData`.",
+ "pr": 1102
+ },
+ {
+ "note": "Rename `ecSignOrderHashAsync` to `ecSignHashAsync` removing `SignerType` parameter.",
+ "pr": 1102
+ }
+ ]
+ },
+ {
"version": "1.0.7",
"changes": [
{
diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json
index 23ed9ca12..6471de9f5 100644
--- a/packages/order-utils/package.json
+++ b/packages/order-utils/package.json
@@ -70,7 +70,7 @@
"ethereum-types": "^1.0.11",
"ethereumjs-abi": "0.6.5",
"ethereumjs-util": "^5.1.1",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"lodash": "^4.17.5"
},
"publishConfig": {
diff --git a/packages/order-utils/src/constants.ts b/packages/order-utils/src/constants.ts
index c23578c20..7de20a696 100644
--- a/packages/order-utils/src/constants.ts
+++ b/packages/order-utils/src/constants.ts
@@ -13,4 +13,39 @@ export const constants = {
BASE_16: 16,
INFINITE_TIMESTAMP_SEC: new BigNumber(2524604400), // Close to infinite
ZERO_AMOUNT: new BigNumber(0),
+ EIP712_DOMAIN_NAME: '0x Protocol',
+ EIP712_DOMAIN_VERSION: '2',
+ EIP712_DOMAIN_SCHEMA: {
+ name: 'EIP712Domain',
+ parameters: [
+ { name: 'name', type: 'string' },
+ { name: 'version', type: 'string' },
+ { name: 'verifyingContract', type: 'address' },
+ ],
+ },
+ EIP712_ORDER_SCHEMA: {
+ name: 'Order',
+ parameters: [
+ { name: 'makerAddress', type: 'address' },
+ { name: 'takerAddress', type: 'address' },
+ { name: 'feeRecipientAddress', type: 'address' },
+ { name: 'senderAddress', type: 'address' },
+ { name: 'makerAssetAmount', type: 'uint256' },
+ { name: 'takerAssetAmount', type: 'uint256' },
+ { name: 'makerFee', type: 'uint256' },
+ { name: 'takerFee', type: 'uint256' },
+ { name: 'expirationTimeSeconds', type: 'uint256' },
+ { name: 'salt', type: 'uint256' },
+ { name: 'makerAssetData', type: 'bytes' },
+ { name: 'takerAssetData', type: 'bytes' },
+ ],
+ },
+ EIP712_ZEROEX_TRANSACTION_SCHEMA: {
+ name: 'ZeroExTransaction',
+ parameters: [
+ { name: 'salt', type: 'uint256' },
+ { name: 'signerAddress', type: 'address' },
+ { name: 'data', type: 'bytes' },
+ ],
+ },
};
diff --git a/packages/order-utils/src/eip712_utils.ts b/packages/order-utils/src/eip712_utils.ts
index b303c93dc..56f736500 100644
--- a/packages/order-utils/src/eip712_utils.ts
+++ b/packages/order-utils/src/eip712_utils.ts
@@ -1,109 +1,83 @@
-import ethUtil = require('ethereumjs-util');
+import { assert } from '@0xproject/assert';
+import { schemas } from '@0xproject/json-schemas';
+import { EIP712Object, EIP712TypedData, EIP712Types, Order, ZeroExTransaction } from '@0xproject/types';
import * as _ from 'lodash';
-import { crypto } from './crypto';
-import { EIP712Schema, EIP712Types } from './types';
-
-const EIP191_PREFIX = '\x19\x01';
-const EIP712_DOMAIN_NAME = '0x Protocol';
-const EIP712_DOMAIN_VERSION = '2';
-const EIP712_VALUE_LENGTH = 32;
-
-const EIP712_DOMAIN_SCHEMA: EIP712Schema = {
- name: 'EIP712Domain',
- parameters: [
- { name: 'name', type: EIP712Types.String },
- { name: 'version', type: EIP712Types.String },
- { name: 'verifyingContract', type: EIP712Types.Address },
- ],
-};
+import { constants } from './constants';
export const eip712Utils = {
/**
- * Compiles the EIP712Schema and returns the hash of the schema.
- * @param schema The EIP712 schema.
- * @return The hash of the compiled schema
- */
- compileSchema(schema: EIP712Schema): Buffer {
- const eip712Schema = eip712Utils._encodeType(schema);
- const eip712SchemaHashBuffer = crypto.solSHA3([eip712Schema]);
- return eip712SchemaHashBuffer;
- },
- /**
- * Merges the EIP712 hash of a struct with the DomainSeparator for 0x v2.
- * @param hashStruct the EIP712 hash of a struct
- * @param contractAddress the exchange contract address
- * @return The hash of an EIP712 message with domain separator prefixed
- */
- createEIP712Message(hashStruct: Buffer, contractAddress: string): Buffer {
- const domainSeparatorHashBuffer = eip712Utils._getDomainSeparatorHashBuffer(contractAddress);
- const messageBuff = crypto.solSHA3([EIP191_PREFIX, domainSeparatorHashBuffer, hashStruct]);
- return messageBuff;
- },
- /**
- * Pad an address to 32 bytes
- * @param address Address to pad
- * @return padded address
+ * Creates a EIP712TypedData object specific to the 0x protocol for use with signTypedData.
+ * @param primaryType The primary type found in message
+ * @param types The additional types for the data in message
+ * @param message The contents of the message
+ * @param exchangeAddress The address of the exchange contract
+ * @return A typed data object
*/
- pad32Address(address: string): Buffer {
- const addressBuffer = ethUtil.toBuffer(address);
- const addressPadded = eip712Utils.pad32Buffer(addressBuffer);
- return addressPadded;
+ createTypedData: (
+ primaryType: string,
+ types: EIP712Types,
+ message: EIP712Object,
+ exchangeAddress: string,
+ ): EIP712TypedData => {
+ assert.isETHAddressHex('exchangeAddress', exchangeAddress);
+ assert.isString('primaryType', primaryType);
+ const typedData = {
+ types: {
+ EIP712Domain: constants.EIP712_DOMAIN_SCHEMA.parameters,
+ ...types,
+ },
+ domain: {
+ name: constants.EIP712_DOMAIN_NAME,
+ version: constants.EIP712_DOMAIN_VERSION,
+ verifyingContract: exchangeAddress,
+ },
+ message,
+ primaryType,
+ };
+ assert.doesConformToSchema('typedData', typedData, schemas.eip712TypedDataSchema);
+ return typedData;
},
/**
- * Pad an buffer to 32 bytes
- * @param buffer Address to pad
- * @return padded buffer
+ * Creates an Order EIP712TypedData object for use with signTypedData.
+ * @param Order the order
+ * @return A typed data object
*/
- pad32Buffer(buffer: Buffer): Buffer {
- const bufferPadded = ethUtil.setLengthLeft(buffer, EIP712_VALUE_LENGTH);
- return bufferPadded;
+ createOrderTypedData: (order: Order): EIP712TypedData => {
+ assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]);
+ const normalizedOrder = _.mapValues(order, value => {
+ return !_.isString(value) ? value.toString() : value;
+ });
+ const typedData = eip712Utils.createTypedData(
+ constants.EIP712_ORDER_SCHEMA.name,
+ { Order: constants.EIP712_ORDER_SCHEMA.parameters },
+ normalizedOrder,
+ order.exchangeAddress,
+ );
+ return typedData;
},
/**
- * Hash together a EIP712 schema with the corresponding data
- * @param schema EIP712-compliant schema
- * @param data Data the complies to the schema
- * @return A buffer containing the SHA256 hash of the schema and encoded data
+ * Creates an ExecuteTransaction EIP712TypedData object for use with signTypedData and
+ * 0x Exchange executeTransaction.
+ * @param ZeroExTransaction the 0x transaction
+ * @param exchangeAddress The address of the exchange contract
+ * @return A typed data object
*/
- structHash(schema: EIP712Schema, data: { [key: string]: any }): Buffer {
- const encodedData = eip712Utils._encodeData(schema, data);
- const schemaHash = eip712Utils.compileSchema(schema);
- const hashBuffer = crypto.solSHA3([schemaHash, ...encodedData]);
- return hashBuffer;
- },
- _getDomainSeparatorSchemaBuffer(): Buffer {
- return eip712Utils.compileSchema(EIP712_DOMAIN_SCHEMA);
- },
- _getDomainSeparatorHashBuffer(exchangeAddress: string): Buffer {
- const domainSeparatorSchemaBuffer = eip712Utils._getDomainSeparatorSchemaBuffer();
- const encodedData = eip712Utils._encodeData(EIP712_DOMAIN_SCHEMA, {
- name: EIP712_DOMAIN_NAME,
- version: EIP712_DOMAIN_VERSION,
- verifyingContract: exchangeAddress,
+ createZeroExTransactionTypedData: (
+ zeroExTransaction: ZeroExTransaction,
+ exchangeAddress: string,
+ ): EIP712TypedData => {
+ assert.isETHAddressHex('exchangeAddress', exchangeAddress);
+ assert.doesConformToSchema('zeroExTransaction', zeroExTransaction, schemas.zeroExTransactionSchema);
+ const normalizedTransaction = _.mapValues(zeroExTransaction, value => {
+ return !_.isString(value) ? value.toString() : value;
});
- const domainSeparatorHashBuff2 = crypto.solSHA3([domainSeparatorSchemaBuffer, ...encodedData]);
- return domainSeparatorHashBuff2;
- },
- _encodeType(schema: EIP712Schema): string {
- const namedTypes = _.map(schema.parameters, ({ name, type }) => `${type} ${name}`);
- const namedTypesJoined = namedTypes.join(',');
- const encodedType = `${schema.name}(${namedTypesJoined})`;
- return encodedType;
- },
- _encodeData(schema: EIP712Schema, data: { [key: string]: any }): any {
- const encodedValues = [];
- for (const parameter of schema.parameters) {
- const value = data[parameter.name];
- if (parameter.type === EIP712Types.String || parameter.type === EIP712Types.Bytes) {
- encodedValues.push(crypto.solSHA3([ethUtil.toBuffer(value)]));
- } else if (parameter.type === EIP712Types.Uint256) {
- encodedValues.push(value);
- } else if (parameter.type === EIP712Types.Address) {
- encodedValues.push(eip712Utils.pad32Address(value));
- } else {
- throw new Error(`Unable to encode ${parameter.type}`);
- }
- }
- return encodedValues;
+ const typedData = eip712Utils.createTypedData(
+ constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.name,
+ { ZeroExTransaction: constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.parameters },
+ normalizedTransaction,
+ exchangeAddress,
+ );
+ return typedData;
},
};
diff --git a/packages/order-utils/src/index.ts b/packages/order-utils/src/index.ts
index 1553647c6..dbb782b85 100644
--- a/packages/order-utils/src/index.ts
+++ b/packages/order-utils/src/index.ts
@@ -2,7 +2,6 @@ export { orderHashUtils } from './order_hash';
export { signatureUtils } from './signature_utils';
export { generatePseudoRandomSalt } from './salt';
export { assetDataUtils } from './asset_data_utils';
-export { eip712Utils } from './eip712_utils';
export { marketUtils } from './market_utils';
export { rateUtils } from './rate_utils';
export { sortingUtils } from './sorting_utils';
@@ -19,7 +18,17 @@ export { ExchangeTransferSimulator } from './exchange_transfer_simulator';
export { BalanceAndProxyAllowanceLazyStore } from './store/balance_and_proxy_allowance_lazy_store';
export { OrderFilledCancelledLazyStore } from './store/order_filled_cancelled_lazy_store';
-export { Provider, JSONRPCRequestPayload, JSONRPCErrorCallback, JSONRPCResponsePayload } from 'ethereum-types';
+export { constants } from './constants';
+export { eip712Utils } from './eip712_utils';
+
+export {
+ Provider,
+ JSONRPCRequestPayload,
+ JSONRPCErrorCallback,
+ JSONRPCResponsePayload,
+ JSONRPCResponseError,
+} from 'ethereum-types';
+
export {
SignedOrder,
Order,
@@ -29,17 +38,19 @@ export {
ERC20AssetData,
ERC721AssetData,
AssetProxyId,
- SignerType,
SignatureType,
OrderStateValid,
OrderStateInvalid,
ExchangeContractErrs,
+ EIP712Parameter,
+ EIP712TypedData,
+ EIP712Types,
+ EIP712Object,
+ EIP712ObjectValue,
+ ZeroExTransaction,
} from '@0xproject/types';
export {
OrderError,
- EIP712Parameter,
- EIP712Schema,
- EIP712Types,
TradeSide,
TransferType,
FindFeeOrdersThatCoverFeesForTargetOrdersOpts,
diff --git a/packages/order-utils/src/order_factory.ts b/packages/order-utils/src/order_factory.ts
index b1292903a..0f0cd6046 100644
--- a/packages/order-utils/src/order_factory.ts
+++ b/packages/order-utils/src/order_factory.ts
@@ -1,4 +1,4 @@
-import { Order, SignedOrder, SignerType } from '@0xproject/types';
+import { Order, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Provider } from 'ethereum-types';
import * as _ from 'lodash';
@@ -71,12 +71,7 @@ export const orderFactory = {
createOrderOpts,
);
const orderHash = orderHashUtils.getOrderHashHex(order);
- const signature = await signatureUtils.ecSignOrderHashAsync(
- provider,
- orderHash,
- makerAddress,
- SignerType.Default,
- );
+ const signature = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress);
const signedOrder: SignedOrder = _.assign(order, { signature });
return signedOrder;
},
diff --git a/packages/order-utils/src/order_hash.ts b/packages/order-utils/src/order_hash.ts
index 8e98f8767..b523a3523 100644
--- a/packages/order-utils/src/order_hash.ts
+++ b/packages/order-utils/src/order_hash.ts
@@ -1,31 +1,13 @@
import { schemas, SchemaValidator } from '@0xproject/json-schemas';
import { Order, SignedOrder } from '@0xproject/types';
+import { signTypedDataUtils } from '@0xproject/utils';
import * as _ from 'lodash';
import { assert } from './assert';
import { eip712Utils } from './eip712_utils';
-import { EIP712Schema, EIP712Types } from './types';
const INVALID_TAKER_FORMAT = 'instance.takerAddress is not of a type(s) string';
-const EIP712_ORDER_SCHEMA: EIP712Schema = {
- name: 'Order',
- parameters: [
- { name: 'makerAddress', type: EIP712Types.Address },
- { name: 'takerAddress', type: EIP712Types.Address },
- { name: 'feeRecipientAddress', type: EIP712Types.Address },
- { name: 'senderAddress', type: EIP712Types.Address },
- { name: 'makerAssetAmount', type: EIP712Types.Uint256 },
- { name: 'takerAssetAmount', type: EIP712Types.Uint256 },
- { name: 'makerFee', type: EIP712Types.Uint256 },
- { name: 'takerFee', type: EIP712Types.Uint256 },
- { name: 'expirationTimeSeconds', type: EIP712Types.Uint256 },
- { name: 'salt', type: EIP712Types.Uint256 },
- { name: 'makerAssetData', type: EIP712Types.Bytes },
- { name: 'takerAssetData', type: EIP712Types.Bytes },
- ],
-};
-
export const orderHashUtils = {
/**
* Checks if the supplied hex encoded order hash is valid.
@@ -45,7 +27,7 @@ export const orderHashUtils = {
/**
* Computes the orderHash for a supplied order.
* @param order An object that conforms to the Order or SignedOrder interface definitions.
- * @return The resulting orderHash from hashing the supplied order.
+ * @return Hex encoded string orderHash from hashing the supplied order.
*/
getOrderHashHex(order: SignedOrder | Order): string {
try {
@@ -64,16 +46,13 @@ export const orderHashUtils = {
return orderHashHex;
},
/**
- * Computes the orderHash for a supplied order and returns it as a Buffer
+ * Computes the orderHash for a supplied order
* @param order An object that conforms to the Order or SignedOrder interface definitions.
- * @return The resulting orderHash from hashing the supplied order as a Buffer
+ * @return A Buffer containing the resulting orderHash from hashing the supplied order
*/
getOrderHashBuffer(order: SignedOrder | Order): Buffer {
- const orderParamsHashBuff = eip712Utils.structHash(EIP712_ORDER_SCHEMA, order);
- const orderHashBuff = eip712Utils.createEIP712Message(orderParamsHashBuff, order.exchangeAddress);
+ const typedData = eip712Utils.createOrderTypedData(order);
+ const orderHashBuff = signTypedDataUtils.generateTypedDataHash(typedData);
return orderHashBuff;
},
- _getOrderSchemaBuffer(): Buffer {
- return eip712Utils.compileSchema(EIP712_ORDER_SCHEMA);
- },
};
diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts
index 3b656d3fc..372d210d0 100644
--- a/packages/order-utils/src/signature_utils.ts
+++ b/packages/order-utils/src/signature_utils.ts
@@ -1,5 +1,5 @@
import { schemas } from '@0xproject/json-schemas';
-import { ECSignature, SignatureType, SignerType, ValidatorSignature } from '@0xproject/types';
+import { ECSignature, Order, SignatureType, SignedOrder, ValidatorSignature } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
@@ -7,9 +7,11 @@ import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { assert } from './assert';
+import { eip712Utils } from './eip712_utils';
import { ExchangeContract } from './generated_contract_wrappers/exchange';
import { IValidatorContract } from './generated_contract_wrappers/i_validator';
import { IWalletContract } from './generated_contract_wrappers/i_wallet';
+import { orderHashUtils } from './order_hash';
import { OrderError } from './types';
import { utils } from './utils';
@@ -49,7 +51,7 @@ export const signatureUtils = {
case SignatureType.EthSign: {
const ecSignature = signatureUtils.parseECSignature(signature);
- const prefixedMessageHex = signatureUtils.addSignedMessagePrefix(data, SignerType.Default);
+ const prefixedMessageHex = signatureUtils.addSignedMessagePrefix(data);
return signatureUtils.isValidECSignature(prefixedMessageHex, ecSignature, signerAddress);
}
@@ -192,36 +194,90 @@ export const signatureUtils = {
}
},
/**
- * Signs an orderHash and returns it's elliptic curve signature and signature type.
- * This method currently supports TestRPC, Geth and Parity above and below V1.6.6
- * @param orderHash Hex encoded orderHash to sign.
+ * Signs an order and returns a SignedOrder. First `eth_signTypedData` is requested
+ * then a fallback to `eth_sign` if not available on the supplied provider.
+ * @param order The Order to sign.
* @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
- * must be available via the Provider supplied to 0x.js.
- * @param signerType Different signers add/require different prefixes to be prepended to the message being signed.
- * Since we cannot know ahead of time which signer you are using, you must supply a SignerType.
- * @return A hex encoded string containing the Elliptic curve signature generated by signing the orderHash and the Signature Type.
+ * must be available via the supplied Provider.
+ * @return A SignedOrder containing the order and Elliptic curve signature with Signature Type.
*/
- async ecSignOrderHashAsync(
- provider: Provider,
- orderHash: string,
- signerAddress: string,
- signerType: SignerType,
- ): Promise<string> {
+ async ecSignOrderAsync(provider: Provider, order: Order, signerAddress: string): Promise<SignedOrder> {
+ assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]);
+ try {
+ const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(provider, order, signerAddress);
+ return signedOrder;
+ } catch (err) {
+ // HACK: We are unable to handle specific errors thrown since provider is not an object
+ // under our control. It could be Metamask Web3, Ethers, or any general RPC provider.
+ // We check for a user denying the signature request in a way that supports Metamask and
+ // Coinbase Wallet. Unfortunately for signers with a different error message,
+ // they will receive two signature requests.
+ if (err.message.includes('User denied message signature')) {
+ throw err;
+ }
+ const orderHash = orderHashUtils.getOrderHashHex(order);
+ const signatureHex = await signatureUtils.ecSignHashAsync(provider, orderHash, signerAddress);
+ const signedOrder = {
+ ...order,
+ signature: signatureHex,
+ };
+ return signedOrder;
+ }
+ },
+ /**
+ * Signs an order using `eth_signTypedData` and returns a SignedOrder.
+ * @param order The Order to sign.
+ * @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
+ * must be available via the supplied Provider.
+ * @return A SignedOrder containing the order and Elliptic curve signature with Signature Type.
+ */
+ async ecSignTypedDataOrderAsync(provider: Provider, order: Order, signerAddress: string): Promise<SignedOrder> {
assert.isWeb3Provider('provider', provider);
- assert.isHexString('orderHash', orderHash);
assert.isETHAddressHex('signerAddress', signerAddress);
+ assert.doesConformToSchema('order', order, schemas.orderSchema, [schemas.hexSchema]);
const web3Wrapper = new Web3Wrapper(provider);
await assert.isSenderAddressAsync('signerAddress', signerAddress, web3Wrapper);
const normalizedSignerAddress = signerAddress.toLowerCase();
-
- let msgHashHex = orderHash;
- const prefixedMsgHashHex = signatureUtils.addSignedMessagePrefix(orderHash, signerType);
- // Metamask incorrectly implements eth_sign and does not prefix the message as per the spec
- // Source: https://github.com/MetaMask/metamask-extension/commit/a9d36860bec424dcee8db043d3e7da6a5ff5672e
- if (signerType === SignerType.Metamask) {
- msgHashHex = prefixedMsgHashHex;
+ const typedData = eip712Utils.createOrderTypedData(order);
+ try {
+ const signature = await web3Wrapper.signTypedDataAsync(normalizedSignerAddress, typedData);
+ const ecSignatureRSV = parseSignatureHexAsRSV(signature);
+ const signatureBuffer = Buffer.concat([
+ ethUtil.toBuffer(ecSignatureRSV.v),
+ ethUtil.toBuffer(ecSignatureRSV.r),
+ ethUtil.toBuffer(ecSignatureRSV.s),
+ ethUtil.toBuffer(SignatureType.EIP712),
+ ]);
+ const signatureHex = `0x${signatureBuffer.toString('hex')}`;
+ return {
+ ...order,
+ signature: signatureHex,
+ };
+ } catch (err) {
+ // Detect if Metamask to transition users to the MetamaskSubprovider
+ if ((provider as any).isMetaMask) {
+ throw new Error(OrderError.InvalidMetamaskSigner);
+ } else {
+ throw err;
+ }
}
- const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHashHex);
+ },
+ /**
+ * Signs a hash using `eth_sign` and returns its elliptic curve signature and signature type.
+ * @param msgHash Hex encoded message to sign.
+ * @param signerAddress The hex encoded Ethereum address you wish to sign it with. This address
+ * must be available via the supplied Provider.
+ * @return A hex encoded string containing the Elliptic curve signature generated by signing the msgHash and the Signature Type.
+ */
+ async ecSignHashAsync(provider: Provider, msgHash: string, signerAddress: string): Promise<string> {
+ assert.isWeb3Provider('provider', provider);
+ assert.isHexString('msgHash', msgHash);
+ assert.isETHAddressHex('signerAddress', signerAddress);
+ const web3Wrapper = new Web3Wrapper(provider);
+ await assert.isSenderAddressAsync('signerAddress', signerAddress, web3Wrapper);
+ const normalizedSignerAddress = signerAddress.toLowerCase();
+ const signature = await web3Wrapper.signMessageAsync(normalizedSignerAddress, msgHash);
+ const prefixedMsgHashHex = signatureUtils.addSignedMessagePrefix(msgHash);
// HACK: There is no consensus on whether the signatureHex string should be formatted as
// v + r + s OR r + s + v, and different clients (even different versions of the same client)
@@ -238,10 +294,7 @@ export const signatureUtils = {
normalizedSignerAddress,
);
if (isValidRSVSignature) {
- const convertedSignatureHex = signatureUtils.convertECSignatureToSignatureHex(
- ecSignatureRSV,
- signerType,
- );
+ const convertedSignatureHex = signatureUtils.convertECSignatureToSignatureHex(ecSignatureRSV);
return convertedSignatureHex;
}
}
@@ -253,41 +306,30 @@ export const signatureUtils = {
normalizedSignerAddress,
);
if (isValidVRSSignature) {
- const convertedSignatureHex = signatureUtils.convertECSignatureToSignatureHex(
- ecSignatureVRS,
- signerType,
- );
+ const convertedSignatureHex = signatureUtils.convertECSignatureToSignatureHex(ecSignatureVRS);
return convertedSignatureHex;
}
}
-
- throw new Error(OrderError.InvalidSignature);
+ // Detect if Metamask to transition users to the MetamaskSubprovider
+ if ((provider as any).isMetaMask) {
+ throw new Error(OrderError.InvalidMetamaskSigner);
+ } else {
+ throw new Error(OrderError.InvalidSignature);
+ }
},
/**
- * Combines ECSignature with V,R,S and the relevant signature type for use in 0x protocol
+ * Combines ECSignature with V,R,S and the EthSign signature type for use in 0x protocol
* @param ecSignature The ECSignature of the signed data
- * @param signerType The SignerType of the signed data
* @return Hex encoded string of signature (v,r,s) with Signature Type
*/
- convertECSignatureToSignatureHex(ecSignature: ECSignature, signerType: SignerType): string {
+ convertECSignatureToSignatureHex(ecSignature: ECSignature): string {
const signatureBuffer = Buffer.concat([
ethUtil.toBuffer(ecSignature.v),
ethUtil.toBuffer(ecSignature.r),
ethUtil.toBuffer(ecSignature.s),
]);
const signatureHex = `0x${signatureBuffer.toString('hex')}`;
- let signatureType;
- switch (signerType) {
- case SignerType.Metamask:
- case SignerType.Ledger:
- case SignerType.Default: {
- signatureType = SignatureType.EthSign;
- break;
- }
- default:
- throw new Error(`Unrecognized SignerType: ${signerType}`);
- }
- const signatureWithType = signatureUtils.convertToSignatureWithType(signatureHex, signatureType);
+ const signatureWithType = signatureUtils.convertToSignatureWithType(signatureHex, SignatureType.EthSign);
return signatureWithType;
},
/**
@@ -304,28 +346,17 @@ export const signatureUtils = {
/**
* Adds the relevant prefix to the message being signed.
* @param message Message to sign
- * @param signerType The type of message prefix to add for a given SignerType. Different signers expect
- * specific message prefixes.
* @return Prefixed message
*/
- addSignedMessagePrefix(message: string, signerType: SignerType = SignerType.Default): string {
+ addSignedMessagePrefix(message: string): string {
assert.isString('message', message);
- assert.doesBelongToStringEnum('signerType', signerType, SignerType);
- switch (signerType) {
- case SignerType.Metamask:
- case SignerType.Ledger:
- case SignerType.Default: {
- const msgBuff = ethUtil.toBuffer(message);
- const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff);
- const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
- return prefixedMsgHex;
- }
- default:
- throw new Error(`Unrecognized SignerType: ${signerType}`);
- }
+ const msgBuff = ethUtil.toBuffer(message);
+ const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff);
+ const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
+ return prefixedMsgHex;
},
/**
- * Parse a 0x protocol hex-encoded signature string into it's ECSignature components
+ * Parse a 0x protocol hex-encoded signature string into its ECSignature components
* @param signature A hex encoded ecSignature 0x Protocol signature
* @return An ECSignature object with r,s,v parameters
*/
diff --git a/packages/order-utils/src/types.ts b/packages/order-utils/src/types.ts
index a843efaa4..5b13dd754 100644
--- a/packages/order-utils/src/types.ts
+++ b/packages/order-utils/src/types.ts
@@ -2,6 +2,7 @@ import { BigNumber } from '@0xproject/utils';
export enum OrderError {
InvalidSignature = 'INVALID_SIGNATURE',
+ InvalidMetamaskSigner = "MetaMask provider must be wrapped in a MetamaskSubprovider (from the '@0xproject/subproviders' package) in order to work with this method.",
}
export enum TradeSide {
@@ -14,24 +15,6 @@ export enum TransferType {
Fee = 'fee',
}
-export interface EIP712Parameter {
- name: string;
- type: EIP712Types;
-}
-
-export interface EIP712Schema {
- name: string;
- parameters: EIP712Parameter[];
-}
-
-export enum EIP712Types {
- Address = 'address',
- Bytes = 'bytes',
- Bytes32 = 'bytes32',
- String = 'string',
- Uint256 = 'uint256',
-}
-
export interface CreateOrderOpts {
takerAddress?: string;
senderAddress?: string;
diff --git a/packages/order-utils/test/eip712_utils_test.ts b/packages/order-utils/test/eip712_utils_test.ts
new file mode 100644
index 000000000..d65cabe9c
--- /dev/null
+++ b/packages/order-utils/test/eip712_utils_test.ts
@@ -0,0 +1,44 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import 'mocha';
+
+import { constants } from '../src/constants';
+import { eip712Utils } from '../src/eip712_utils';
+
+import { chaiSetup } from './utils/chai_setup';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+describe('EIP712 Utils', () => {
+ describe('createTypedData', () => {
+ it('adds in the EIP712DomainSeparator', () => {
+ const primaryType = 'Test';
+ const typedData = eip712Utils.createTypedData(
+ primaryType,
+ { Test: [{ name: 'testValue', type: 'uint256' }] },
+ { testValue: '1' },
+ constants.NULL_ADDRESS,
+ );
+ expect(typedData.domain).to.not.be.undefined();
+ expect(typedData.types.EIP712Domain).to.not.be.undefined();
+ const domainObject = typedData.domain;
+ expect(domainObject.name).to.eq(constants.EIP712_DOMAIN_NAME);
+ expect(typedData.primaryType).to.eq(primaryType);
+ });
+ });
+ describe('createTypedData', () => {
+ it('adds in the EIP712DomainSeparator', () => {
+ const typedData = eip712Utils.createZeroExTransactionTypedData(
+ {
+ salt: new BigNumber('0'),
+ data: constants.NULL_BYTES,
+ signerAddress: constants.NULL_ADDRESS,
+ },
+ constants.NULL_ADDRESS,
+ );
+ expect(typedData.primaryType).to.eq(constants.EIP712_ZEROEX_TRANSACTION_SCHEMA.name);
+ expect(typedData.types.EIP712Domain).to.not.be.undefined();
+ });
+ });
+});
diff --git a/packages/order-utils/test/order_hash_test.ts b/packages/order-utils/test/order_hash_test.ts
index 3fdbbad21..fe44218d6 100644
--- a/packages/order-utils/test/order_hash_test.ts
+++ b/packages/order-utils/test/order_hash_test.ts
@@ -35,6 +35,20 @@ describe('Order hashing', () => {
const orderHash = orderHashUtils.getOrderHashHex(order);
expect(orderHash).to.be.equal(expectedOrderHash);
});
+ it('calculates the order hash if amounts are strings', async () => {
+ // It's common for developers using javascript to provide the amounts
+ // as strings. Since we eventually toString() the BigNumber
+ // before encoding we should result in the same orderHash in this scenario
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ const orderHash = orderHashUtils.getOrderHashHex({
+ ...order,
+ makerAssetAmount: '0',
+ takerAssetAmount: '0',
+ makerFee: '0',
+ takerFee: '0',
+ } as any);
+ expect(orderHash).to.be.equal(expectedOrderHash);
+ });
it('throws a readable error message if taker format is invalid', async () => {
const orderWithInvalidtakerFormat = {
...order,
diff --git a/packages/order-utils/test/signature_utils_test.ts b/packages/order-utils/test/signature_utils_test.ts
index 2ca1109a1..f2d6790fb 100644
--- a/packages/order-utils/test/signature_utils_test.ts
+++ b/packages/order-utils/test/signature_utils_test.ts
@@ -1,12 +1,13 @@
-import { SignerType } from '@0xproject/types';
+import { Order, SignatureType } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { JSONRPCErrorCallback, JSONRPCRequestPayload } from 'ethereum-types';
+import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import 'mocha';
-import * as Sinon from 'sinon';
-import { generatePseudoRandomSalt } from '../src';
+import { generatePseudoRandomSalt, orderHashUtils } from '../src';
+import { constants } from '../src/constants';
import { signatureUtils } from '../src/signature_utils';
import { chaiSetup } from './utils/chai_setup';
@@ -16,6 +17,28 @@ chaiSetup.configure();
const expect = chai.expect;
describe('Signature utils', () => {
+ let makerAddress: string;
+ const fakeExchangeContractAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48';
+ let order: Order;
+ before(async () => {
+ const availableAddreses = await web3Wrapper.getAvailableAddressesAsync();
+ makerAddress = availableAddreses[0];
+ order = {
+ makerAddress,
+ takerAddress: constants.NULL_ADDRESS,
+ senderAddress: constants.NULL_ADDRESS,
+ feeRecipientAddress: constants.NULL_ADDRESS,
+ makerAssetData: constants.NULL_ADDRESS,
+ takerAssetData: constants.NULL_ADDRESS,
+ exchangeAddress: fakeExchangeContractAddress,
+ salt: new BigNumber(0),
+ makerFee: new BigNumber(0),
+ takerFee: new BigNumber(0),
+ makerAssetAmount: new BigNumber(0),
+ takerAssetAmount: new BigNumber(0),
+ expirationTimeSeconds: new BigNumber(0),
+ };
+ });
describe('#isValidSignatureAsync', () => {
let dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const ethSignSignature =
@@ -115,28 +138,64 @@ describe('Signature utils', () => {
expect(salt.lessThan(twoPow256)).to.be.true();
});
});
- describe('#ecSignOrderHashAsync', () => {
- let stubs: Sinon.SinonStub[] = [];
- let makerAddress: string;
+ describe('#ecSignOrderAsync', () => {
+ it('should default to eth_sign if eth_signTypedData is unavailable', async () => {
+ const expectedSignature =
+ '0x1c3582f06356a1314dbf1c0e534c4d8e92e59b056ee607a7ff5a825f5f2cc5e6151c5cc7fdd420f5608e4d5bef108e42ad90c7a4b408caef32e24374cf387b0d7603';
+
+ const fakeProvider = {
+ async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
+ if (payload.method === 'eth_signTypedData') {
+ callback(new Error('Internal RPC Error'));
+ } else if (payload.method === 'eth_sign') {
+ const [address, message] = payload.params;
+ const signature = await web3Wrapper.signMessageAsync(address, message);
+ callback(null, {
+ id: 42,
+ jsonrpc: '2.0',
+ result: signature,
+ });
+ } else {
+ callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
+ }
+ },
+ };
+ const signedOrder = await signatureUtils.ecSignOrderAsync(fakeProvider, order, makerAddress);
+ expect(signedOrder.signature).to.equal(expectedSignature);
+ });
+ it('should throw if the user denies the signing request', async () => {
+ const fakeProvider = {
+ async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
+ if (payload.method === 'eth_signTypedData') {
+ callback(new Error('User denied message signature'));
+ } else if (payload.method === 'eth_sign') {
+ const [address, message] = payload.params;
+ const signature = await web3Wrapper.signMessageAsync(address, message);
+ callback(null, {
+ id: 42,
+ jsonrpc: '2.0',
+ result: signature,
+ });
+ } else {
+ callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
+ }
+ },
+ };
+ expect(signatureUtils.ecSignOrderAsync(fakeProvider, order, makerAddress)).to.to.be.rejectedWith(
+ 'User denied message signature',
+ );
+ });
+ });
+ describe('#ecSignHashAsync', () => {
before(async () => {
const availableAddreses = await web3Wrapper.getAvailableAddressesAsync();
makerAddress = availableAddreses[0];
});
- afterEach(() => {
- // clean up any stubs after the test has completed
- _.each(stubs, s => s.restore());
- stubs = [];
- });
- it('Should return the correct Signature', async () => {
+ it('should return the correct Signature', async () => {
const orderHash = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
const expectedSignature =
'0x1b61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403';
- const ecSignature = await signatureUtils.ecSignOrderHashAsync(
- provider,
- orderHash,
- makerAddress,
- SignerType.Default,
- );
+ const ecSignature = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress);
expect(ecSignature).to.equal(expectedSignature);
});
it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => {
@@ -162,12 +221,7 @@ describe('Signature utils', () => {
}
},
};
- const ecSignature = await signatureUtils.ecSignOrderHashAsync(
- fakeProvider,
- orderHash,
- makerAddress,
- SignerType.Default,
- );
+ const ecSignature = await signatureUtils.ecSignHashAsync(fakeProvider, orderHash, makerAddress);
expect(ecSignature).to.equal(expectedSignature);
});
it('should return the correct Signature for signatureHex concatenated as V + R + S', async () => {
@@ -190,64 +244,68 @@ describe('Signature utils', () => {
},
};
- const ecSignature = await signatureUtils.ecSignOrderHashAsync(
- fakeProvider,
+ const ecSignature = await signatureUtils.ecSignHashAsync(fakeProvider, orderHash, makerAddress);
+ expect(ecSignature).to.equal(expectedSignature);
+ });
+ it('should return a valid signature', async () => {
+ const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
+ const ecSignature = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress);
+
+ const isValidSignature = await signatureUtils.isValidSignatureAsync(
+ provider,
orderHash,
+ ecSignature,
makerAddress,
- SignerType.Default,
);
- expect(ecSignature).to.equal(expectedSignature);
+ expect(isValidSignature).to.be.true();
});
- // Note this is due to a bug in Metamask where it does not prefix before signing, this is a known issue and is to be fixed in the future
- // Source: https://github.com/MetaMask/metamask-extension/commit/a9d36860bec424dcee8db043d3e7da6a5ff5672e
- it('should receive a payload modified with a prefix when Metamask is SignerType', async () => {
- const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
- const orderHashPrefixed = '0xae70f31d26096291aa681b26cb7574563956221d0b4213631e1ef9df675d4cba';
+ });
+ describe('#ecSignTypedDataOrderAsync', () => {
+ it('should result in the same signature as signing the order hash without an ethereum message prefix', async () => {
+ // Note: Since order hash is an EIP712 hash the result of a valid EIP712 signature
+ // of order hash is the same as signing the order without the Ethereum Message prefix.
+ const orderHashHex = orderHashUtils.getOrderHashHex(order);
+ const sig = ethUtil.ecsign(
+ ethUtil.toBuffer(orderHashHex),
+ Buffer.from('F2F48EE19680706196E2E339E5DA3491186E0C4C5030670656B0E0164837257D', 'hex'),
+ );
+ const signatureBuffer = Buffer.concat([
+ ethUtil.toBuffer(sig.v),
+ ethUtil.toBuffer(sig.r),
+ ethUtil.toBuffer(sig.s),
+ ethUtil.toBuffer(SignatureType.EIP712),
+ ]);
+ const signatureHex = `0x${signatureBuffer.toString('hex')}`;
+ const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(provider, order, makerAddress);
+ const isValidSignature = await signatureUtils.isValidSignatureAsync(
+ provider,
+ orderHashHex,
+ signedOrder.signature,
+ makerAddress,
+ );
+ expect(signatureHex).to.eq(signedOrder.signature);
+ expect(isValidSignature).to.eq(true);
+ });
+ it('should return the correct Signature for signatureHex concatenated as R + S + V', async () => {
const expectedSignature =
- '0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03';
- // Generated from a MM eth_sign request from 0x5409ed021d9299bf6814279a6a1411a7e866a631 signing 0xae70f31d26096291aa681b26cb7574563956221d0b4213631e1ef9df675d4cba
- const metamaskSignature =
- '0x117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b1b';
+ '0x1cd472c439833774b55d248c31b6585f21aea1b9363ebb4ec58549e46b62eb5a6f696f5781f62de008ee7f77650ef940d99c97ec1dee67b3f5cea1bbfdfeb2eba602';
const fakeProvider = {
async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
- if (payload.method === 'eth_sign') {
- const [, message] = payload.params;
- expect(message).to.equal(orderHashPrefixed);
+ if (payload.method === 'eth_signTypedData') {
+ const [address, typedData] = payload.params;
+ const signature = await web3Wrapper.signTypedDataAsync(address, typedData);
callback(null, {
id: 42,
jsonrpc: '2.0',
- result: metamaskSignature,
+ result: signature,
});
} else {
callback(null, { id: 42, jsonrpc: '2.0', result: [makerAddress] });
}
},
};
-
- const ecSignature = await signatureUtils.ecSignOrderHashAsync(
- fakeProvider,
- orderHash,
- makerAddress,
- SignerType.Metamask,
- );
- expect(ecSignature).to.equal(expectedSignature);
- });
- it('should return a valid signature', async () => {
- const orderHash = '0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004';
- const ecSignature = await signatureUtils.ecSignOrderHashAsync(
- provider,
- orderHash,
- makerAddress,
- SignerType.Default,
- );
-
- const isValidSignature = await signatureUtils.isValidSignatureAsync(
- provider,
- orderHash,
- ecSignature,
- makerAddress,
- );
- expect(isValidSignature).to.be.true();
+ const signedOrder = await signatureUtils.ecSignTypedDataOrderAsync(fakeProvider, order, makerAddress);
+ expect(signedOrder.signature).to.equal(expectedSignature);
});
});
describe('#convertECSignatureToSignatureHex', () => {
@@ -256,38 +314,11 @@ describe('Signature utils', () => {
r: '0xaca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d64393',
s: '0x46b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf2',
};
- it('should concatenate v,r,s and append the EthSign signature type when SignerType is Default', async () => {
+ it('should concatenate v,r,s and append the EthSign signature type', async () => {
const expectedSignatureWithSignatureType =
'0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
- const signatureWithSignatureType = signatureUtils.convertECSignatureToSignatureHex(
- ecSignature,
- SignerType.Default,
- );
+ const signatureWithSignatureType = signatureUtils.convertECSignatureToSignatureHex(ecSignature);
expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
});
- it('should concatenate v,r,s and append the EthSign signature type when SignerType is Ledger', async () => {
- const expectedSignatureWithSignatureType =
- '0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
- const signatureWithSignatureType = signatureUtils.convertECSignatureToSignatureHex(
- ecSignature,
- SignerType.Ledger,
- );
- expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
- });
- it('should concatenate v,r,s and append the EthSign signature type when SignerType is Metamask', async () => {
- const expectedSignatureWithSignatureType =
- '0x1baca7da997ad177f040240cdccf6905b71ab16b74434388c3a72f34fd25d6439346b2bac274ff29b48b3ea6e2d04c1336eaceafda3c53ab483fc3ff12fac3ebf203';
- const signatureWithSignatureType = signatureUtils.convertECSignatureToSignatureHex(
- ecSignature,
- SignerType.Metamask,
- );
- expect(signatureWithSignatureType).to.equal(expectedSignatureWithSignatureType);
- });
- it('should throw if the SignerType is invalid', async () => {
- const expectedMessage = 'Unrecognized SignerType: INVALID_SIGNER';
- expect(() =>
- signatureUtils.convertECSignatureToSignatureHex(ecSignature, 'INVALID_SIGNER' as SignerType),
- ).to.throw(expectedMessage);
- });
});
});
diff --git a/packages/order-watcher/package.json b/packages/order-watcher/package.json
index 1b075b8ea..9bdaef5b1 100644
--- a/packages/order-watcher/package.json
+++ b/packages/order-watcher/package.json
@@ -82,7 +82,7 @@
"bintrees": "^1.0.2",
"ethereum-types": "^1.0.11",
"ethereumjs-blockstream": "6.0.0",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"lodash": "^4.17.5"
},
"publishConfig": {
diff --git a/packages/order-watcher/src/index.ts b/packages/order-watcher/src/index.ts
index d7ad4fba7..d2f91eab1 100644
--- a/packages/order-watcher/src/index.ts
+++ b/packages/order-watcher/src/index.ts
@@ -12,4 +12,10 @@ export {
export { OnOrderStateChangeCallback, OrderWatcherConfig } from './types';
export { SignedOrder } from '@0xproject/types';
-export { JSONRPCRequestPayload, JSONRPCErrorCallback, Provider, JSONRPCResponsePayload } from 'ethereum-types';
+export {
+ JSONRPCRequestPayload,
+ JSONRPCErrorCallback,
+ Provider,
+ JSONRPCResponsePayload,
+ JSONRPCResponseError,
+} from 'ethereum-types';
diff --git a/packages/sol-cov/src/index.ts b/packages/sol-cov/src/index.ts
index 15be86a9d..612d0869a 100644
--- a/packages/sol-cov/src/index.ts
+++ b/packages/sol-cov/src/index.ts
@@ -8,7 +8,13 @@ export { ProfilerSubprovider } from './profiler_subprovider';
export { RevertTraceSubprovider } from './revert_trace_subprovider';
export { ContractData } from './types';
-export { JSONRPCRequestPayload, Provider, JSONRPCErrorCallback, JSONRPCResponsePayload } from 'ethereum-types';
+export {
+ JSONRPCRequestPayload,
+ Provider,
+ JSONRPCErrorCallback,
+ JSONRPCResponsePayload,
+ JSONRPCResponseError,
+} from 'ethereum-types';
export {
JSONRPCRequestPayloadWithMethod,
diff --git a/packages/subproviders/CHANGELOG.json b/packages/subproviders/CHANGELOG.json
index 97f886f64..387207b01 100644
--- a/packages/subproviders/CHANGELOG.json
+++ b/packages/subproviders/CHANGELOG.json
@@ -1,5 +1,18 @@
[
{
+ "version": "2.1.0",
+ "changes": [
+ {
+ "note": "Add `MetamaskSubprovider` to handle inconsistent JSON RPC behaviour",
+ "pr": 1102
+ },
+ {
+ "note": "Add support for `eth_signTypedData` in wallets Mnemonic, Private and EthLightWallet",
+ "pr": 1102
+ }
+ ]
+ },
+ {
"version": "2.0.7",
"changes": [
{
diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json
index fad478349..ff3ab7ed5 100644
--- a/packages/subproviders/package.json
+++ b/packages/subproviders/package.json
@@ -45,7 +45,7 @@
"ethereum-types": "^1.0.11",
"ethereumjs-tx": "^1.3.5",
"ethereumjs-util": "^5.1.1",
- "ganache-core": "0xProject/ganache-core#monorepo-dep",
+ "ganache-core": "^2.2.1",
"hdkey": "^0.7.1",
"json-rpc-error": "2.0.0",
"lodash": "^4.17.5",
diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts
index b5f9b3f90..9f4dac58b 100644
--- a/packages/subproviders/src/index.ts
+++ b/packages/subproviders/src/index.ts
@@ -27,6 +27,7 @@ export { Subprovider } from './subproviders/subprovider';
export { NonceTrackerSubprovider } from './subproviders/nonce_tracker';
export { PrivateKeyWalletSubprovider } from './subproviders/private_key_wallet';
export { MnemonicWalletSubprovider } from './subproviders/mnemonic_wallet';
+export { MetamaskSubprovider } from './subproviders/metamask_subprovider';
export { EthLightwalletSubprovider } from './subproviders/eth_lightwallet_subprovider';
export {
@@ -47,6 +48,19 @@ export {
LedgerGetAddressResult,
} from './types';
-export { ECSignature } from '@0xproject/types';
+export {
+ ECSignature,
+ EIP712Object,
+ EIP712ObjectValue,
+ EIP712TypedData,
+ EIP712Types,
+ EIP712Parameter,
+} from '@0xproject/types';
-export { JSONRPCRequestPayload, Provider, JSONRPCResponsePayload, JSONRPCErrorCallback } from 'ethereum-types';
+export {
+ JSONRPCRequestPayload,
+ Provider,
+ JSONRPCResponsePayload,
+ JSONRPCErrorCallback,
+ JSONRPCResponseError,
+} from 'ethereum-types';
diff --git a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts b/packages/subproviders/src/subproviders/base_wallet_subprovider.ts
index 4342e47e9..409a0d330 100644
--- a/packages/subproviders/src/subproviders/base_wallet_subprovider.ts
+++ b/packages/subproviders/src/subproviders/base_wallet_subprovider.ts
@@ -23,6 +23,7 @@ export abstract class BaseWalletSubprovider extends Subprovider {
public abstract async getAccountsAsync(): Promise<string[]>;
public abstract async signTransactionAsync(txParams: PartialTxParams): Promise<string>;
public abstract async signPersonalMessageAsync(data: string, address: string): Promise<string>;
+ public abstract async signTypedDataAsync(address: string, typedData: any): Promise<string>;
/**
* This method conforms to the web3-provider-engine interface.
@@ -36,6 +37,8 @@ export abstract class BaseWalletSubprovider extends Subprovider {
public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
let accounts;
let txParams;
+ let address;
+ let typedData;
switch (payload.method) {
case 'eth_coinbase':
try {
@@ -86,7 +89,7 @@ export abstract class BaseWalletSubprovider extends Subprovider {
case 'eth_sign':
case 'personal_sign':
const data = payload.method === 'eth_sign' ? payload.params[1] : payload.params[0];
- const address = payload.method === 'eth_sign' ? payload.params[0] : payload.params[1];
+ address = payload.method === 'eth_sign' ? payload.params[0] : payload.params[1];
try {
const ecSignatureHex = await this.signPersonalMessageAsync(data, address);
end(null, ecSignatureHex);
@@ -94,6 +97,15 @@ export abstract class BaseWalletSubprovider extends Subprovider {
end(err);
}
return;
+ case 'eth_signTypedData':
+ [address, typedData] = payload.params;
+ try {
+ const signature = await this.signTypedDataAsync(address, typedData);
+ end(null, signature);
+ } catch (err) {
+ end(err);
+ }
+ return;
default:
next();
diff --git a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
index 6afd71422..a1d93ac49 100644
--- a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
+++ b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
@@ -1,3 +1,4 @@
+import { EIP712TypedData } from '@0xproject/types';
import * as lightwallet from 'eth-lightwallet';
import { PartialTxParams } from '../types';
@@ -48,16 +49,16 @@ export class EthLightwalletSubprovider extends BaseWalletSubprovider {
// Lightwallet loses the chain id information when hex encoding the transaction
// this results in a different signature on certain networks. PrivateKeyWallet
// respects this as it uses the parameters passed in
- let privKey = this._keystore.exportPrivateKey(txParams.from, this._pwDerivedKey);
- const privKeyWallet = new PrivateKeyWalletSubprovider(privKey);
- privKey = '';
- const privKeySignature = await privKeyWallet.signTransactionAsync(txParams);
- return privKeySignature;
+ let privateKey = this._keystore.exportPrivateKey(txParams.from, this._pwDerivedKey);
+ const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
+ privateKey = '';
+ const privateKeySignature = await privateKeyWallet.signTransactionAsync(txParams);
+ return privateKeySignature;
}
/**
* Sign a personal Ethereum signed message. The signing account will be the account
* associated with the provided address.
- * If you've added the MnemonicWalletSubprovider to your app's provider, you can simply send an `eth_sign`
+ * If you've added this Subprovider to your app's provider, you can simply send an `eth_sign`
* or `personal_sign` JSON RPC request, and this method will be called auto-magically.
* If you are not using this via a ProviderEngine instance, you can call it directly.
* @param data Hex string message to sign
@@ -65,10 +66,26 @@ export class EthLightwalletSubprovider extends BaseWalletSubprovider {
* @return Signature hex string (order: rsv)
*/
public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- let privKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey);
- const privKeyWallet = new PrivateKeyWalletSubprovider(privKey);
- privKey = '';
- const result = privKeyWallet.signPersonalMessageAsync(data, address);
+ let privateKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey);
+ const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
+ privateKey = '';
+ const result = privateKeyWallet.signPersonalMessageAsync(data, address);
+ return result;
+ }
+ /**
+ * Sign an EIP712 Typed Data message. The signing address will associated with the provided address.
+ * If you've added this Subprovider to your app's provider, you can simply send an `eth_signTypedData`
+ * JSON RPC request, and this method will be called auto-magically.
+ * If you are not using this via a ProviderEngine instance, you can call it directly.
+ * @param address Address of the account to sign with
+ * @param data the typed data object
+ * @return Signature hex string (order: rsv)
+ */
+ public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
+ let privateKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey);
+ const privateKeyWallet = new PrivateKeyWalletSubprovider(privateKey);
+ privateKey = '';
+ const result = privateKeyWallet.signTypedDataAsync(address, typedData);
return result;
}
}
diff --git a/packages/subproviders/src/subproviders/ledger.ts b/packages/subproviders/src/subproviders/ledger.ts
index 6ad5de2e2..ee8edde92 100644
--- a/packages/subproviders/src/subproviders/ledger.ts
+++ b/packages/subproviders/src/subproviders/ledger.ts
@@ -187,6 +187,16 @@ export class LedgerSubprovider extends BaseWalletSubprovider {
throw err;
}
}
+ /**
+ * eth_signTypedData is currently not supported on Ledger devices.
+ * @param address Address of the account to sign with
+ * @param data the typed data object
+ * @return Signature hex string (order: rsv)
+ */
+ // tslint:disable-next-line:prefer-function-over-method
+ public async signTypedDataAsync(address: string, typedData: any): Promise<string> {
+ throw new Error(WalletSubproviderErrors.MethodNotSupported);
+ }
private async _createLedgerClientAsync(): Promise<LedgerEthereumClient> {
await this._connectionLock.acquire();
if (!_.isUndefined(this._ledgerClientIfExists)) {
diff --git a/packages/subproviders/src/subproviders/metamask_subprovider.ts b/packages/subproviders/src/subproviders/metamask_subprovider.ts
new file mode 100644
index 000000000..46fc2a9cd
--- /dev/null
+++ b/packages/subproviders/src/subproviders/metamask_subprovider.ts
@@ -0,0 +1,126 @@
+import { marshaller, Web3Wrapper } from '@0xproject/web3-wrapper';
+import { JSONRPCRequestPayload, Provider } from 'ethereum-types';
+import * as ethUtil from 'ethereumjs-util';
+
+import { Callback, ErrorCallback } from '../types';
+
+import { Subprovider } from './subprovider';
+
+/**
+ * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine)
+ * subprovider interface and the provider sendAsync interface.
+ * It handles inconsistencies with Metamask implementations of various JSON RPC methods.
+ * It forwards JSON RPC requests involving the domain of a signer (getAccounts,
+ * sendTransaction, signMessage etc...) to the provider instance supplied at instantiation. All other requests
+ * are passed onwards for subsequent subproviders to handle.
+ */
+export class MetamaskSubprovider extends Subprovider {
+ private readonly _web3Wrapper: Web3Wrapper;
+ private readonly _provider: Provider;
+ /**
+ * Instantiates a new MetamaskSubprovider
+ * @param provider Web3 provider that should handle all user account related requests
+ */
+ constructor(provider: Provider) {
+ super();
+ this._web3Wrapper = new Web3Wrapper(provider);
+ this._provider = provider;
+ }
+ /**
+ * This method conforms to the web3-provider-engine interface.
+ * It is called internally by the ProviderEngine when it is this subproviders
+ * turn to handle a JSON RPC request.
+ * @param payload JSON RPC payload
+ * @param next Callback to call if this subprovider decides not to handle the request
+ * @param end Callback to call if subprovider handled the request and wants to pass back the request.
+ */
+ // tslint:disable-next-line:prefer-function-over-method async-suffix
+ public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
+ let message;
+ let address;
+ switch (payload.method) {
+ case 'web3_clientVersion':
+ try {
+ const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
+ end(null, nodeVersion);
+ } catch (err) {
+ end(err);
+ }
+ return;
+ case 'eth_accounts':
+ try {
+ const accounts = await this._web3Wrapper.getAvailableAddressesAsync();
+ end(null, accounts);
+ } catch (err) {
+ end(err);
+ }
+ return;
+ case 'eth_sendTransaction':
+ const [txParams] = payload.params;
+ try {
+ const txData = marshaller.unmarshalTxData(txParams);
+ const txHash = await this._web3Wrapper.sendTransactionAsync(txData);
+ end(null, txHash);
+ } catch (err) {
+ end(err);
+ }
+ return;
+ case 'eth_sign':
+ [address, message] = payload.params;
+ try {
+ // Metamask incorrectly implements eth_sign and does not prefix the message as per the spec
+ // Source: https://github.com/MetaMask/metamask-extension/commit/a9d36860bec424dcee8db043d3e7da6a5ff5672e
+ const msgBuff = ethUtil.toBuffer(message);
+ const prefixedMsgBuff = ethUtil.hashPersonalMessage(msgBuff);
+ const prefixedMsgHex = ethUtil.bufferToHex(prefixedMsgBuff);
+ const signature = await this._web3Wrapper.signMessageAsync(address, prefixedMsgHex);
+ signature ? end(null, signature) : end(new Error('Error performing eth_sign'), null);
+ } catch (err) {
+ end(err);
+ }
+ return;
+ case 'eth_signTypedData':
+ case 'eth_signTypedData_v3':
+ [address, message] = payload.params;
+ try {
+ // Metamask supports multiple versions and has namespaced signTypedData to v3 for an indeterminate period of time.
+ // eth_signTypedData is mapped to an older implementation before the spec was finalized.
+ // Source: https://github.com/MetaMask/metamask-extension/blob/c49d854b55b3efd34c7fd0414b76f7feaa2eec7c/app/scripts/metamask-controller.js#L1262
+ // and expects message to be serialised as JSON
+ const messageJSON = JSON.stringify(message);
+ const signature = await this._web3Wrapper.sendRawPayloadAsync<string>({
+ method: 'eth_signTypedData_v3',
+ params: [address, messageJSON],
+ });
+ signature ? end(null, signature) : end(new Error('Error performing eth_signTypedData'), null);
+ } catch (err) {
+ end(err);
+ }
+ return;
+ default:
+ next();
+ return;
+ }
+ }
+ /**
+ * This method conforms to the provider sendAsync interface.
+ * Allowing the MetamaskSubprovider to be used as a generic provider (outside of Web3ProviderEngine) with the
+ * addition of wrapping the inconsistent Metamask behaviour
+ * @param payload JSON RPC payload
+ * @return The contents nested under the result key of the response body
+ */
+ public sendAsync(payload: JSONRPCRequestPayload, callback: ErrorCallback): void {
+ void this.handleRequest(
+ payload,
+ // handleRequest has decided to not handle this, so fall through to the provider
+ () => {
+ const sendAsync = this._provider.sendAsync.bind(this._provider);
+ sendAsync(payload, callback);
+ },
+ // handleRequest has called end and will handle this
+ (err, data) => {
+ err ? callback(err) : callback(null, { ...payload, result: data });
+ },
+ );
+ }
+}
diff --git a/packages/subproviders/src/subproviders/mnemonic_wallet.ts b/packages/subproviders/src/subproviders/mnemonic_wallet.ts
index 1495112b6..04a11c7be 100644
--- a/packages/subproviders/src/subproviders/mnemonic_wallet.ts
+++ b/packages/subproviders/src/subproviders/mnemonic_wallet.ts
@@ -1,4 +1,5 @@
import { assert } from '@0xproject/assert';
+import { EIP712TypedData } from '@0xproject/types';
import { addressUtils } from '@0xproject/utils';
import * as bip39 from 'bip39';
import HDNode = require('hdkey');
@@ -90,10 +91,10 @@ export class MnemonicWalletSubprovider extends BaseWalletSubprovider {
}
/**
* Sign a personal Ethereum signed message. The signing account will be the account
- * associated with the provided address.
- * If you've added the MnemonicWalletSubprovider to your app's provider, you can simply send an `eth_sign`
- * or `personal_sign` JSON RPC request, and this method will be called auto-magically.
- * If you are not using this via a ProviderEngine instance, you can call it directly.
+ * associated with the provided address. If you've added the MnemonicWalletSubprovider to
+ * your app's provider, you can simply send an `eth_sign` or `personal_sign` JSON RPC request,
+ * and this method will be called auto-magically. If you are not using this via a ProviderEngine
+ * instance, you can call it directly.
* @param data Hex string message to sign
* @param address Address of the account to sign with
* @return Signature hex string (order: rsv)
@@ -108,6 +109,25 @@ export class MnemonicWalletSubprovider extends BaseWalletSubprovider {
const sig = await privateKeyWallet.signPersonalMessageAsync(data, address);
return sig;
}
+ /**
+ * Sign an EIP712 Typed Data message. The signing account will be the account
+ * associated with the provided address. If you've added this MnemonicWalletSubprovider to
+ * your app's provider, you can simply send an `eth_signTypedData` JSON RPC request, and
+ * this method will be called auto-magically. If you are not using this via a ProviderEngine
+ * instance, you can call it directly.
+ * @param address Address of the account to sign with
+ * @param data the typed data object
+ * @return Signature hex string (order: rsv)
+ */
+ public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
+ if (_.isUndefined(typedData)) {
+ throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
+ }
+ assert.isETHAddressHex('address', address);
+ const privateKeyWallet = this._privateKeyWalletForAddress(address);
+ const sig = await privateKeyWallet.signTypedDataAsync(address, typedData);
+ return sig;
+ }
private _privateKeyWalletForAddress(address: string): PrivateKeyWalletSubprovider {
const derivedKeyInfo = this._findDerivedKeyInfoForAddress(address);
const privateKeyHex = derivedKeyInfo.hdKey.privateKey.toString('hex');
diff --git a/packages/subproviders/src/subproviders/private_key_wallet.ts b/packages/subproviders/src/subproviders/private_key_wallet.ts
index 9d6fc487e..e89c4c186 100644
--- a/packages/subproviders/src/subproviders/private_key_wallet.ts
+++ b/packages/subproviders/src/subproviders/private_key_wallet.ts
@@ -1,4 +1,6 @@
import { assert } from '@0xproject/assert';
+import { EIP712TypedData } from '@0xproject/types';
+import { signTypedDataUtils } from '@0xproject/utils';
import EthereumTx = require('ethereumjs-tx');
import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
@@ -23,7 +25,7 @@ export class PrivateKeyWalletSubprovider extends BaseWalletSubprovider {
constructor(privateKey: string) {
assert.isString('privateKey', privateKey);
super();
- this._privateKeyBuffer = new Buffer(privateKey, 'hex');
+ this._privateKeyBuffer = Buffer.from(privateKey, 'hex');
this._address = `0x${ethUtil.privateToAddress(this._privateKeyBuffer).toString('hex')}`;
}
/**
@@ -84,4 +86,29 @@ export class PrivateKeyWalletSubprovider extends BaseWalletSubprovider {
const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s);
return rpcSig;
}
+ /**
+ * Sign an EIP712 Typed Data message. The signing address will be calculated from the private key.
+ * The address must be provided it must match the address calculated from the private key.
+ * If you've added this Subprovider to your app's provider, you can simply send an `eth_signTypedData`
+ * JSON RPC request, and this method will be called auto-magically.
+ * If you are not using this via a ProviderEngine instance, you can call it directly.
+ * @param address Address of the account to sign with
+ * @param data the typed data object
+ * @return Signature hex string (order: rsv)
+ */
+ public async signTypedDataAsync(address: string, typedData: EIP712TypedData): Promise<string> {
+ if (_.isUndefined(typedData)) {
+ throw new Error(WalletSubproviderErrors.DataMissingForSignTypedData);
+ }
+ assert.isETHAddressHex('address', address);
+ if (address !== this._address) {
+ throw new Error(
+ `Requested to sign message with address: ${address}, instantiated with address: ${this._address}`,
+ );
+ }
+ const dataBuff = signTypedDataUtils.generateTypedDataHash(typedData);
+ const sig = ethUtil.ecsign(dataBuff, this._privateKeyBuffer);
+ const rpcSig = ethUtil.toRpcSig(sig.v, sig.r, sig.s);
+ return rpcSig;
+ }
}
diff --git a/packages/subproviders/src/subproviders/signer.ts b/packages/subproviders/src/subproviders/signer.ts
index d5fd86897..eda7db42e 100644
--- a/packages/subproviders/src/subproviders/signer.ts
+++ b/packages/subproviders/src/subproviders/signer.ts
@@ -14,7 +14,7 @@ import { Subprovider } from './subprovider';
export class SignerSubprovider extends Subprovider {
private readonly _web3Wrapper: Web3Wrapper;
/**
- * Instantiates a new SignerSubprovider
+ * Instantiates a new SignerSubprovider.
* @param provider Web3 provider that should handle all user account related requests
*/
constructor(provider: Provider) {
@@ -31,6 +31,8 @@ export class SignerSubprovider extends Subprovider {
*/
// tslint:disable-next-line:prefer-function-over-method async-suffix
public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
+ let message;
+ let address;
switch (payload.method) {
case 'web3_clientVersion':
try {
@@ -59,7 +61,7 @@ export class SignerSubprovider extends Subprovider {
}
return;
case 'eth_sign':
- const [address, message] = payload.params;
+ [address, message] = payload.params;
try {
const signature = await this._web3Wrapper.signMessageAsync(address, message);
end(null, signature);
@@ -67,6 +69,15 @@ export class SignerSubprovider extends Subprovider {
end(err);
}
return;
+ case 'eth_signTypedData':
+ [address, message] = payload.params;
+ try {
+ const signature = await this._web3Wrapper.signTypedDataAsync(address, message);
+ end(null, signature);
+ } catch (err) {
+ end(err);
+ }
+ return;
default:
next();
return;
diff --git a/packages/subproviders/src/types.ts b/packages/subproviders/src/types.ts
index fe58bffa5..e8a47ad34 100644
--- a/packages/subproviders/src/types.ts
+++ b/packages/subproviders/src/types.ts
@@ -107,8 +107,10 @@ export interface ResponseWithTxParams {
export enum WalletSubproviderErrors {
AddressNotFound = 'ADDRESS_NOT_FOUND',
DataMissingForSignPersonalMessage = 'DATA_MISSING_FOR_SIGN_PERSONAL_MESSAGE',
+ DataMissingForSignTypedData = 'DATA_MISSING_FOR_SIGN_TYPED_DATA',
SenderInvalidOrNotSupplied = 'SENDER_INVALID_OR_NOT_SUPPLIED',
FromAddressMissingOrInvalid = 'FROM_ADDRESS_MISSING_OR_INVALID',
+ MethodNotSupported = 'METHOD_NOT_SUPPORTED',
}
export enum LedgerSubproviderErrors {
TooOldLedgerFirmware = 'TOO_OLD_LEDGER_FIRMWARE',
diff --git a/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts b/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts
index 063817a95..49698ce9e 100644
--- a/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts
+++ b/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts
@@ -73,6 +73,13 @@ describe('EthLightwalletSubprovider', () => {
const txHex = await ethLightwalletSubprovider.signTransactionAsync(fixtureData.TX_DATA);
expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
});
+ it('signs an EIP712 sign typed data message', async () => {
+ const signature = await ethLightwalletSubprovider.signTypedDataAsync(
+ fixtureData.TEST_RPC_ACCOUNT_0,
+ fixtureData.EIP712_TEST_TYPED_DATA,
+ );
+ expect(signature).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
+ });
});
});
describe('calls through a provider', () => {
@@ -129,6 +136,20 @@ describe('EthLightwalletSubprovider', () => {
});
provider.sendAsync(payload, callback);
});
+ it('signs an EIP712 sign typed data message with eth_signTypedData', (done: DoneCallback) => {
+ const payload = {
+ jsonrpc: '2.0',
+ method: 'eth_signTypedData',
+ params: [fixtureData.TEST_RPC_ACCOUNT_0, fixtureData.EIP712_TEST_TYPED_DATA],
+ id: 1,
+ };
+ const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
+ expect(err).to.be.a('null');
+ expect(response.result).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
+ done();
+ });
+ provider.sendAsync(payload, callback);
+ });
});
describe('failure cases', () => {
it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
diff --git a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts
index f2bdda3cd..61dcbf6da 100644
--- a/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts
+++ b/packages/subproviders/test/unit/mnemonic_wallet_subprovider_test.ts
@@ -47,6 +47,13 @@ describe('MnemonicWalletSubprovider', () => {
const txHex = await subprovider.signTransactionAsync(txData);
expect(txHex).to.be.equal(fixtureData.TX_DATA_ACCOUNT_1_SIGNED_RESULT);
});
+ it('signs an EIP712 sign typed data message', async () => {
+ const signature = await subprovider.signTypedDataAsync(
+ fixtureData.TEST_RPC_ACCOUNT_0,
+ fixtureData.EIP712_TEST_TYPED_DATA,
+ );
+ expect(signature).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
+ });
});
describe('failure cases', () => {
it('throws an error if address is invalid ', async () => {
@@ -118,6 +125,20 @@ describe('MnemonicWalletSubprovider', () => {
});
provider.sendAsync(payload, callback);
});
+ it('signs an EIP712 sign typed data message with eth_signTypedData', (done: DoneCallback) => {
+ const payload = {
+ jsonrpc: '2.0',
+ method: 'eth_signTypedData',
+ params: [fixtureData.TEST_RPC_ACCOUNT_0, fixtureData.EIP712_TEST_TYPED_DATA],
+ id: 1,
+ };
+ const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
+ expect(err).to.be.a('null');
+ expect(response.result).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
+ done();
+ });
+ provider.sendAsync(payload, callback);
+ });
});
describe('failure cases', () => {
it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
diff --git a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts
index 95773145f..4cd70e5ed 100644
--- a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts
+++ b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts
@@ -32,6 +32,13 @@ describe('PrivateKeyWalletSubprovider', () => {
const txHex = await subprovider.signTransactionAsync(fixtureData.TX_DATA);
expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
});
+ it('signs an EIP712 sign typed data message', async () => {
+ const signature = await subprovider.signTypedDataAsync(
+ fixtureData.TEST_RPC_ACCOUNT_0,
+ fixtureData.EIP712_TEST_TYPED_DATA,
+ );
+ expect(signature).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
+ });
});
});
describe('calls through a provider', () => {
@@ -103,6 +110,20 @@ describe('PrivateKeyWalletSubprovider', () => {
});
provider.sendAsync(payload, callback);
});
+ it('signs an EIP712 sign typed data message with eth_signTypedData', (done: DoneCallback) => {
+ const payload = {
+ jsonrpc: '2.0',
+ method: 'eth_signTypedData',
+ params: [fixtureData.TEST_RPC_ACCOUNT_0, fixtureData.EIP712_TEST_TYPED_DATA],
+ id: 1,
+ };
+ const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
+ expect(err).to.be.a('null');
+ expect(response.result).to.be.equal(fixtureData.EIP712_TEST_TYPED_DATA_SIGNED_RESULT);
+ done();
+ });
+ provider.sendAsync(payload, callback);
+ });
});
describe('failure cases', () => {
it('should throw if `data` param not hex when calling eth_sign', (done: DoneCallback) => {
diff --git a/packages/subproviders/test/utils/fixture_data.ts b/packages/subproviders/test/utils/fixture_data.ts
index 7cf502c97..3eb4493b5 100644
--- a/packages/subproviders/test/utils/fixture_data.ts
+++ b/packages/subproviders/test/utils/fixture_data.ts
@@ -30,4 +30,35 @@ export const fixtureData = {
'0xf85f8080822710940000000000000000000000000000000000000000808078a0712854c73c69445cc1b22a7c3d7312ff9a97fe4ffba35fd636e8236b211b6e7ca0647cee031615e52d916c7c707025bc64ad525d8f1b9876c3435a863b42743178',
TX_DATA_ACCOUNT_1_SIGNED_RESULT:
'0xf85f8080822710940000000000000000000000000000000000000000808078a04b02af7ff3f18ce114b601542cc8ebdc50921354f75dd510d31793453a0710e6a0540082a01e475465801b8186a2edc79ec1a2dcf169b9781c25a58a417023c9ca',
+ EIP712_TEST_TYPED_DATA: {
+ types: {
+ EIP712Domain: [
+ {
+ name: 'name',
+ type: 'string',
+ },
+ ],
+ Test: [
+ {
+ name: 'testAddress',
+ type: 'address',
+ },
+ {
+ name: 'testNumber',
+ type: 'uint256',
+ },
+ ],
+ },
+ domain: {
+ name: 'Test',
+ },
+ message: {
+ testAddress: '0x0000000000000000000000000000000000000000',
+ testNumber: '12345',
+ },
+ primaryType: 'Test',
+ },
+ EIP712_TEST_TYPED_DATA_HASH: '0xb460d69ca60383293877cd765c0f97bd832d66bca720f7e32222ce1118832493',
+ EIP712_TEST_TYPED_DATA_SIGNED_RESULT:
+ '0x20af5b6bfc3658942198d6eeda159b4ed589f90cee6eac3ba117818ffba5fd7e354a353aad93faabd6eb6c66e17921c92bd1cd09c92a770f554470dc3e254ce701',
};
diff --git a/packages/testnet-faucets/gulpfile.js b/packages/testnet-faucets/gulpfile.js
index 7c4e25e0f..839ef851b 100644
--- a/packages/testnet-faucets/gulpfile.js
+++ b/packages/testnet-faucets/gulpfile.js
@@ -14,10 +14,7 @@ const config = {
},
devtool: 'source-map',
resolve: {
- modules: [
- path.join(__dirname, '/src/ts'),
- 'node_modules',
- ],
+ modules: [path.join(__dirname, '/src/ts'), 'node_modules'],
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
alias: {
ts: path.join(__dirname, '/src/ts'),
@@ -44,10 +41,10 @@ const config = {
}),
],
externals: nodeExternals({
- modulesDir: path.join(__dirname, '../../node_modules')
+ modulesDir: path.join(__dirname, '../../node_modules'),
}),
watchOptions: {
- ignored: /server|node_modules|transpiled/
+ ignored: /server|node_modules|transpiled/,
},
};
@@ -77,16 +74,18 @@ gulp.task('run', ['watch'], function() {
});
function onBuild(done) {
- return function(err, stats) {
- if(err) {
- console.log('Error', err);
- }
- else {
- console.log(stats.toString());
- }
-
- if(done) {
- done();
- }
- }
+ return function(err, stats) {
+ if (err) {
+ console.log('Error', err);
+ process.exit(1);
+ } else {
+ console.log(stats.toString());
+ }
+ if (done) {
+ if (stats.compilation.errors && stats.compilation.errors.length > 0) {
+ process.exit(1);
+ }
+ done();
+ }
+ };
}
diff --git a/packages/testnet-faucets/src/ts/handler.ts b/packages/testnet-faucets/src/ts/handler.ts
index e73eb1744..be42ebde8 100644
--- a/packages/testnet-faucets/src/ts/handler.ts
+++ b/packages/testnet-faucets/src/ts/handler.ts
@@ -9,7 +9,6 @@ import {
RPCSubprovider,
signatureUtils,
SignedOrder,
- SignerType,
Web3ProviderEngine,
} from '0x.js';
import { NonceTrackerSubprovider, PrivateKeyWalletSubprovider } from '@0xproject/subproviders';
@@ -180,11 +179,10 @@ export class Handler {
expirationTimeSeconds: new BigNumber(Date.now() + FIVE_DAYS_IN_MS).div(1000).floor(),
};
const orderHash = orderHashUtils.getOrderHashHex(order);
- const signature = await signatureUtils.ecSignOrderHashAsync(
+ const signature = await signatureUtils.ecSignHashAsync(
networkConfig.web3Wrapper.getProvider(),
orderHash,
configs.DISPENSER_ADDRESS,
- SignerType.Default,
);
const signedOrder: SignedOrder = {
...order,
diff --git a/packages/types/CHANGELOG.json b/packages/types/CHANGELOG.json
index 6bb6ced70..53e1f3716 100644
--- a/packages/types/CHANGELOG.json
+++ b/packages/types/CHANGELOG.json
@@ -1,5 +1,18 @@
[
{
+ "version": "1.2.0",
+ "changes": [
+ {
+ "note": "Added `EIP712Parameter` `EIP712Types` `EIP712TypedData` for EIP712 signing",
+ "pr": 1102
+ },
+ {
+ "note": "Added `ZeroExTransaction` type for Exchange executeTransaction",
+ "pr": 1102
+ }
+ ]
+ },
+ {
"timestamp": 1538693146,
"version": "1.1.4",
"changes": [
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 3ae0536d5..6bc966ba1 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -42,6 +42,15 @@ export interface SignedOrder extends Order {
}
/**
+ * ZeroExTransaction for use with 0x Exchange executeTransaction
+ */
+export interface ZeroExTransaction {
+ salt: BigNumber;
+ signerAddress: string;
+ data: string;
+}
+
+/**
* Elliptic Curve signature
*/
export interface ECSignature {
@@ -143,16 +152,6 @@ export enum SignatureType {
NSignatureTypes,
}
-/**
- * The type of the Signer implementation. Some signer implementations use different message prefixes or implement different
- * eth_sign behaviour (e.g Metamask). Default assumes a spec compliant `eth_sign`.
- */
-export enum SignerType {
- Default = 'DEFAULT',
- Ledger = 'LEDGER',
- Metamask = 'METAMASK',
-}
-
export enum AssetProxyId {
ERC20 = '0xf47261b0',
ERC721 = '0x02571792',
@@ -599,3 +598,25 @@ export interface Metadata {
externalTypeToLink: ExternalTypeToLink;
externalExportToLink: ExternalExportToLink;
}
+
+export interface EIP712Parameter {
+ name: string;
+ type: string;
+}
+
+export interface EIP712Types {
+ [key: string]: EIP712Parameter[];
+}
+
+export type EIP712ObjectValue = string | number | EIP712Object;
+
+export interface EIP712Object {
+ [key: string]: EIP712ObjectValue;
+}
+
+export interface EIP712TypedData {
+ types: EIP712Types;
+ domain: EIP712Object;
+ message: EIP712Object;
+ primaryType: string;
+}
diff --git a/packages/utils/package.json b/packages/utils/package.json
index f1017f84d..20b0f0c86 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -50,7 +50,7 @@
"detect-node": "2.0.3",
"ethereum-types": "^1.0.11",
"ethereumjs-util": "^5.1.1",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"isomorphic-fetch": "^2.2.1",
"js-sha3": "^0.7.0",
"lodash": "^4.17.5"
diff --git a/packages/utils/src/abi_decoder.ts b/packages/utils/src/abi_decoder.ts
index ea8c91d10..ac3e54efb 100644
--- a/packages/utils/src/abi_decoder.ts
+++ b/packages/utils/src/abi_decoder.ts
@@ -9,7 +9,7 @@ import {
RawLog,
SolidityTypes,
} from 'ethereum-types';
-import * as ethers from 'ethers';
+import { ethers } from 'ethers';
import * as _ from 'lodash';
import { addressUtils } from './address_utils';
@@ -41,7 +41,7 @@ export class AbiDecoder {
return log;
}
const event = this._methodIds[methodId][numIndexedArgs];
- const ethersInterface = new ethers.Interface([event]);
+ const ethersInterface = new ethers.utils.Interface([event]);
const decodedParams: DecodedLogArgs = {};
let topicsIndex = 1;
@@ -96,7 +96,7 @@ export class AbiDecoder {
if (_.isUndefined(abiArray)) {
return;
}
- const ethersInterface = new ethers.Interface(abiArray);
+ const ethersInterface = new ethers.utils.Interface(abiArray);
_.map(abiArray, (abi: AbiDefinition) => {
if (abi.type === AbiType.Event) {
const topic = ethersInterface.events[abi.name].topic;
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index 9d01e5bc5..0723e5788 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -9,3 +9,4 @@ export { abiUtils } from './abi_utils';
export { NULL_BYTES } from './constants';
export { errorUtils } from './error_utils';
export { fetchAsync } from './fetch_async';
+export { signTypedDataUtils } from './sign_typed_data_utils';
diff --git a/packages/utils/src/sign_typed_data_utils.ts b/packages/utils/src/sign_typed_data_utils.ts
new file mode 100644
index 000000000..cd5bcb42f
--- /dev/null
+++ b/packages/utils/src/sign_typed_data_utils.ts
@@ -0,0 +1,82 @@
+import * as ethUtil from 'ethereumjs-util';
+import * as ethers from 'ethers';
+import * as _ from 'lodash';
+
+import { EIP712Object, EIP712ObjectValue, EIP712TypedData, EIP712Types } from '@0xproject/types';
+
+export const signTypedDataUtils = {
+ /**
+ * Generates the EIP712 Typed Data hash for signing
+ * @param typedData An object that conforms to the EIP712TypedData interface
+ * @return A Buffer containing the hash of the typed data.
+ */
+ generateTypedDataHash(typedData: EIP712TypedData): Buffer {
+ return ethUtil.sha3(
+ Buffer.concat([
+ Buffer.from('1901', 'hex'),
+ signTypedDataUtils._structHash('EIP712Domain', typedData.domain, typedData.types),
+ signTypedDataUtils._structHash(typedData.primaryType, typedData.message, typedData.types),
+ ]),
+ );
+ },
+ _findDependencies(primaryType: string, types: EIP712Types, found: string[] = []): string[] {
+ if (found.includes(primaryType) || types[primaryType] === undefined) {
+ return found;
+ }
+ found.push(primaryType);
+ for (const field of types[primaryType]) {
+ for (const dep of signTypedDataUtils._findDependencies(field.type, types, found)) {
+ if (!found.includes(dep)) {
+ found.push(dep);
+ }
+ }
+ }
+ return found;
+ },
+ _encodeType(primaryType: string, types: EIP712Types): string {
+ let deps = signTypedDataUtils._findDependencies(primaryType, types);
+ deps = deps.filter(d => d !== primaryType);
+ deps = [primaryType].concat(deps.sort());
+ let result = '';
+ for (const dep of deps) {
+ result += `${dep}(${types[dep].map(({ name, type }) => `${type} ${name}`).join(',')})`;
+ }
+ return result;
+ },
+ _encodeData(primaryType: string, data: EIP712Object, types: EIP712Types): string {
+ const encodedTypes = ['bytes32'];
+ const encodedValues: Array<Buffer | EIP712ObjectValue> = [signTypedDataUtils._typeHash(primaryType, types)];
+ for (const field of types[primaryType]) {
+ const value = data[field.name];
+ if (field.type === 'string' || field.type === 'bytes') {
+ const hashValue = ethUtil.sha3(value as string);
+ encodedTypes.push('bytes32');
+ encodedValues.push(hashValue);
+ } else if (types[field.type] !== undefined) {
+ encodedTypes.push('bytes32');
+ const hashValue = ethUtil.sha3(
+ // tslint:disable-next-line:no-unnecessary-type-assertion
+ signTypedDataUtils._encodeData(field.type, value as EIP712Object, types),
+ );
+ encodedValues.push(hashValue);
+ } else if (field.type.lastIndexOf(']') === field.type.length - 1) {
+ throw new Error('Arrays currently unimplemented in encodeData');
+ } else {
+ encodedTypes.push(field.type);
+ const normalizedValue = signTypedDataUtils._normalizeValue(field.type, value);
+ encodedValues.push(normalizedValue);
+ }
+ }
+ return ethers.utils.defaultAbiCoder.encode(encodedTypes, encodedValues);
+ },
+ _normalizeValue(type: string, value: any): EIP712ObjectValue {
+ const normalizedValue = type === 'uint256' && _.isObject(value) && value.isBigNumber ? value.toString() : value;
+ return normalizedValue;
+ },
+ _typeHash(primaryType: string, types: EIP712Types): Buffer {
+ return ethUtil.sha3(signTypedDataUtils._encodeType(primaryType, types));
+ },
+ _structHash(primaryType: string, data: EIP712Object, types: EIP712Types): Buffer {
+ return ethUtil.sha3(signTypedDataUtils._encodeData(primaryType, data, types));
+ },
+};
diff --git a/packages/utils/test/sign_typed_data_utils_test.ts b/packages/utils/test/sign_typed_data_utils_test.ts
new file mode 100644
index 000000000..dcba08b04
--- /dev/null
+++ b/packages/utils/test/sign_typed_data_utils_test.ts
@@ -0,0 +1,140 @@
+import * as chai from 'chai';
+import 'mocha';
+
+import { signTypedDataUtils } from '../src/sign_typed_data_utils';
+
+const expect = chai.expect;
+
+describe('signTypedDataUtils', () => {
+ describe('signTypedDataHash', () => {
+ const simpleSignTypedDataHashHex = '0xb460d69ca60383293877cd765c0f97bd832d66bca720f7e32222ce1118832493';
+ const simpleSignTypedData = {
+ types: {
+ EIP712Domain: [
+ {
+ name: 'name',
+ type: 'string',
+ },
+ ],
+ Test: [
+ {
+ name: 'testAddress',
+ type: 'address',
+ },
+ {
+ name: 'testNumber',
+ type: 'uint256',
+ },
+ ],
+ },
+ domain: {
+ name: 'Test',
+ },
+ message: {
+ testAddress: '0x0000000000000000000000000000000000000000',
+ testNumber: '12345',
+ },
+ primaryType: 'Test',
+ };
+ const orderSignTypedDataHashHex = '0x55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692';
+ const orderSignTypedData = {
+ types: {
+ EIP712Domain: [
+ {
+ name: 'name',
+ type: 'string',
+ },
+ {
+ name: 'version',
+ type: 'string',
+ },
+ {
+ name: 'verifyingContract',
+ type: 'address',
+ },
+ ],
+ Order: [
+ {
+ name: 'makerAddress',
+ type: 'address',
+ },
+ {
+ name: 'takerAddress',
+ type: 'address',
+ },
+ {
+ name: 'feeRecipientAddress',
+ type: 'address',
+ },
+ {
+ name: 'senderAddress',
+ type: 'address',
+ },
+ {
+ name: 'makerAssetAmount',
+ type: 'uint256',
+ },
+ {
+ name: 'takerAssetAmount',
+ type: 'uint256',
+ },
+ {
+ name: 'makerFee',
+ type: 'uint256',
+ },
+ {
+ name: 'takerFee',
+ type: 'uint256',
+ },
+ {
+ name: 'expirationTimeSeconds',
+ type: 'uint256',
+ },
+ {
+ name: 'salt',
+ type: 'uint256',
+ },
+ {
+ name: 'makerAssetData',
+ type: 'bytes',
+ },
+ {
+ name: 'takerAssetData',
+ type: 'bytes',
+ },
+ ],
+ },
+ domain: {
+ name: '0x Protocol',
+ version: '2',
+ verifyingContract: '0x0000000000000000000000000000000000000000',
+ },
+ message: {
+ makerAddress: '0x0000000000000000000000000000000000000000',
+ takerAddress: '0x0000000000000000000000000000000000000000',
+ makerAssetAmount: '1000000000000000000',
+ takerAssetAmount: '1000000000000000000',
+ expirationTimeSeconds: '12345',
+ makerFee: '0',
+ takerFee: '0',
+ feeRecipientAddress: '0x0000000000000000000000000000000000000000',
+ senderAddress: '0x0000000000000000000000000000000000000000',
+ salt: '12345',
+ makerAssetData: '0x0000000000000000000000000000000000000000',
+ takerAssetData: '0x0000000000000000000000000000000000000000',
+ exchangeAddress: '0x0000000000000000000000000000000000000000',
+ },
+ primaryType: 'Order',
+ };
+ it('creates a hash of the test sign typed data', () => {
+ const hash = signTypedDataUtils.generateTypedDataHash(simpleSignTypedData).toString('hex');
+ const hashHex = `0x${hash}`;
+ expect(hashHex).to.be.eq(simpleSignTypedDataHashHex);
+ });
+ it('creates a hash of the order sign typed data', () => {
+ const hash = signTypedDataUtils.generateTypedDataHash(orderSignTypedData).toString('hex');
+ const hashHex = `0x${hash}`;
+ expect(hashHex).to.be.eq(orderSignTypedDataHashHex);
+ });
+ });
+});
diff --git a/packages/web3-wrapper/CHANGELOG.json b/packages/web3-wrapper/CHANGELOG.json
index 47f054300..be5c1fef6 100644
--- a/packages/web3-wrapper/CHANGELOG.json
+++ b/packages/web3-wrapper/CHANGELOG.json
@@ -1,5 +1,19 @@
[
{
+ "version": "3.1.0",
+ "changes": [
+ {
+ "note": "Add `signTypedData` to perform EIP712 `eth_signTypedData`.",
+ "pr": 1102
+ },
+ {
+ "note":
+ "Web3Wrapper now throws when an RPC request contains an error field in the response. Previously errors could be swallowed and undefined returned.",
+ "pr": 1102
+ }
+ ]
+ },
+ {
"version": "3.0.3",
"changes": [
{
diff --git a/packages/web3-wrapper/package.json b/packages/web3-wrapper/package.json
index ef31a68dc..a3f82c87e 100644
--- a/packages/web3-wrapper/package.json
+++ b/packages/web3-wrapper/package.json
@@ -60,7 +60,7 @@
"@0xproject/utils": "^2.0.2",
"ethereum-types": "^1.0.11",
"ethereumjs-util": "^5.1.1",
- "ethers": "4.0.0-beta.14",
+ "ethers": "~4.0.4",
"lodash": "^4.17.5"
},
"publishConfig": {
diff --git a/packages/web3-wrapper/src/index.ts b/packages/web3-wrapper/src/index.ts
index 7cdd25e55..9bef06fd4 100644
--- a/packages/web3-wrapper/src/index.ts
+++ b/packages/web3-wrapper/src/index.ts
@@ -30,6 +30,7 @@ export {
OpCode,
TxDataPayable,
JSONRPCResponsePayload,
+ JSONRPCResponseError,
RawLogEntry,
DecodedLogEntryEvent,
LogWithDecodedArgs,
diff --git a/packages/web3-wrapper/src/web3_wrapper.ts b/packages/web3-wrapper/src/web3_wrapper.ts
index d52c1cb6e..726246f1a 100644
--- a/packages/web3-wrapper/src/web3_wrapper.ts
+++ b/packages/web3-wrapper/src/web3_wrapper.ts
@@ -315,6 +315,21 @@ export class Web3Wrapper {
return signData;
}
/**
+ * Sign an EIP712 typed data message with a specific address's private key (`eth_signTypedData`)
+ * @param address Address of signer
+ * @param typedData Typed data message to sign
+ * @returns Signature string (as RSV)
+ */
+ public async signTypedDataAsync(address: string, typedData: any): Promise<string> {
+ assert.isETHAddressHex('address', address);
+ assert.doesConformToSchema('typedData', typedData, schemas.eip712TypedDataSchema);
+ const signData = await this.sendRawPayloadAsync<string>({
+ method: 'eth_signTypedData',
+ params: [address, typedData],
+ });
+ return signData;
+ }
+ /**
* Fetches the latest block number
* @returns Block number
*/
@@ -654,6 +669,9 @@ export class Web3Wrapper {
...payload,
};
const response = await promisify<JSONRPCResponsePayload>(sendAsync)(payloadWithDefaults);
+ if (response.error) {
+ throw new Error(response.error.message);
+ }
const result = response.result;
return result;
}
diff --git a/packages/web3-wrapper/test/web3_wrapper_test.ts b/packages/web3-wrapper/test/web3_wrapper_test.ts
index 385c469bf..164253777 100644
--- a/packages/web3-wrapper/test/web3_wrapper_test.ts
+++ b/packages/web3-wrapper/test/web3_wrapper_test.ts
@@ -1,5 +1,5 @@
import * as chai from 'chai';
-import { BlockParamLiteral } from 'ethereum-types';
+import { BlockParamLiteral, JSONRPCErrorCallback, JSONRPCRequestPayload } from 'ethereum-types';
import * as Ganache from 'ganache-core';
import * as _ from 'lodash';
import 'mocha';
@@ -78,6 +78,19 @@ describe('Web3Wrapper tests', () => {
const signatureLength = 132;
expect(signature.length).to.be.equal(signatureLength);
});
+ it('should throw if the provider returns an error', async () => {
+ const message = '0xdeadbeef';
+ const signer = addresses[1];
+ const fakeProvider = {
+ async sendAsync(payload: JSONRPCRequestPayload, callback: JSONRPCErrorCallback): Promise<void> {
+ callback(new Error('User denied message signature'));
+ },
+ };
+ const errorWeb3Wrapper = new Web3Wrapper(fakeProvider);
+ expect(errorWeb3Wrapper.signMessageAsync(signer, message)).to.be.rejectedWith(
+ 'User denied message signature',
+ );
+ });
});
describe('#getBlockNumberAsync', () => {
it('get block number', async () => {
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index c420bbf3a..b1181e4c6 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -9,11 +9,12 @@ import {
ExchangeFillEventArgs,
IndexedFilterValues,
} from '@0xproject/contract-wrappers';
-import { assetDataUtils, orderHashUtils, signatureUtils, SignerType } from '@0xproject/order-utils';
+import { assetDataUtils, orderHashUtils, signatureUtils } from '@0xproject/order-utils';
import { EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared';
import {
ledgerEthereumBrowserClientFactoryAsync,
LedgerSubprovider,
+ MetamaskSubprovider,
RedundantSubprovider,
RPCSubprovider,
SignerSubprovider,
@@ -27,8 +28,6 @@ import * as _ from 'lodash';
import * as moment from 'moment';
import * as React from 'react';
import contract = require('truffle-contract');
-import { tokenAddressOverrides } from 'ts/utils/token_address_overrides';
-
import { BlockchainWatcher } from 'ts/blockchain_watcher';
import { AssetSendCompleted } from 'ts/components/flash_messages/asset_send_completed';
import { TransactionSubmitted } from 'ts/components/flash_messages/transaction_submitted';
@@ -54,6 +53,7 @@ import { backendClient } from 'ts/utils/backend_client';
import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
import { errorReporter } from 'ts/utils/error_reporter';
+import { tokenAddressOverrides } from 'ts/utils/token_address_overrides';
import { utils } from 'ts/utils/utils';
import FilterSubprovider = require('web3-provider-engine/subproviders/filters');
@@ -161,7 +161,13 @@ export class Blockchain {
// We catch all requests involving a users account and send it to the injectedWeb3
// instance. All other requests go to the public hosted node.
const provider = new Web3ProviderEngine();
- provider.addProvider(new SignerSubprovider(injectedWeb3.currentProvider));
+ const providerName = this._getNameGivenProvider(injectedWeb3.currentProvider);
+ // Wrap Metamask in a compatability wrapper MetamaskSubprovider (to handle inconsistencies)
+ const signerSubprovider =
+ providerName === Providers.Metamask
+ ? new MetamaskSubprovider(injectedWeb3.currentProvider)
+ : new SignerSubprovider(injectedWeb3.currentProvider);
+ provider.addProvider(signerSubprovider);
provider.addProvider(new FilterSubprovider());
const rpcSubproviders = _.map(publicNodeUrlsIfExistsForNetworkId, publicNodeUrl => {
return new RPCSubprovider(publicNodeUrl);
@@ -432,21 +438,7 @@ export class Blockchain {
}
this._showFlashMessageIfLedger();
const provider = this._contractWrappers.getProvider();
- const isLedgerSigner = !_.isUndefined(this._ledgerSubprovider);
- const injectedProvider = Blockchain._getInjectedWeb3().currentProvider;
- const isMetaMaskSigner = utils.getProviderType(injectedProvider) === Providers.Metamask;
- let signerType = SignerType.Default;
- if (isLedgerSigner) {
- signerType = SignerType.Ledger;
- } else if (isMetaMaskSigner) {
- signerType = SignerType.Metamask;
- }
- const ecSignatureString = await signatureUtils.ecSignOrderHashAsync(
- provider,
- orderHash,
- makerAddress,
- signerType,
- );
+ const ecSignatureString = await signatureUtils.ecSignHashAsync(provider, orderHash, makerAddress);
this._dispatcher.updateSignature(ecSignatureString);
return ecSignatureString;
}
diff --git a/yarn.lock b/yarn.lock
index ff8a87c7b..9b33ab44e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -528,22 +528,6 @@
sinon "^4.0.0"
websocket "^1.0.25"
-"@0xproject/connect@^2.0.4":
- version "2.0.4"
- resolved "https://registry.npmjs.org/@0xproject/connect/-/connect-2.0.4.tgz#d61cd382edbb80120c8efce91dc85d2c668a5c5e"
- dependencies:
- "@0xproject/assert" "^1.0.11"
- "@0xproject/json-schemas" "^1.0.4"
- "@0xproject/order-utils" "^1.0.5"
- "@0xproject/types" "^1.1.1"
- "@0xproject/typescript-typings" "^2.0.2"
- "@0xproject/utils" "^1.0.11"
- lodash "^4.17.5"
- query-string "^5.0.1"
- sinon "^4.0.0"
- uuid "^3.3.2"
- websocket "^1.0.25"
-
"@0xproject/contract-wrappers@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@0xproject/contract-wrappers/-/contract-wrappers-0.1.1.tgz#8108d7ec051f202ef0cfa77c91c4ef994bf89881"
@@ -716,7 +700,7 @@
lodash "4.17.10"
web3 "0.20.6"
-"@0xproject/utils@^1.0.11", "@0xproject/utils@^1.0.4":
+"@0xproject/utils@^1.0.4":
version "1.0.11"
resolved "https://registry.yarnpkg.com/@0xproject/utils/-/utils-1.0.11.tgz#5b53e7d9d4dbe68e219049218c9db04e97c37429"
dependencies:
@@ -867,10 +851,6 @@
call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0"
-"@sindresorhus/is@^0.7.0":
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
-
"@sinonjs/formatio@^2.0.0":
version "2.0.0"
resolved "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2"
@@ -1223,6 +1203,13 @@
"@types/react" "*"
redux "^3.6.0"
+"@types/react-redux@^6.0.9":
+ version "6.0.9"
+ resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-6.0.9.tgz#96aa7f5b0716bcc3bfb36ceaa1223118d509f79a"
+ dependencies:
+ "@types/react" "*"
+ redux "^4.0.0"
+
"@types/react-router-dom@^4.0.4":
version "4.2.6"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.2.6.tgz#9f7eb3c0e6661a9607d878ff8675cc4ea95cd276"
@@ -1254,16 +1241,11 @@
dependencies:
"@types/react" "*"
-"@types/react@*":
- version "16.3.13"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-16.3.13.tgz#47d466462b774556c1174ea0eda22c0578643362"
- dependencies:
- csstype "^2.2.0"
-
-"@types/react@16.4.7":
- version "16.4.7"
- resolved "https://registry.npmjs.org/@types/react/-/react-16.4.7.tgz#f33f6d759a7e1833befa15224d68942d178a5a3f"
+"@types/react@*", "@types/react@^16.4.16":
+ version "16.4.16"
+ resolved "https://registry.npmjs.org/@types/react/-/react-16.4.16.tgz#99f91b1200ae8c2062030402006d3b3c3a177043"
dependencies:
+ "@types/prop-types" "*"
csstype "^2.2.0"
"@types/react@^16.4.2":
@@ -1320,6 +1302,13 @@
version "0.2.1"
resolved "https://registry.npmjs.org/@types/solidity-parser-antlr/-/solidity-parser-antlr-0.2.1.tgz#29ff386773a72a06c8a9c40c666d2a1cea53c2ed"
+"@types/styled-components@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-4.0.0.tgz#33b47071885003878a62689e0883aa2fc59f970a"
+ dependencies:
+ "@types/node" "*"
+ "@types/react" "*"
+
"@types/tmp@^0.0.33":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
@@ -1700,16 +1689,12 @@ ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
-ansi-styles@^3.1.0, ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+ansi-styles@^3.2.0, ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
dependencies:
color-convert "^1.9.0"
-ansi-styles@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
-
ansi-wrap@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf"
@@ -1722,10 +1707,6 @@ antlr4@4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.0.tgz#297f956ddc06f83397fc0990ecf2e0cf20bfbbee"
-any-observable@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.2.0.tgz#c67870058003579009083f54ac0abafb5c33d242"
-
any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@@ -1911,14 +1892,6 @@ assign-symbols@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
-ast-types@0.10.1:
- version "0.10.1"
- resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.1.tgz#f52fca9715579a14f841d67d7f8d25432ab6a3dd"
-
-ast-types@0.11.3:
- version "0.11.3"
- resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.3.tgz#c20757fe72ee71278ea0ff3d87e5c2ca30d9edf8"
-
astral-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
@@ -1949,7 +1922,7 @@ async-limiter@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
-async@1.x, async@^1.4.0, async@^1.4.2, async@^1.5.0, async@^1.5.2:
+async@1.x, async@^1.4.0, async@^1.4.2, async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
@@ -2043,17 +2016,11 @@ aws4@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
-axios@0.15.3:
- version "0.15.3"
- resolved "http://registry.npmjs.org/axios/-/axios-0.15.3.tgz#2c9d638b2e191a08ea1d6cc988eadd6ba5bdc053"
- dependencies:
- follow-redirects "1.0.0"
-
-axios@^0.17.0:
- version "0.17.1"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.17.1.tgz#2d8e3e5d0bdbd7327f91bc814f5c57660f81824d"
+axios@^0.18.0:
+ version "0.18.0"
+ resolved "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
dependencies:
- follow-redirects "^1.2.5"
+ follow-redirects "^1.3.0"
is-buffer "^1.1.5"
babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
@@ -2125,14 +2092,6 @@ babel-generator@^6.18.0, babel-generator@^6.26.0:
source-map "^0.5.7"
trim-right "^1.0.1"
-babel-helper-bindify-decorators@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330"
- dependencies:
- babel-runtime "^6.22.0"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
@@ -2167,15 +2126,6 @@ babel-helper-explode-assignable-expression@^6.24.1:
babel-traverse "^6.24.1"
babel-types "^6.24.1"
-babel-helper-explode-class@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb"
- dependencies:
- babel-helper-bindify-decorators "^6.24.1"
- babel-runtime "^6.22.0"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
babel-helper-function-name@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
@@ -2279,39 +2229,11 @@ babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
-babel-plugin-syntax-async-generators@^6.5.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
-
-babel-plugin-syntax-class-constructor-call@^6.18.0:
- version "6.18.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416"
-
-babel-plugin-syntax-class-properties@^6.8.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
-
-babel-plugin-syntax-decorators@^6.13.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
-
-babel-plugin-syntax-dynamic-import@^6.18.0:
- version "6.18.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
-
babel-plugin-syntax-exponentiation-operator@^6.8.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
-babel-plugin-syntax-export-extensions@^6.8.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721"
-
-babel-plugin-syntax-flow@^6.18.0:
- version "6.18.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"
-
-babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0:
+babel-plugin-syntax-object-rest-spread@^6.13.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
@@ -2319,15 +2241,7 @@ babel-plugin-syntax-trailing-function-commas@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
-babel-plugin-transform-async-generator-functions@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db"
- dependencies:
- babel-helper-remap-async-to-generator "^6.24.1"
- babel-plugin-syntax-async-generators "^6.5.0"
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1:
+babel-plugin-transform-async-to-generator@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
dependencies:
@@ -2335,33 +2249,6 @@ babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-
babel-plugin-syntax-async-functions "^6.8.0"
babel-runtime "^6.22.0"
-babel-plugin-transform-class-constructor-call@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9"
- dependencies:
- babel-plugin-syntax-class-constructor-call "^6.18.0"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
-
-babel-plugin-transform-class-properties@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
- dependencies:
- babel-helper-function-name "^6.24.1"
- babel-plugin-syntax-class-properties "^6.8.0"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
-
-babel-plugin-transform-decorators@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d"
- dependencies:
- babel-helper-explode-class "^6.24.1"
- babel-plugin-syntax-decorators "^6.13.0"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
- babel-types "^6.24.1"
-
babel-plugin-transform-es2015-arrow-functions@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
@@ -2374,7 +2261,7 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1:
+babel-plugin-transform-es2015-block-scoping@^6.23.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
dependencies:
@@ -2384,7 +2271,7 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20
babel-types "^6.26.0"
lodash "^4.17.4"
-babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1:
+babel-plugin-transform-es2015-classes@^6.23.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
dependencies:
@@ -2398,33 +2285,33 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla
babel-traverse "^6.24.1"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1:
+babel-plugin-transform-es2015-computed-properties@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
dependencies:
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0:
+babel-plugin-transform-es2015-destructuring@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
+babel-plugin-transform-es2015-duplicate-keys@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
dependencies:
babel-runtime "^6.22.0"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0:
+babel-plugin-transform-es2015-for-of@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1:
+babel-plugin-transform-es2015-function-name@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
dependencies:
@@ -2455,7 +2342,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e
babel-template "^6.26.0"
babel-types "^6.26.0"
-babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
+babel-plugin-transform-es2015-modules-systemjs@^6.23.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
dependencies:
@@ -2463,7 +2350,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-e
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1:
+babel-plugin-transform-es2015-modules-umd@^6.23.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
dependencies:
@@ -2471,14 +2358,14 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015
babel-runtime "^6.22.0"
babel-template "^6.24.1"
-babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1:
+babel-plugin-transform-es2015-object-super@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
dependencies:
babel-helper-replace-supers "^6.24.1"
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1:
+babel-plugin-transform-es2015-parameters@^6.23.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
dependencies:
@@ -2489,7 +2376,7 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-
babel-traverse "^6.24.1"
babel-types "^6.24.1"
-babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
+babel-plugin-transform-es2015-shorthand-properties@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
dependencies:
@@ -2502,7 +2389,7 @@ babel-plugin-transform-es2015-spread@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1:
+babel-plugin-transform-es2015-sticky-regex@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
dependencies:
@@ -2516,13 +2403,13 @@ babel-plugin-transform-es2015-template-literals@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
+babel-plugin-transform-es2015-typeof-symbol@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1:
+babel-plugin-transform-es2015-unicode-regex@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
dependencies:
@@ -2530,7 +2417,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es20
babel-runtime "^6.22.0"
regexpu-core "^2.0.0"
-babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1:
+babel-plugin-transform-exponentiation-operator@^6.22.0:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
dependencies:
@@ -2538,28 +2425,7 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e
babel-plugin-syntax-exponentiation-operator "^6.8.0"
babel-runtime "^6.22.0"
-babel-plugin-transform-export-extensions@^6.22.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653"
- dependencies:
- babel-plugin-syntax-export-extensions "^6.8.0"
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-flow-strip-types@^6.8.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf"
- dependencies:
- babel-plugin-syntax-flow "^6.18.0"
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-object-rest-spread@^6.22.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
- dependencies:
- babel-plugin-syntax-object-rest-spread "^6.8.0"
- babel-runtime "^6.26.0"
-
-babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1:
+babel-plugin-transform-regenerator@^6.22.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
dependencies:
@@ -2607,35 +2473,6 @@ babel-preset-env@^1.3.2:
invariant "^2.2.2"
semver "^5.3.0"
-babel-preset-es2015@^6.9.0:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
- dependencies:
- babel-plugin-check-es2015-constants "^6.22.0"
- babel-plugin-transform-es2015-arrow-functions "^6.22.0"
- babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
- babel-plugin-transform-es2015-block-scoping "^6.24.1"
- babel-plugin-transform-es2015-classes "^6.24.1"
- babel-plugin-transform-es2015-computed-properties "^6.24.1"
- babel-plugin-transform-es2015-destructuring "^6.22.0"
- babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
- babel-plugin-transform-es2015-for-of "^6.22.0"
- babel-plugin-transform-es2015-function-name "^6.24.1"
- babel-plugin-transform-es2015-literals "^6.22.0"
- babel-plugin-transform-es2015-modules-amd "^6.24.1"
- babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
- babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
- babel-plugin-transform-es2015-modules-umd "^6.24.1"
- babel-plugin-transform-es2015-object-super "^6.24.1"
- babel-plugin-transform-es2015-parameters "^6.24.1"
- babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
- babel-plugin-transform-es2015-spread "^6.22.0"
- babel-plugin-transform-es2015-sticky-regex "^6.24.1"
- babel-plugin-transform-es2015-template-literals "^6.22.0"
- babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
- babel-plugin-transform-es2015-unicode-regex "^6.24.1"
- babel-plugin-transform-regenerator "^6.24.1"
-
babel-preset-jest@^23.2.0:
version "23.2.0"
resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
@@ -2643,34 +2480,7 @@ babel-preset-jest@^23.2.0:
babel-plugin-jest-hoist "^23.2.0"
babel-plugin-syntax-object-rest-spread "^6.13.0"
-babel-preset-stage-1@^6.5.0:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0"
- dependencies:
- babel-plugin-transform-class-constructor-call "^6.24.1"
- babel-plugin-transform-export-extensions "^6.22.0"
- babel-preset-stage-2 "^6.24.1"
-
-babel-preset-stage-2@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1"
- dependencies:
- babel-plugin-syntax-dynamic-import "^6.18.0"
- babel-plugin-transform-class-properties "^6.24.1"
- babel-plugin-transform-decorators "^6.24.1"
- babel-preset-stage-3 "^6.24.1"
-
-babel-preset-stage-3@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395"
- dependencies:
- babel-plugin-syntax-trailing-function-commas "^6.22.0"
- babel-plugin-transform-async-generator-functions "^6.24.1"
- babel-plugin-transform-async-to-generator "^6.24.1"
- babel-plugin-transform-exponentiation-operator "^6.24.1"
- babel-plugin-transform-object-rest-spread "^6.22.0"
-
-babel-register@^6.26.0, babel-register@^6.9.0:
+babel-register@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
dependencies:
@@ -2729,14 +2539,10 @@ babelify@^7.3.0:
babel-core "^6.0.14"
object-assign "^4.0.0"
-babylon@^6.1.21, babylon@^6.17.3, babylon@^6.18.0:
+babylon@^6.1.21, babylon@^6.18.0:
version "6.18.0"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
-babylon@^7.0.0-beta.30:
- version "7.0.0-beta.46"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.46.tgz#b6ddaba81bbb130313932757ff9c195d527088b6"
-
backoff@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
@@ -2883,10 +2689,6 @@ binary-extensions@^1.0.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
-binaryextensions@2:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935"
-
bindings@^1.2.1, bindings@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7"
@@ -3094,13 +2896,6 @@ brorand@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
-brotli-size@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/brotli-size/-/brotli-size-0.0.1.tgz#8c1aeea01cd22f359b048951185bd539ff0c829f"
- dependencies:
- duplexer "^0.1.1"
- iltorb "^1.0.9"
-
browser-process-hrtime@^0.1.2:
version "0.1.3"
resolved "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4"
@@ -3289,6 +3084,13 @@ buffer@^5.0.3, buffer@^5.0.5:
base64-js "^1.0.2"
ieee754 "^1.1.4"
+buffer@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6"
+ dependencies:
+ base64-js "^1.0.2"
+ ieee754 "^1.1.4"
+
builtin-modules@^1.0.0, builtin-modules@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
@@ -3301,19 +3103,18 @@ builtins@^1.0.3:
version "1.0.3"
resolved "http://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
-bundlesize@^0.17.0:
- version "0.17.0"
- resolved "https://registry.yarnpkg.com/bundlesize/-/bundlesize-0.17.0.tgz#212ae5731ab0554d2acd509d23e1de18640b2008"
+bundlewatch@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/bundlewatch/-/bundlewatch-0.2.1.tgz#3bf5279f49c098c7b27c31f7c172397154eb2e65"
dependencies:
- axios "^0.17.0"
- brotli-size "0.0.1"
+ axios "^0.18.0"
bytes "^3.0.0"
- ci-env "^1.4.0"
- commander "^2.11.0"
- github-build "^1.2.0"
+ chalk "^2.4.0"
+ commander "^2.15.1"
glob "^7.1.2"
gzip-size "^4.0.0"
- prettycli "^1.4.3"
+ jsonpack "^1.1.5"
+ lodash.merge "^4.6.1"
read-pkg-up "^3.0.0"
byline@^5.0.0:
@@ -3388,18 +3189,6 @@ cache-base@^1.0.1:
union-value "^1.0.0"
unset-value "^1.0.0"
-cacheable-request@^2.1.1:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d"
- dependencies:
- clone-response "1.0.2"
- get-stream "3.0.0"
- http-cache-semantics "3.8.1"
- keyv "3.0.0"
- lowercase-keys "1.0.0"
- normalize-url "2.0.1"
- responselike "1.0.2"
-
cachedown@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15"
@@ -3542,14 +3331,6 @@ chain-function@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.0.tgz#0d4ab37e7e18ead0bdc47b920764118ce58733dc"
-chalk@2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e"
- dependencies:
- ansi-styles "^3.1.0"
- escape-string-regexp "^1.0.5"
- supports-color "^4.0.0"
-
chalk@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
@@ -3576,7 +3357,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@^2.4.1:
+chalk@^2.4.0, chalk@^2.4.1:
version "2.4.1"
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
dependencies:
@@ -3584,14 +3365,6 @@ chalk@^2.4.1:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@~0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f"
- dependencies:
- ansi-styles "~1.0.0"
- has-color "~0.1.0"
- strip-ansi "~0.1.0"
-
change-case@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.0.2.tgz#fd48746cce02f03f0a672577d1d3a8dc2eceb037"
@@ -3714,10 +3487,6 @@ chrome-trace-event@^1.0.0:
dependencies:
tslib "^1.9.0"
-ci-env@^1.4.0:
- version "1.6.1"
- resolved "https://registry.yarnpkg.com/ci-env/-/ci-env-1.6.1.tgz#3e3ef4fc528a2825397f912cfa30cde17ec364cc"
-
ci-info@^1.0.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2"
@@ -3795,12 +3564,6 @@ cli-table2@0.2.0:
optionalDependencies:
colors "^1.1.2"
-cli-table@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23"
- dependencies:
- colors "1.0.3"
-
cli-truncate@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
@@ -3852,12 +3615,6 @@ clone-buffer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
-clone-response@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
- dependencies:
- mimic-response "^1.0.0"
-
clone-stats@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1"
@@ -3965,7 +3722,7 @@ colors@0.5.x:
version "0.5.1"
resolved "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
-colors@1.0.3, colors@1.0.x:
+colors@1.0.x:
version "1.0.3"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
@@ -4006,9 +3763,9 @@ commander@2.15.1, commander@^2.12.1, commander@^2.8.1:
version "2.15.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
-commander@^2.11.0:
- version "2.18.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970"
+commander@^2.15.1:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
commander@^2.7.1, commander@~2.17.1:
version "2.17.1"
@@ -4274,10 +4031,6 @@ core-js@^2.4.0, core-js@^2.5.0:
version "2.5.5"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.5.tgz#b14dde936c640c0579a6b50cabcc132dd6127e3b"
-core-js@^2.4.1:
- version "2.5.6"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.6.tgz#0fe6d45bf3cac3ac364a9d72de7576f4eb221b9d"
-
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -4593,10 +4346,6 @@ dargs@^4.0.1:
dependencies:
number-is-nan "^1.0.0"
-dargs@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829"
-
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -4623,7 +4372,7 @@ dateformat@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
-dateformat@^3.0.0, dateformat@^3.0.3:
+dateformat@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
@@ -4770,10 +4519,6 @@ deep-equal@~0.2.1:
version "0.2.2"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d"
-deep-extend@^0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f"
-
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
@@ -4933,10 +4678,6 @@ destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
-detect-conflict@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/detect-conflict/-/detect-conflict-1.0.1.tgz#088657a66a961c05019db7c4230883b1c6b4176e"
-
detect-file@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
@@ -4951,10 +4692,6 @@ detect-indent@^5.0.0:
version "5.0.0"
resolved "http://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
-detect-libc@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-0.2.0.tgz#47fdf567348a17ec25fcbf0b9e446348a76f9fb5"
-
detect-libc@^1.0.2, detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
@@ -4978,7 +4715,7 @@ diff@3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75"
-diff@3.5.0, diff@^3.1.0, diff@^3.2.0, diff@^3.3.1, diff@^3.5.0:
+diff@3.5.0, diff@^3.1.0, diff@^3.2.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
@@ -5177,10 +4914,6 @@ ecc-jsbn@~0.1.1:
dependencies:
jsbn "~0.1.0"
-editions@^1.3.3:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b"
-
editor@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742"
@@ -5189,10 +4922,6 @@ ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
-ejs@^2.5.9:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
-
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30:
version "1.3.42"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz#95c33bf01d0cc405556aec899fe61fd4d76ea0f9"
@@ -5277,10 +5006,6 @@ entities@^1.1.1, entities@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
-envinfo@^4.4.2:
- version "4.4.2"
- resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-4.4.2.tgz#472c49f3a8b9bca73962641ce7cb692bf623cd1c"
-
enzyme-adapter-react-16@^1.5.0:
version "1.5.0"
resolved "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.5.0.tgz#50af8d76a45fe0915de932bd95d34cdca75c0be3"
@@ -5337,13 +5062,6 @@ error-ex@^1.2.0, error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
-error@^7.0.2:
- version "7.0.2"
- resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02"
- dependencies:
- string-template "~0.2.1"
- xtend "~4.0.0"
-
es-abstract@^1.10.0, es-abstract@^1.5.1, es-abstract@^1.6.1:
version "1.12.0"
resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
@@ -5515,7 +5233,7 @@ esprima@^3.1.3:
version "3.1.3"
resolved "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
-esprima@^4.0.0, esprima@~4.0.0:
+esprima@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
@@ -5654,6 +5372,17 @@ eth-sig-util@^1.4.2:
ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git"
ethereumjs-util "^5.1.1"
+eth-sig-util@^2.0.2:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.1.0.tgz#33e60e5486897a2ddeb4bf5a0993b2c6d5cc9e19"
+ dependencies:
+ buffer "^5.2.1"
+ elliptic "^6.4.0"
+ ethereumjs-abi "0.6.5"
+ ethereumjs-util "^5.1.1"
+ tweetnacl "^1.0.0"
+ tweetnacl-util "^0.15.0"
+
eth-tx-summary@^3.1.2:
version "3.2.1"
resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.1.tgz#0c2d5e4c57d2511614f85b9b583c32fa2924166c"
@@ -5691,7 +5420,7 @@ ethereum-types@^0.0.2:
"@types/node" "^8.0.53"
bignumber.js "~4.1.0"
-ethereumjs-abi@0.6.5:
+ethereumjs-abi@0.6.5, ethereumjs-abi@^0.6.5:
version "0.6.5"
resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241"
dependencies:
@@ -5748,7 +5477,7 @@ ethereumjs-blockstream@6.0.0:
source-map-support "0.5.6"
uuid "3.2.1"
-ethereumjs-tx@0xProject/ethereumjs-tx#fake-tx-include-signature-by-default:
+ethereumjs-tx@0xProject/ethereumjs-tx#fake-tx-include-signature-by-default, ethereumjs-tx@1.3.4:
version "1.3.4"
resolved "https://codeload.github.com/0xProject/ethereumjs-tx/tar.gz/29d1153889c389591f74b2401da8a0c6ad40f9a7"
dependencies:
@@ -5855,9 +5584,9 @@ ethers@3.0.22:
uuid "2.0.1"
xmlhttprequest "1.8.0"
-ethers@4.0.0-beta.14:
- version "4.0.0-beta.14"
- resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.14.tgz#76aa9257b9c93a7604ff4dc11f2a445d07f6459d"
+ethers@~4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.4.tgz#d3f85e8b27f4b59537e06526439b0fb15b44dc65"
dependencies:
"@types/node" "^10.3.2"
aes-js "3.0.0"
@@ -5865,7 +5594,7 @@ ethers@4.0.0-beta.14:
elliptic "6.3.3"
hash.js "1.1.3"
js-sha3 "0.5.7"
- scrypt-js "2.0.3"
+ scrypt-js "2.0.4"
setimmediate "1.0.4"
uuid "2.0.1"
xmlhttprequest "1.8.0"
@@ -6398,12 +6127,6 @@ first-chunk-stream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e"
-first-chunk-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70"
- dependencies:
- readable-stream "^2.0.2"
-
flagged-respawn@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7"
@@ -6421,10 +6144,6 @@ flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
-flow-parser@^0.*:
- version "0.72.0"
- resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.72.0.tgz#6c8041e76ac7d0be1a71ce29c00cd1435fb6013c"
-
flush-write-stream@^1.0.0, flush-write-stream@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd"
@@ -6432,13 +6151,7 @@ flush-write-stream@^1.0.0, flush-write-stream@^1.0.2:
inherits "^2.0.1"
readable-stream "^2.0.4"
-follow-redirects@1.0.0:
- version "1.0.0"
- resolved "http://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz#8e34298cbd2e176f254effec75a1c78cc849fd37"
- dependencies:
- debug "^2.2.0"
-
-follow-redirects@^1.2.5:
+follow-redirects@^1.3.0:
version "1.5.8"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.8.tgz#1dbfe13e45ad969f813e86c00e5296f525c885a1"
dependencies:
@@ -6515,7 +6228,7 @@ fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
-from2@^2.1.0, from2@^2.1.1:
+from2@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
dependencies:
@@ -6641,12 +6354,11 @@ functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
-ganache-cli@6.1.3:
- version "6.1.3"
- resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.3.tgz#40323e56c878b5c7275830cb8a4fa75a32f6d468"
+ganache-cli@6.1.8:
+ version "6.1.8"
+ resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.8.tgz#49a8a331683a9652183f82ef1378d17e1814fcd3"
dependencies:
source-map-support "^0.5.3"
- webpack-cli "^2.0.9"
ganache-core@0xProject/ganache-core#monorepo-dep:
version "2.1.2"
@@ -6685,6 +6397,46 @@ ganache-core@0xProject/ganache-core#monorepo-dep:
websocket "^1.0.24"
yargs "^7.0.2"
+ganache-core@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.2.1.tgz#c0125d77d3e28d627a812dd002dac21e1d2cc8b7"
+ dependencies:
+ abstract-leveldown "^3.0.0"
+ async "^2.5.0"
+ bip39 "~2.4.0"
+ bn.js "4.11.6"
+ cachedown "^1.0.0"
+ chai "^3.5.0"
+ clone "^2.1.1"
+ eth-sig-util "^2.0.2"
+ ethereumjs-abi "^0.6.5"
+ ethereumjs-account "~2.0.4"
+ ethereumjs-block "~1.2.2"
+ ethereumjs-tx "1.3.4"
+ ethereumjs-util "^5.2.0"
+ ethereumjs-vm "2.3.5"
+ ethereumjs-wallet "0.6.0"
+ fake-merkle-patricia-tree "~1.0.1"
+ heap "~0.2.6"
+ js-scrypt "^0.2.0"
+ level-sublevel "^6.6.1"
+ levelup "^1.1.0"
+ localstorage-down "^0.6.7"
+ lodash "^4.17.5"
+ merkle-patricia-tree "^2.2.0"
+ pify "^3.0.0"
+ prepend-file "^1.3.1"
+ request "^2.87.0"
+ seedrandom "~2.4.2"
+ shebang-loader "0.0.1"
+ solc "0.4.24"
+ temp "^0.8.3"
+ tmp "0.0.31"
+ web3 "^1.0.0-beta.34"
+ web3-provider-engine "^14.0.6"
+ websocket "^1.0.24"
+ yargs "^7.0.2"
+
gauge@~1.2.5:
version "1.2.7"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93"
@@ -6748,10 +6500,6 @@ get-stdin@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
-get-stream@3.0.0, get-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
-
get-stream@^2.2.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de"
@@ -6759,6 +6507,10 @@ get-stream@^2.2.0:
object-assign "^4.0.1"
pinkie-promise "^2.0.0"
+get-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@@ -6769,13 +6521,6 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
-gh-got@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/gh-got/-/gh-got-6.0.0.tgz#d74353004c6ec466647520a10bd46f7299d268d0"
- dependencies:
- got "^7.0.0"
- is-plain-obj "^1.1.0"
-
ghauth@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ghauth/-/ghauth-2.0.1.tgz#79b7d68b0bcf8e7d0852a23b147539dfd314acf6"
@@ -6816,12 +6561,6 @@ gitconfiglocal@^1.0.0:
dependencies:
ini "^1.3.2"
-github-build@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/github-build/-/github-build-1.2.0.tgz#b0bdb705ae4088218577e863c1a301030211051f"
- dependencies:
- axios "0.15.3"
-
github-from-package@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
@@ -6832,19 +6571,6 @@ github-url-to-object@^1.4.2:
dependencies:
is-url "^1.1.0"
-github-username@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/github-username/-/github-username-4.1.0.tgz#cbe280041883206da4212ae9e4b5f169c30bf417"
- dependencies:
- gh-got "^6.0.0"
-
-glob-all@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab"
- dependencies:
- glob "^7.0.5"
- yargs "~1.2.6"
-
glob-base@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@@ -7009,7 +6735,7 @@ globby@^6.1.0:
pify "^2.0.0"
pinkie-promise "^2.0.0"
-globby@^8.0.0, globby@^8.0.1:
+globby@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50"
dependencies:
@@ -7041,7 +6767,7 @@ good-listener@^1.2.2:
dependencies:
delegate "^3.1.2"
-got@7.1.0, got@^7.0.0, got@^7.1.0:
+got@7.1.0, got@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a"
dependencies:
@@ -7076,28 +6802,6 @@ got@^6.7.1:
unzip-response "^2.0.1"
url-parse-lax "^1.0.0"
-got@^8.2.0:
- version "8.3.1"
- resolved "https://registry.yarnpkg.com/got/-/got-8.3.1.tgz#093324403d4d955f5a16a7a8d39955d055ae10ed"
- dependencies:
- "@sindresorhus/is" "^0.7.0"
- cacheable-request "^2.1.1"
- decompress-response "^3.3.0"
- duplexer3 "^0.1.4"
- get-stream "^3.0.0"
- into-stream "^3.1.0"
- is-retry-allowed "^1.1.0"
- isurl "^1.0.0-alpha5"
- lowercase-keys "^1.0.0"
- mimic-response "^1.0.0"
- p-cancelable "^0.4.0"
- p-timeout "^2.0.1"
- pify "^3.0.0"
- safe-buffer "^5.1.1"
- timed-out "^4.0.1"
- url-parse-lax "^3.0.0"
- url-to-options "^1.0.1"
-
graceful-fs@^3.0.0:
version "3.0.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818"
@@ -7116,12 +6820,6 @@ graceful-fs@~1.2.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
-grouped-queue@^0.3.3:
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/grouped-queue/-/grouped-queue-0.3.3.tgz#c167d2a5319c5a0e0964ef6a25b7c2df8996c85c"
- dependencies:
- lodash "^4.17.2"
-
growl@1.10.3:
version "1.10.3"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f"
@@ -7241,10 +6939,6 @@ has-ansi@^2.0.0:
dependencies:
ansi-regex "^2.0.0"
-has-color@~0.1.0:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f"
-
has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
@@ -7481,10 +7175,6 @@ htmlparser2@^3.9.0, htmlparser2@^3.9.1:
inherits "^2.0.1"
readable-stream "^2.0.2"
-http-cache-semantics@3.8.1:
- version "3.8.1"
- resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
-
http-deceiver@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
@@ -7644,15 +7334,6 @@ ignore@^3.3.5:
version "3.3.7"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
-iltorb@^1.0.9:
- version "1.3.10"
- resolved "https://registry.yarnpkg.com/iltorb/-/iltorb-1.3.10.tgz#a0d9e4e7d52bf510741442236cbe0cc4230fc9f8"
- dependencies:
- detect-libc "^0.2.0"
- nan "^2.6.2"
- node-gyp "^3.6.2"
- prebuild-install "^2.3.0"
-
image-size@~0.5.0:
version "0.5.5"
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
@@ -7786,7 +7467,7 @@ inquirer@^3.0.6, inquirer@^3.3.0:
strip-ansi "^4.0.0"
through "^2.3.6"
-inquirer@^5.1.0, inquirer@^5.2.0:
+inquirer@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726"
dependencies:
@@ -7822,17 +7503,10 @@ internal-ip@^3.0.1:
default-gateway "^2.6.0"
ipaddr.js "^1.5.2"
-interpret@^1.0.0, interpret@^1.0.4, interpret@^1.1.0:
+interpret@^1.0.0, interpret@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
-into-stream@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6"
- dependencies:
- from2 "^2.1.1"
- p-is-promise "^1.1.0"
-
invariant@^2.0.0, invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
@@ -8122,12 +7796,6 @@ is-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
-is-observable@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-0.2.0.tgz#b361311d83c6e5d726cabf5e250b0237106f5ae2"
- dependencies:
- symbol-observable "^0.2.2"
-
is-odd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24"
@@ -8192,16 +7860,10 @@ is-resolvable@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
-is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0:
+is-retry-allowed@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
-is-scoped@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-scoped/-/is-scoped-1.0.0.tgz#449ca98299e713038256289ecb2b540dc437cb30"
- dependencies:
- scoped-regex "^1.0.0"
-
is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@@ -8286,10 +7948,6 @@ isarray@^2.0.4:
version "2.0.4"
resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7"
-isbinaryfile@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621"
-
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -8444,14 +8102,6 @@ istanbul@^0.4.5:
which "^1.1.1"
wordwrap "^1.0.0"
-istextorbinary@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53"
- dependencies:
- binaryextensions "2"
- editions "^1.3.3"
- textextensions "2"
-
isurl@^1.0.0-alpha5:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67"
@@ -8816,46 +8466,6 @@ jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
-jscodeshift@^0.4.0:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.4.1.tgz#da91a1c2eccfa03a3387a21d39948e251ced444a"
- dependencies:
- async "^1.5.0"
- babel-plugin-transform-flow-strip-types "^6.8.0"
- babel-preset-es2015 "^6.9.0"
- babel-preset-stage-1 "^6.5.0"
- babel-register "^6.9.0"
- babylon "^6.17.3"
- colors "^1.1.2"
- flow-parser "^0.*"
- lodash "^4.13.1"
- micromatch "^2.3.7"
- node-dir "0.1.8"
- nomnom "^1.8.1"
- recast "^0.12.5"
- temp "^0.8.1"
- write-file-atomic "^1.2.0"
-
-jscodeshift@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.5.0.tgz#bdb7b6cc20dd62c16aa728c3fa2d2fe66ca7c748"
- dependencies:
- babel-plugin-transform-flow-strip-types "^6.8.0"
- babel-preset-es2015 "^6.9.0"
- babel-preset-stage-1 "^6.5.0"
- babel-register "^6.9.0"
- babylon "^7.0.0-beta.30"
- colors "^1.1.2"
- flow-parser "^0.*"
- lodash "^4.13.1"
- micromatch "^2.3.7"
- neo-async "^2.5.0"
- node-dir "0.1.8"
- nomnom "^1.8.1"
- recast "^0.14.1"
- temp "^0.8.1"
- write-file-atomic "^1.2.0"
-
jsdom@^11.5.1:
version "11.12.0"
resolved "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
@@ -8895,10 +8505,6 @@ jsesc@~0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
-json-buffer@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
-
json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@@ -8990,6 +8596,10 @@ jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+jsonpack@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/jsonpack/-/jsonpack-1.1.5.tgz#d42b0dcfd91ac58ef3110f96d2c599404c3dc27c"
+
jsonparse@^1.2.0:
version "1.3.1"
resolved "http://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
@@ -9114,12 +8724,6 @@ keycode@^2.1.8, keycode@^2.1.9:
version "2.2.0"
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04"
-keyv@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373"
- dependencies:
- json-buffer "3.0.0"
-
killable@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b"
@@ -9344,19 +8948,6 @@ listr-update-renderer@^0.2.0:
log-update "^1.0.2"
strip-ansi "^3.0.1"
-listr-update-renderer@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz#344d980da2ca2e8b145ba305908f32ae3f4cc8a7"
- dependencies:
- chalk "^1.1.3"
- cli-truncate "^0.2.1"
- elegant-spinner "^1.0.1"
- figures "^1.7.0"
- indent-string "^3.0.0"
- log-symbols "^1.0.2"
- log-update "^1.0.2"
- strip-ansi "^3.0.1"
-
listr-verbose-renderer@^0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35"
@@ -9387,28 +8978,6 @@ listr@^0.12.0:
stream-to-observable "^0.1.0"
strip-ansi "^3.0.1"
-listr@^0.13.0:
- version "0.13.0"
- resolved "https://registry.yarnpkg.com/listr/-/listr-0.13.0.tgz#20bb0ba30bae660ee84cc0503df4be3d5623887d"
- dependencies:
- chalk "^1.1.3"
- cli-truncate "^0.2.1"
- figures "^1.7.0"
- indent-string "^2.1.0"
- is-observable "^0.2.0"
- is-promise "^2.1.0"
- is-stream "^1.1.0"
- listr-silent-renderer "^1.1.1"
- listr-update-renderer "^0.4.0"
- listr-verbose-renderer "^0.4.0"
- log-symbols "^1.0.2"
- log-update "^1.0.2"
- ora "^0.2.3"
- p-map "^1.1.1"
- rxjs "^5.4.2"
- stream-to-observable "^0.2.0"
- strip-ansi "^3.0.1"
-
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -9617,7 +9186,7 @@ lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
-lodash.merge@^4.6.0:
+lodash.merge@^4.6.0, lodash.merge@^4.6.1:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
@@ -9713,14 +9282,14 @@ lodash@^3.10.1, lodash@^3.3.1, lodash@^3.6.0, lodash@^3.7.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
-lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1:
- version "4.17.5"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
-
-lodash@^4.15.0:
+lodash@^4.13.1, lodash@^4.15.0:
version "4.17.11"
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
+lodash@^4.14.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1:
+ version "4.17.5"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
+
lodash@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551"
@@ -9798,10 +9367,6 @@ lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
-lowercase-keys@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
-
lowercase-keys@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
@@ -9860,12 +9425,6 @@ make-dir@^1.0.0:
dependencies:
pify "^3.0.0"
-make-dir@^1.1.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
- dependencies:
- pify "^3.0.0"
-
make-error@1.x:
version "1.3.5"
resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
@@ -9975,30 +9534,6 @@ media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
-mem-fs-editor@^4.0.0:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/mem-fs-editor/-/mem-fs-editor-4.0.2.tgz#55a79b1e824da631254c4c95ba6366602c77af90"
- dependencies:
- commondir "^1.0.1"
- deep-extend "^0.5.1"
- ejs "^2.5.9"
- glob "^7.0.3"
- globby "^8.0.0"
- isbinaryfile "^3.0.2"
- mkdirp "^0.5.0"
- multimatch "^2.0.0"
- rimraf "^2.2.8"
- through2 "^2.0.0"
- vinyl "^2.0.1"
-
-mem-fs@^1.1.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/mem-fs/-/mem-fs-1.1.3.tgz#b8ae8d2e3fcb6f5d3f9165c12d4551a065d989cc"
- dependencies:
- through2 "^2.0.0"
- vinyl "^1.1.0"
- vinyl-file "^2.0.0"
-
mem@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
@@ -10109,7 +9644,7 @@ methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
-micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7:
+micromatch@^2.1.5, micromatch@^2.3.11:
version "2.3.11"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
dependencies:
@@ -10422,7 +9957,7 @@ multicast-dns@^6.0.1:
dns-packet "^1.3.1"
thunky "^1.0.2"
-multimatch@^2.0.0, multimatch@^2.1.0:
+multimatch@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
dependencies:
@@ -10587,10 +10122,6 @@ node-abi@^2.2.0:
dependencies:
semver "^5.4.1"
-node-dir@0.1.8:
- version "0.1.8"
- resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.8.tgz#55fb8deb699070707fb67f91a460f0448294c77d"
-
node-fetch@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.1.tgz#369ca70b82f50c86496104a6c776d274f4e4a2d4"
@@ -10728,13 +10259,6 @@ nodemon@^1.11.0:
undefsafe "^2.0.2"
update-notifier "^2.3.0"
-nomnom@^1.8.1:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7"
- dependencies:
- chalk "~0.4.0"
- underscore "~1.6.0"
-
nomnom@~1.6.2:
version "1.6.2"
resolved "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971"
@@ -10795,14 +10319,6 @@ normalize-scroll-left@^0.1.2:
version "0.1.2"
resolved "https://registry.npmjs.org/normalize-scroll-left/-/normalize-scroll-left-0.1.2.tgz#6b79691ba79eb5fb107fa5edfbdc06b55caee2aa"
-normalize-url@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6"
- dependencies:
- prepend-http "^2.0.0"
- query-string "^5.0.1"
- sort-keys "^2.0.0"
-
normalize-url@^1.4.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c"
@@ -11283,20 +10799,10 @@ p-cancelable@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa"
-p-cancelable@^0.4.0:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0"
-
p-defer@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
-p-each-series@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71"
- dependencies:
- p-reduce "^1.0.0"
-
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
@@ -11305,10 +10811,6 @@ p-is-promise@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
-p-lazy@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-lazy/-/p-lazy-1.0.0.tgz#ec53c802f2ee3ac28f166cc82d0b2b02de27a835"
-
p-limit@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
@@ -11353,12 +10855,6 @@ p-timeout@^1.1.1:
dependencies:
p-finally "^1.0.0"
-p-timeout@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038"
- dependencies:
- p-finally "^1.0.0"
-
p-try@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
@@ -11683,6 +11179,12 @@ polished@^1.9.3:
version "1.9.3"
resolved "https://registry.npmjs.org/polished/-/polished-1.9.3.tgz#d61b8a0c4624efe31e2583ff24a358932b6b75e1"
+polished@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.npmjs.org/polished/-/polished-2.2.0.tgz#5ca7e178cc5352bd7fd1efc45342f7c6d59cc982"
+ dependencies:
+ "@babel/runtime" "^7.0.0"
+
popper.js@1.14.3, popper.js@^1.14.1:
version "1.14.3"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095"
@@ -12056,7 +11558,7 @@ postman-url-encoder@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/postman-url-encoder/-/postman-url-encoder-1.0.1.tgz#a094a42e9415ff0bbfdce0eaa8e6011d449ee83c"
-prebuild-install@^2.2.2, prebuild-install@^2.3.0:
+prebuild-install@^2.2.2:
version "2.5.3"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-2.5.3.tgz#9f65f242782d370296353710e9bc843490c19f69"
dependencies:
@@ -12094,15 +11596,11 @@ prepend-http@^1.0.0, prepend-http@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
-prepend-http@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
-
preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-prettier@^1.11.1, prettier@^1.5.3:
+prettier@^1.11.1:
version "1.12.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325"
@@ -12113,10 +11611,6 @@ pretty-bytes@^1.0.4:
get-stdin "^4.0.1"
meow "^3.1.0"
-pretty-bytes@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
-
pretty-format@^23.6.0:
version "23.6.0"
resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
@@ -12135,19 +11629,13 @@ pretty-ms@3.1.0:
parse-ms "^1.0.0"
plur "^2.1.2"
-prettycli@^1.4.3:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/prettycli/-/prettycli-1.4.3.tgz#b28ec2aad9de07ae1fd75ef294fb54cbdee07ed5"
- dependencies:
- chalk "2.1.0"
-
prismjs@^1.15.0:
version "1.15.0"
resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.15.0.tgz#8801d332e472091ba8def94976c8877ad60398d9"
optionalDependencies:
clipboard "^2.0.0"
-private@^0.1.6, private@^0.1.7, private@^0.1.8, private@~0.1.5:
+private@^0.1.6, private@^0.1.7, private@^0.1.8:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
@@ -12643,7 +12131,7 @@ react-popper@^1.0.0-beta.6:
typed-styles "^0.0.5"
warning "^3.0.0"
-react-redux@^5.0.3:
+react-redux@^5.0.3, react-redux@^5.0.7:
version "5.0.7"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8"
dependencies:
@@ -12757,13 +12245,6 @@ react@^16.5.2:
prop-types "^15.6.2"
schedule "^0.5.0"
-read-chunk@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655"
- dependencies:
- pify "^3.0.0"
- safe-buffer "^5.1.1"
-
read-cmd-shim@^1.0.1:
version "1.0.1"
resolved "http://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b"
@@ -12903,25 +12384,6 @@ realpath-native@^1.0.0:
dependencies:
util.promisify "^1.0.0"
-recast@^0.12.5:
- version "0.12.9"
- resolved "https://registry.yarnpkg.com/recast/-/recast-0.12.9.tgz#e8e52bdb9691af462ccbd7c15d5a5113647a15f1"
- dependencies:
- ast-types "0.10.1"
- core-js "^2.4.1"
- esprima "~4.0.0"
- private "~0.1.5"
- source-map "~0.6.1"
-
-recast@^0.14.1:
- version "0.14.7"
- resolved "https://registry.yarnpkg.com/recast/-/recast-0.14.7.tgz#4f1497c2b5826d42a66e8e3c9d80c512983ff61d"
- dependencies:
- ast-types "0.11.3"
- esprima "~4.0.0"
- private "~0.1.5"
- source-map "~0.6.1"
-
rechoir@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
@@ -13022,7 +12484,7 @@ redux-devtools-extension@^2.13.2:
version "2.13.2"
resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.2.tgz#e0f9a8e8dfca7c17be92c7124958a3b94eb2911d"
-redux@*:
+redux@*, redux@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03"
dependencies:
@@ -13391,12 +12853,6 @@ resolve@~1.5.0:
dependencies:
path-parse "^1.0.5"
-responselike@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
- dependencies:
- lowercase-keys "^1.0.0"
-
restore-cursor@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
@@ -13492,7 +12948,7 @@ rsvp@^3.3.3:
version "3.6.2"
resolved "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
-run-async@^2.0.0, run-async@^2.2.0:
+run-async@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
dependencies:
@@ -13532,7 +12988,7 @@ rxjs@^5.0.0-beta.11:
dependencies:
symbol-observable "1.0.1"
-rxjs@^5.4.2, rxjs@^5.5.2:
+rxjs@^5.5.2:
version "5.5.10"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.10.tgz#fde02d7a614f6c8683d0d1957827f492e09db045"
dependencies:
@@ -13620,10 +13076,6 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
-scoped-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8"
-
scrypt-async@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9"
@@ -13632,6 +13084,10 @@ scrypt-js@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4"
+scrypt-js@2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16"
+
scrypt.js@0.2.0, scrypt.js@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada"
@@ -13911,7 +13367,7 @@ shelljs@^0.7.3:
interpret "^1.0.0"
rechoir "^0.6.2"
-shelljs@^0.8.0, shelljs@^0.8.2:
+shelljs@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35"
dependencies:
@@ -14410,12 +13866,6 @@ stream-to-observable@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe"
-stream-to-observable@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.2.0.tgz#59d6ea393d87c2c0ddac10aa0d561bc6ba6f0e10"
- dependencies:
- any-observable "^0.2.0"
-
stream-to-pull-stream@^1.7.1:
version "1.7.2"
resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.2.tgz#757609ae1cebd33c7432d4afbe31ff78650b9dde"
@@ -14448,10 +13898,6 @@ string-length@^2.0.0:
astral-regex "^1.0.0"
strip-ansi "^4.0.0"
-string-template@~0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add"
-
string-width@^1.0.1, string-width@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
@@ -14515,17 +13961,6 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
-strip-ansi@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
-
-strip-bom-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca"
- dependencies:
- first-chunk-stream "^2.0.0"
- strip-bom "^2.0.0"
-
strip-bom@3.0.0, strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
@@ -14619,6 +14054,20 @@ styled-components@^3.3.3:
stylis-rule-sheet "^0.0.10"
supports-color "^3.2.3"
+styled-components@^3.4.9:
+ version "3.4.10"
+ resolved "https://registry.npmjs.org/styled-components/-/styled-components-3.4.10.tgz#9a654c50ea2b516c36ade57ddcfa296bf85c96e1"
+ dependencies:
+ buffer "^5.0.3"
+ css-to-react-native "^2.0.3"
+ fbjs "^0.8.16"
+ hoist-non-react-statics "^2.5.0"
+ prop-types "^15.5.4"
+ react-is "^16.3.1"
+ stylis "^3.5.0"
+ stylis-rule-sheet "^0.0.10"
+ supports-color "^3.2.3"
+
stylis-rule-sheet@^0.0.10:
version "0.0.10"
resolved "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430"
@@ -14649,12 +14098,6 @@ supports-color@^3.1.0, supports-color@^3.1.2, supports-color@^3.2.3:
dependencies:
has-flag "^1.0.0"
-supports-color@^4.0.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
- dependencies:
- has-flag "^2.0.0"
-
supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -14737,10 +14180,6 @@ symbol-observable@1.0.4:
version "1.0.4"
resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
-symbol-observable@^0.2.2:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40"
-
symbol-observable@^1.0.3, symbol-observable@^1.0.4, symbol-observable@^1.1.0, symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
@@ -14877,7 +14316,7 @@ temp-write@^3.4.0:
temp-dir "^1.0.0"
uuid "^3.0.1"
-temp@^0.8.1, temp@^0.8.3:
+temp@^0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59"
dependencies:
@@ -14939,14 +14378,10 @@ text-extensions@^1.0.0:
version "1.7.0"
resolved "http://registry.yarnpkg.com/text-extensions/-/text-extensions-1.7.0.tgz#faaaba2625ed746d568a23e4d0aacd9bf08a8b39"
-text-table@^0.2.0, text-table@~0.2.0:
+text-table@~0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
-textextensions@2:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286"
-
theming@^1.3.0:
version "1.3.0"
resolved "https://registry.npmjs.org/theming/-/theming-1.3.0.tgz#286d5bae80be890d0adc645e5ca0498723725bdc"
@@ -15318,6 +14753,10 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
+tweetnacl-util@^0.15.0:
+ version "0.15.0"
+ resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.0.tgz#4576c1cee5e2d63d207fee52f1ba02819480bc75"
+
tweetnacl@0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.13.2.tgz#453161770469d45cd266c36404e2bc99a8fa9944"
@@ -15326,6 +14765,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+tweetnacl@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.0.tgz#713d8b818da42068740bf68386d0479e66fc8a7b"
+
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@@ -15513,10 +14956,6 @@ underscore@~1.4.4:
version "1.4.4"
resolved "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604"
-underscore@~1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
-
underscore@~1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
@@ -15631,10 +15070,6 @@ unset-value@^1.0.0:
has-value "^0.3.1"
isobject "^3.0.0"
-untildify@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.2.tgz#7f1f302055b3fea0f3e81dc78eb36766cb65e3f1"
-
unzip-response@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
@@ -15684,12 +15119,6 @@ url-parse-lax@^1.0.0:
dependencies:
prepend-http "^1.0.1"
-url-parse-lax@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
- dependencies:
- prepend-http "^2.0.0"
-
url-parse@1.0.x:
version "1.0.5"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b"
@@ -15813,10 +15242,6 @@ uvm@1.7.0:
lodash "4.17.4"
uuid "3.0.1"
-v8-compile-cache@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz#8d32e4f16974654657e676e0e467a348e89b0dc4"
-
v8-compile-cache@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c"
@@ -15891,17 +15316,6 @@ vfile@^2.0.0:
unist-util-stringify-position "^1.0.0"
vfile-message "^1.0.0"
-vinyl-file@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a"
- dependencies:
- graceful-fs "^4.1.2"
- pify "^2.3.0"
- pinkie-promise "^2.0.0"
- strip-bom "^2.0.0"
- strip-bom-stream "^2.0.0"
- vinyl "^1.1.0"
-
vinyl-fs@^0.3.0:
version "0.3.14"
resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6"
@@ -15964,15 +15378,7 @@ vinyl@^0.5.0:
clone-stats "^0.0.1"
replace-ext "0.0.1"
-vinyl@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884"
- dependencies:
- clone "^1.0.0"
- clone-stats "^0.0.1"
- replace-ext "0.0.1"
-
-vinyl@^2.0.0, vinyl@^2.0.1, vinyl@^2.1.0:
+vinyl@^2.0.0, vinyl@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c"
dependencies:
@@ -16365,12 +15771,6 @@ webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
-webpack-addons@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/webpack-addons/-/webpack-addons-1.1.5.tgz#2b178dfe873fb6e75e40a819fa5c26e4a9bc837a"
- dependencies:
- jscodeshift "^0.4.0"
-
webpack-cli@3.1.2, webpack-cli@^3.1.1:
version "3.1.2"
resolved "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.2.tgz#17d7e01b77f89f884a2bbf9db545f0f6a648e746"
@@ -16386,37 +15786,6 @@ webpack-cli@3.1.2, webpack-cli@^3.1.1:
v8-compile-cache "^2.0.2"
yargs "^12.0.2"
-webpack-cli@^2.0.9:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-2.1.3.tgz#65d166851abaa56067ef3f716b02a97ba6bbe84d"
- dependencies:
- chalk "^2.3.2"
- cross-spawn "^6.0.5"
- diff "^3.5.0"
- enhanced-resolve "^4.0.0"
- envinfo "^4.4.2"
- glob-all "^3.1.0"
- global-modules "^1.0.0"
- got "^8.2.0"
- import-local "^1.0.0"
- inquirer "^5.1.0"
- interpret "^1.0.4"
- jscodeshift "^0.5.0"
- listr "^0.13.0"
- loader-utils "^1.1.0"
- lodash "^4.17.5"
- log-symbols "^2.2.0"
- mkdirp "^0.5.1"
- p-each-series "^1.0.0"
- p-lazy "^1.0.0"
- prettier "^1.5.3"
- supports-color "^5.3.0"
- v8-compile-cache "^1.1.2"
- webpack-addons "^1.1.5"
- yargs "^11.1.0"
- yeoman-environment "^2.0.0"
- yeoman-generator "^2.0.4"
-
webpack-dev-middleware@3.4.0:
version "3.4.0"
resolved "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890"
@@ -16678,7 +16047,7 @@ wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
-write-file-atomic@^1.1.4, write-file-atomic@^1.2.0:
+write-file-atomic@^1.1.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
dependencies:
@@ -16897,7 +16266,7 @@ yargs-parser@^9.0.2:
dependencies:
camelcase "^4.1.0"
-yargs@11.1.0, yargs@^11.1.0:
+yargs@11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"
dependencies:
@@ -17049,12 +16418,6 @@ yargs@^8.0.2:
y18n "^3.2.1"
yargs-parser "^7.0.0"
-yargs@~1.2.6:
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.2.6.tgz#9c7b4a82fd5d595b2bf17ab6dcc43135432fe34b"
- dependencies:
- minimist "^0.1.0"
-
yargs@~3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
@@ -17071,56 +16434,6 @@ yauzl@^2.4.2:
buffer-crc32 "~0.2.3"
fd-slicer "~1.0.1"
-yeoman-environment@^2.0.0, yeoman-environment@^2.0.5:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/yeoman-environment/-/yeoman-environment-2.1.0.tgz#175f49ad693aff41c8998d32f6103c20c62ec37b"
- dependencies:
- chalk "^2.1.0"
- cross-spawn "^6.0.5"
- debug "^3.1.0"
- diff "^3.3.1"
- escape-string-regexp "^1.0.2"
- globby "^8.0.1"
- grouped-queue "^0.3.3"
- inquirer "^5.2.0"
- is-scoped "^1.0.0"
- lodash "^4.17.10"
- log-symbols "^2.1.0"
- mem-fs "^1.1.0"
- strip-ansi "^4.0.0"
- text-table "^0.2.0"
- untildify "^3.0.2"
-
-yeoman-generator@^2.0.4:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-2.0.5.tgz#57b0b3474701293cc9ec965288f3400b00887c81"
- dependencies:
- async "^2.6.0"
- chalk "^2.3.0"
- cli-table "^0.3.1"
- cross-spawn "^6.0.5"
- dargs "^5.1.0"
- dateformat "^3.0.3"
- debug "^3.1.0"
- detect-conflict "^1.0.0"
- error "^7.0.2"
- find-up "^2.1.0"
- github-username "^4.0.0"
- istextorbinary "^2.2.1"
- lodash "^4.17.10"
- make-dir "^1.1.0"
- mem-fs-editor "^4.0.0"
- minimist "^1.2.0"
- pretty-bytes "^4.0.2"
- read-chunk "^2.1.0"
- read-pkg-up "^3.0.0"
- rimraf "^2.6.2"
- run-async "^2.0.0"
- shelljs "^0.8.0"
- text-table "^0.2.0"
- through2 "^2.0.0"
- yeoman-environment "^2.0.5"
-
yn@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"