Merge pull request #1044 from 0xProject/feature/website/update-portal-v2

[website] Update portal for v2
This commit is contained in:
Francesco Agosti
2018-09-04 12:37:53 -07:00
committed by GitHub
27 changed files with 452 additions and 1062 deletions

View File

@@ -45,6 +45,7 @@
"dependencies": {
"@0xproject/assert": "^1.0.7",
"@0xproject/json-schemas": "^1.0.1-rc.6",
"@0xproject/order-utils": "^1.0.1-rc.6",
"@0xproject/types": "^1.0.1-rc.6",
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",

View File

@@ -1,5 +1,6 @@
import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas';
import { orderParsingUtils } from '@0xproject/order-utils';
import {
APIOrder,
@@ -19,7 +20,7 @@ export const relayerResponseJsonParsers = {
},
parseAssetPairsItemsJson(json: any): AssetPairsItem[] {
return json.map((assetDataPair: any) => {
return typeConverters.convertStringsFieldsToBigNumbers(assetDataPair, [
return orderParsingUtils.convertStringsFieldsToBigNumbers(assetDataPair, [
'assetDataA.minAmount',
'assetDataA.maxAmount',
'assetDataB.minAmount',
@@ -44,6 +45,6 @@ export const relayerResponseJsonParsers = {
},
parseOrderConfigResponseJson(json: any): OrderConfigResponse {
assert.doesConformToSchema('orderConfigResponse', json, schemas.relayerApiOrderConfigResponseSchema);
return typeConverters.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']);
return orderParsingUtils.convertStringsFieldsToBigNumbers(json, ['makerFee', 'takerFee']);
},
};

View File

@@ -1,4 +1,4 @@
import { BigNumber } from '@0xproject/utils';
import { orderParsingUtils } from '@0xproject/order-utils';
import * as _ from 'lodash';
import { APIOrder } from '../types';
@@ -21,28 +21,6 @@ export const typeConverters = {
};
},
convertAPIOrderStringFieldsToBigNumber(apiOrder: any): APIOrder {
return { ...apiOrder, order: typeConverters.convertOrderStringFieldsToBigNumber(apiOrder.order) };
},
convertOrderStringFieldsToBigNumber(order: any): any {
return typeConverters.convertStringsFieldsToBigNumbers(order, [
'makerAssetAmount',
'takerAssetAmount',
'makerFee',
'takerFee',
'expirationTimeSeconds',
'salt',
]);
},
convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any {
const result = _.assign({}, obj);
_.each(fields, field => {
_.update(result, field, (value: string) => {
if (_.isUndefined(value)) {
throw new Error(`Could not find field '${field}' while converting string fields to BigNumber.`);
}
return new BigNumber(value);
});
});
return result;
return { ...apiOrder, order: orderParsingUtils.convertOrderStringFieldsToBigNumber(apiOrder.order) };
},
};

View File

@@ -5,6 +5,11 @@
{
"note": "Add `OrderValidatorWrapper`"
},
{
"note":
"Fix bug where contracts not deployed on a network showed an `EXCHANGE_CONTRACT_DOES_NOT_EXIST` error instead of `CONTRACT_NOT_DEPLOYED_ON_NETWORK`",
"pr": 1044
},
{
"note":
"Export `AssetBalanceAndProxyAllowanceFetcher` and `OrderFilledCancelledFetcher` implementations",

View File

@@ -145,9 +145,12 @@ export abstract class ContractWrapper {
}
protected _getContractAddress(artifact: ContractArtifact, addressIfExists?: string): string {
if (_.isUndefined(addressIfExists)) {
if (_.isUndefined(artifact.networks[this._networkId])) {
throw new Error(ContractWrappersError.ContractNotDeployedOnNetwork);
}
const contractAddress = artifact.networks[this._networkId].address;
if (_.isUndefined(contractAddress)) {
throw new Error(ContractWrappersError.ExchangeContractDoesNotExist);
throw new Error(CONTRACT_NAME_TO_NOT_FOUND_ERROR[artifact.contractName]);
}
return contractAddress;
} else {

View File

@@ -1,4 +1,13 @@
[
{
"version": "1.0.1-rc.7",
"changes": [
{
"note": "Export `orderParsingUtils`",
"pr": 1044
}
]
},
{
"version": "1.0.1-rc.6",
"changes": [

View File

@@ -6,6 +6,7 @@ export { eip712Utils } from './eip712_utils';
export { marketUtils } from './market_utils';
export { rateUtils } from './rate_utils';
export { sortingUtils } from './sorting_utils';
export { orderParsingUtils } from './parsing_utils';
export { OrderStateUtils } from './order_state_utils';
export { AbstractBalanceAndProxyAllowanceFetcher } from './abstract/abstract_balance_and_proxy_allowance_fetcher';

View File

@@ -0,0 +1,27 @@
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
export const orderParsingUtils = {
convertStringsFieldsToBigNumbers(obj: any, fields: string[]): any {
const result = _.assign({}, obj);
_.each(fields, field => {
_.update(result, field, (value: string) => {
if (_.isUndefined(value)) {
throw new Error(`Could not find field '${field}' while converting string fields to BigNumber.`);
}
return new BigNumber(value);
});
});
return result;
},
convertOrderStringFieldsToBigNumber(order: any): any {
return orderParsingUtils.convertStringsFieldsToBigNumbers(order, [
'makerAssetAmount',
'takerAssetAmount',
'makerFee',
'takerFee',
'expirationTimeSeconds',
'salt',
]);
},
};

View File

@@ -18,13 +18,14 @@
"author": "Fabio Berger",
"license": "Apache-2.0",
"dependencies": {
"@0xproject/contract-wrappers": "^0.0.5",
"@0xproject/order-utils": "^0.0.9",
"0x.js": "^0.38.6",
"@0xproject/contract-wrappers": "^1.0.1-rc.5",
"@0xproject/order-utils": "^1.0.1-rc.6",
"@0xproject/react-docs": "^1.0.7",
"@0xproject/react-shared": "^1.0.8",
"@0xproject/subproviders": "^2.0.1",
"@0xproject/types": "^0.8.1",
"@0xproject/typescript-typings": "^0.4.3",
"@0xproject/types": "^1.0.1-rc.6",
"@0xproject/typescript-typings": "^1.0.5",
"@0xproject/utils": "^1.0.7",
"@0xproject/web3-wrapper": "^2.0.1",
"accounting": "^0.4.1",
@@ -32,6 +33,7 @@
"blockies": "^0.0.2",
"bowser": "^1.9.3",
"deep-equal": "^1.0.1",
"ethereum-types": "^1.0.5",
"ethereumjs-util": "^5.1.1",
"find-versions": "^2.0.0",
"jsonschema": "^1.2.0",
@@ -66,7 +68,6 @@
"@types/accounting": "^0.4.1",
"@types/blockies": "^0.0.0",
"@types/deep-equal": "^1.0.0",
"@types/web3-provider-engine": "^14.0.0",
"@types/find-versions": "^2.0.0",
"@types/jsonschema": "^1.1.1",
"@types/lodash": "4.14.104",
@@ -83,6 +84,7 @@
"@types/react-scroll": "1.5.3",
"@types/react-tap-event-plugin": "0.0.30",
"@types/redux": "^3.6.0",
"@types/web3-provider-engine": "^14.0.0",
"awesome-typescript-loader": "^3.1.3",
"copy-webpack-plugin": "^4.0.1",
"copyfiles": "^2.0.0",

View File

@@ -1,610 +0,0 @@
{
"contract_name": "Exchange",
"abi": [
{
"constant": true,
"inputs": [
{
"name": "numerator",
"type": "uint256"
},
{
"name": "denominator",
"type": "uint256"
},
{
"name": "target",
"type": "uint256"
}
],
"name": "isRoundingError",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "bytes32"
}
],
"name": "filled",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "bytes32"
}
],
"name": "cancelled",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "fillOrdersUpTo",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "cancelTakerTokenAmount",
"type": "uint256"
}
],
"name": "cancelOrder",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "ZRX_TOKEN_CONTRACT",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmounts",
"type": "uint256[]"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "batchFillOrKillOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "fillOrKillOrder",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "orderHash",
"type": "bytes32"
}
],
"name": "getUnavailableTakerTokenAmount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "signer",
"type": "address"
},
{
"name": "hash",
"type": "bytes32"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "isValidSignature",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "numerator",
"type": "uint256"
},
{
"name": "denominator",
"type": "uint256"
},
{
"name": "target",
"type": "uint256"
}
],
"name": "getPartialAmount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "TOKEN_TRANSFER_PROXY_CONTRACT",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "fillTakerTokenAmounts",
"type": "uint256[]"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8[]"
},
{
"name": "r",
"type": "bytes32[]"
},
{
"name": "s",
"type": "bytes32[]"
}
],
"name": "batchFillOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5][]"
},
{
"name": "orderValues",
"type": "uint256[6][]"
},
{
"name": "cancelTakerTokenAmounts",
"type": "uint256[]"
}
],
"name": "batchCancelOrders",
"outputs": [],
"payable": false,
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
},
{
"name": "fillTakerTokenAmount",
"type": "uint256"
},
{
"name": "shouldThrowOnInsufficientBalanceOrAllowance",
"type": "bool"
},
{
"name": "v",
"type": "uint8"
},
{
"name": "r",
"type": "bytes32"
},
{
"name": "s",
"type": "bytes32"
}
],
"name": "fillOrder",
"outputs": [
{
"name": "filledTakerTokenAmount",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "orderAddresses",
"type": "address[5]"
},
{
"name": "orderValues",
"type": "uint256[6]"
}
],
"name": "getOrderHash",
"outputs": [
{
"name": "",
"type": "bytes32"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "EXTERNAL_QUERY_GAS_LIMIT",
"outputs": [
{
"name": "",
"type": "uint16"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "VERSION",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"type": "function"
},
{
"inputs": [
{
"name": "_zrxToken",
"type": "address"
},
{
"name": "_tokenTransferProxy",
"type": "address"
}
],
"payable": false,
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "maker",
"type": "address"
},
{
"indexed": false,
"name": "taker",
"type": "address"
},
{
"indexed": true,
"name": "feeRecipient",
"type": "address"
},
{
"indexed": false,
"name": "makerToken",
"type": "address"
},
{
"indexed": false,
"name": "takerToken",
"type": "address"
},
{
"indexed": false,
"name": "filledMakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "filledTakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "paidMakerFee",
"type": "uint256"
},
{
"indexed": false,
"name": "paidTakerFee",
"type": "uint256"
},
{
"indexed": true,
"name": "tokens",
"type": "bytes32"
},
{
"indexed": false,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogFill",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "maker",
"type": "address"
},
{
"indexed": true,
"name": "feeRecipient",
"type": "address"
},
{
"indexed": false,
"name": "makerToken",
"type": "address"
},
{
"indexed": false,
"name": "takerToken",
"type": "address"
},
{
"indexed": false,
"name": "cancelledMakerTokenAmount",
"type": "uint256"
},
{
"indexed": false,
"name": "cancelledTakerTokenAmount",
"type": "uint256"
},
{
"indexed": true,
"name": "tokens",
"type": "bytes32"
},
{
"indexed": false,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogCancel",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "errorId",
"type": "uint8"
},
{
"indexed": true,
"name": "orderHash",
"type": "bytes32"
}
],
"name": "LogError",
"type": "event"
}
],
"networks": {
"1": {
"address": "0x12459c951127e0c374ff9105dda097662a027093"
},
"3": {
"address": "0x479cc461fecd078f766ecc58533d6f69580cf3ac"
},
"4": {
"address": "0x1d16ef40fac01cec8adac2ac49427b9384192c05"
},
"42": {
"address": "0x90fe2af704b34e0224bf2299c838e04d4dcf1364"
},
"50": {
"address": "0x48bacb9266a570d521063ef5dd96e61686dbe788"
}
}
}

View File

@@ -1,15 +1,15 @@
import { ZeroEx } from '0x.js';
import {
BlockRange,
ContractWrappers,
DecodedLogEvent,
ExchangeContractEventArgs,
ExchangeCancelEventArgs,
ExchangeEventArgs,
ExchangeEvents,
ExchangeFillEventArgs,
IndexedFilterValues,
LogCancelContractEventArgs,
LogFillContractEventArgs,
Token as ZeroExToken,
} from '@0xproject/contract-wrappers';
import { isValidOrderHash, signOrderHashAsync } from '@0xproject/order-utils';
import { assetDataUtils, orderHashUtils, signatureUtils, SignerType } from '@0xproject/order-utils';
import { EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/react-shared';
import {
ledgerEthereumBrowserClientFactoryAsync,
@@ -19,21 +19,15 @@ import {
SignerSubprovider,
Web3ProviderEngine,
} from '@0xproject/subproviders';
import {
BlockParam,
ECSignature,
LogWithDecodedArgs,
Order,
Provider,
SignedOrder,
TransactionReceiptWithDecodedLogs,
} from '@0xproject/types';
import { SignedOrder, Token as ZeroExToken } from '@0xproject/types';
import { BigNumber, intervalUtils, logUtils, promisify } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { BlockParam, LogWithDecodedArgs, Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import * as moment from 'moment';
import * as React from 'react';
import contract = require('truffle-contract');
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';
@@ -48,7 +42,6 @@ import {
InjectedProviderObservable,
InjectedProviderUpdate,
InjectedWeb3,
Order as PortalOrder,
Providers,
ProviderType,
Side,
@@ -65,9 +58,6 @@ import FilterSubprovider = require('web3-provider-engine/subproviders/filters');
import * as MintableArtifacts from '../contracts/Mintable.json';
// HACK: remove this hard-coded abi and use @0xproject/contract-wrappers
import * as Exchange from './artifacts/Exchange.json';
const BLOCK_NUMBER_BACK_TRACK = 50;
const GWEI_IN_WEI = 1000000000;
@@ -83,6 +73,7 @@ export class Blockchain {
public networkId: number;
public nodeVersion: string;
private _contractWrappers: ContractWrappers;
private _zeroEx: ZeroEx;
private readonly _dispatcher: Dispatcher;
private _web3Wrapper?: Web3Wrapper;
private _blockchainWatcher?: BlockchainWatcher;
@@ -230,8 +221,8 @@ export class Blockchain {
}
}
public async isAddressInTokenRegistryAsync(tokenAddress: string): Promise<boolean> {
utils.assert(!_.isUndefined(this._contractWrappers), 'Contract Wrappers must be instantiated.');
const tokenIfExists = await this._contractWrappers.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
const tokenIfExists = await this._zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
return !_.isUndefined(tokenIfExists);
}
public getLedgerDerivationPathIfExists(): string {
@@ -266,7 +257,7 @@ export class Blockchain {
utils.assert(!_.isUndefined(this._contractWrappers), 'Contract Wrappers must be instantiated.');
this._showFlashMessageIfLedger();
const txHash = await this._contractWrappers.token.setProxyAllowanceAsync(
const txHash = await this._contractWrappers.erc20Token.setProxyAllowanceAsync(
token.address,
this._userAddressIfExists,
amountInBaseUnits,
@@ -307,7 +298,7 @@ export class Blockchain {
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
this._showFlashMessageIfLedger();
const txHash = await this._contractWrappers.token.transferAsync(
const txHash = await this._contractWrappers.erc20Token.transferAsync(
token.address,
this._userAddressIfExists,
toAddress,
@@ -332,66 +323,41 @@ export class Blockchain {
}),
);
}
public portalOrderToZeroExOrder(portalOrder: PortalOrder): SignedOrder {
const exchangeContractAddress = this.getExchangeContractAddressIfExists();
const zeroExSignedOrder = {
exchangeContractAddress,
maker: portalOrder.signedOrder.maker,
taker: portalOrder.signedOrder.taker,
makerTokenAddress: portalOrder.signedOrder.makerTokenAddress,
takerTokenAddress: portalOrder.signedOrder.takerTokenAddress,
makerTokenAmount: new BigNumber(portalOrder.signedOrder.makerTokenAmount),
takerTokenAmount: new BigNumber(portalOrder.signedOrder.takerTokenAmount),
makerFee: new BigNumber(portalOrder.signedOrder.makerFee),
takerFee: new BigNumber(portalOrder.signedOrder.takerFee),
expirationUnixTimestampSec: new BigNumber(portalOrder.signedOrder.expirationUnixTimestampSec),
feeRecipient: portalOrder.signedOrder.feeRecipient,
ecSignature: portalOrder.signedOrder.ecSignature,
salt: new BigNumber(portalOrder.signedOrder.salt),
};
return zeroExSignedOrder;
}
public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber): Promise<BigNumber> {
utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.');
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const shouldThrowOnInsufficientBalanceOrAllowance = true;
this._showFlashMessageIfLedger();
const txHash = await this._contractWrappers.exchange.fillOrderAsync(
signedOrder,
fillTakerTokenAmount,
shouldThrowOnInsufficientBalanceOrAllowance,
this._userAddressIfExists,
{
gasPrice: this._defaultGasPrice,
},
);
const receipt = await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const logs: Array<LogWithDecodedArgs<ExchangeContractEventArgs>> = receipt.logs as any;
this._contractWrappers.exchange.throwLogErrorsAsErrors(logs);
const logFill = _.find(logs, { event: 'LogFill' });
const args = (logFill.args as any) as LogFillContractEventArgs;
const filledTakerTokenAmount = args.filledTakerTokenAmount;
return filledTakerTokenAmount;
const logs: Array<LogWithDecodedArgs<ExchangeEventArgs>> = receipt.logs as any;
const logFill = _.find(logs, { event: ExchangeEvents.Fill });
const args = (logFill.args as any) as ExchangeFillEventArgs;
const takerAssetFilledAmount = args.takerAssetFilledAmount;
return takerAssetFilledAmount;
}
public async cancelOrderAsync(signedOrder: SignedOrder, cancelTakerTokenAmount: BigNumber): Promise<BigNumber> {
public async cancelOrderAsync(signedOrder: SignedOrder): Promise<string> {
this._showFlashMessageIfLedger();
const txHash = await this._contractWrappers.exchange.cancelOrderAsync(signedOrder, cancelTakerTokenAmount, {
const txHash = await this._contractWrappers.exchange.cancelOrderAsync(signedOrder, {
gasPrice: this._defaultGasPrice,
});
const receipt = await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const logs: Array<LogWithDecodedArgs<ExchangeContractEventArgs>> = receipt.logs as any;
this._contractWrappers.exchange.throwLogErrorsAsErrors(logs);
const logCancel = _.find(logs, { event: ExchangeEvents.LogCancel });
const args = (logCancel.args as any) as LogCancelContractEventArgs;
const cancelledTakerTokenAmount = args.cancelledTakerTokenAmount;
return cancelledTakerTokenAmount;
const logs: Array<LogWithDecodedArgs<ExchangeEventArgs>> = receipt.logs as any;
const logCancel = _.find(logs, { event: ExchangeEvents.Cancel });
const args = (logCancel.args as any) as ExchangeCancelEventArgs;
const cancelledOrderHash = args.orderHash;
return cancelledOrderHash;
}
public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber> {
utils.assert(isValidOrderHash(orderHash), 'Must be valid orderHash');
utils.assert(orderHashUtils.isValidOrderHash(orderHash), 'Must be valid orderHash');
utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.');
const unavailableTakerAmount = await this._contractWrappers.exchange.getUnavailableTakerAmountAsync(orderHash);
const unavailableTakerAmount = await this._contractWrappers.exchange.getFilledTakerAssetAmountAsync(orderHash);
return unavailableTakerAmount;
}
public getExchangeContractAddressIfExists(): string | undefined {
@@ -408,16 +374,19 @@ export class Blockchain {
takerAddress,
);
}
public async validateCancelOrderThrowIfInvalidAsync(
order: Order,
cancelTakerTokenAmount: BigNumber,
): Promise<void> {
await this._contractWrappers.exchange.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount);
}
public isValidAddress(address: string): boolean {
const lowercaseAddress = address.toLowerCase();
return Web3Wrapper.isAddress(lowercaseAddress);
}
public async isValidSignatureAsync(data: string, signature: string, signerAddress: string): Promise<boolean> {
const result = await signatureUtils.isValidSignatureAsync(
this._contractWrappers.getProvider(),
data,
signature,
signerAddress,
);
return result;
}
public async pollTokenBalanceAsync(token: Token): Promise<BigNumber> {
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
@@ -446,7 +415,7 @@ export class Blockchain {
return newTokenBalancePromise;
}
public async signOrderHashAsync(orderHash: string): Promise<ECSignature> {
public async signOrderHashAsync(orderHash: string): Promise<string> {
utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.');
const makerAddress = this._userAddressIfExists;
// If makerAddress is undefined, this means they have a web3 instance injected into their browser
@@ -454,20 +423,25 @@ export class Blockchain {
if (_.isUndefined(makerAddress)) {
throw new Error('Tried to send a sign request but user has no associated addresses');
}
this._showFlashMessageIfLedger();
const nodeVersion = await this._web3Wrapper.getNodeVersionAsync();
const isParityNode = utils.isParityNode(nodeVersion);
const isTestRpc = utils.isTestRpc(nodeVersion);
const isLedgerSigner = !_.isUndefined(this._ledgerSubprovider);
let shouldAddPersonalMessagePrefix = true;
if ((isParityNode && !isLedgerSigner) || isTestRpc || isLedgerSigner) {
shouldAddPersonalMessagePrefix = false;
}
const provider = this._contractWrappers.getProvider();
const ecSignature = await signOrderHashAsync(provider, orderHash, makerAddress, shouldAddPersonalMessagePrefix);
this._dispatcher.updateECSignature(ecSignature);
return ecSignature;
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,
);
this._dispatcher.updateSignature(ecSignatureString);
return ecSignatureString;
}
public async mintTestTokensAsync(token: Token): Promise<void> {
utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
@@ -540,8 +514,8 @@ export class Blockchain {
let allowance = new BigNumber(0);
if (this._doesUserAddressExist()) {
[balance, allowance] = await Promise.all([
this._contractWrappers.token.getBalanceAsync(tokenAddress, ownerAddressIfExists),
this._contractWrappers.token.getProxyAllowanceAsync(tokenAddress, ownerAddressIfExists),
this._contractWrappers.erc20Token.getBalanceAsync(tokenAddress, ownerAddressIfExists),
this._contractWrappers.erc20Token.getProxyAllowanceAsync(tokenAddress, ownerAddressIfExists),
]);
}
return [balance, allowance];
@@ -653,8 +627,7 @@ export class Blockchain {
);
const provider = this._contractWrappers.getProvider();
const web3Wrapper = new Web3Wrapper(provider);
// HACK: remove this hard-coded abi and use @0xproject/contract-wrappers
const exchangeAbi = _.get(Exchange, 'abi', []);
const exchangeAbi = this._contractWrappers.exchange.abi;
web3Wrapper.abiDecoder.addABI(exchangeAbi);
const receipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
return receipt;
@@ -699,9 +672,9 @@ export class Blockchain {
// Start a subscription for new logs
this._contractWrappers.exchange.subscribe(
ExchangeEvents.LogFill,
ExchangeEvents.Fill,
indexFilterValues,
async (err: Error, decodedLogEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
async (err: Error, decodedLogEvent: DecodedLogEvent<ExchangeFillEventArgs>) => {
if (err) {
// Note: it's not entirely clear from the documentation which
// errors will be thrown by `watch`. For now, let's log the error
@@ -732,8 +705,8 @@ export class Blockchain {
fromBlock,
toBlock: 'latest' as BlockParam,
};
const decodedLogs = await this._contractWrappers.exchange.getLogsAsync<LogFillContractEventArgs>(
ExchangeEvents.LogFill,
const decodedLogs = await this._contractWrappers.exchange.getLogsAsync<ExchangeFillEventArgs>(
ExchangeEvents.Fill,
blockRange,
indexFilterValues,
);
@@ -746,28 +719,28 @@ export class Blockchain {
tradeHistoryStorage.addFillToUser(this._userAddressIfExists, this.networkId, fill);
}
}
private async _convertDecodedLogToFillAsync(
decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>,
): Promise<Fill> {
private async _convertDecodedLogToFillAsync(decodedLog: LogWithDecodedArgs<ExchangeFillEventArgs>): Promise<Fill> {
const args = decodedLog.args;
const blockTimestamp = await this._web3Wrapper.getBlockTimestampAsync(decodedLog.blockHash);
const makerToken = assetDataUtils.decodeERC20AssetData(args.makerAssetData).tokenAddress;
const takerToken = assetDataUtils.decodeERC20AssetData(args.takerAssetData).tokenAddress;
const fill = {
filledTakerTokenAmount: args.filledTakerTokenAmount,
filledMakerTokenAmount: args.filledMakerTokenAmount,
filledTakerTokenAmount: args.takerAssetFilledAmount,
filledMakerTokenAmount: args.makerAssetFilledAmount,
logIndex: decodedLog.logIndex,
maker: args.maker,
maker: args.makerAddress,
orderHash: args.orderHash,
taker: args.taker,
makerToken: args.makerToken,
takerToken: args.takerToken,
paidMakerFee: args.paidMakerFee,
paidTakerFee: args.paidTakerFee,
taker: args.takerAddress,
makerToken,
takerToken,
paidMakerFee: args.makerFeePaid,
paidTakerFee: args.takerFeePaid,
transactionHash: decodedLog.transactionHash,
blockTimestamp,
};
return fill;
}
private _doesLogEventInvolveUser(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>): boolean {
private _doesLogEventInvolveUser(decodedLog: LogWithDecodedArgs<ExchangeFillEventArgs>): boolean {
const args = decodedLog.args;
const isUserMakerOrTaker = args.maker === this._userAddressIfExists || args.taker === this._userAddressIfExists;
return isUserMakerOrTaker;
@@ -796,8 +769,8 @@ export class Blockchain {
if (this.networkId === constants.NETWORK_ID_MAINNET) {
tokenRegistryTokens = await backendClient.getTokenInfosAsync();
} else {
utils.assert(!_.isUndefined(this._contractWrappers), 'ContractWrappers must be instantiated.');
tokenRegistryTokens = await this._contractWrappers.tokenRegistry.getTokensAsync();
utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
tokenRegistryTokens = await this._zeroEx.tokenRegistry.getTokensAsync();
}
const tokenByAddress: TokenByAddress = {};
_.each(tokenRegistryTokens, (t: ZeroExToken) => {
@@ -877,6 +850,11 @@ export class Blockchain {
} else {
this._contractWrappers = new ContractWrappers(provider, { networkId });
}
if (!_.isUndefined(this._zeroEx)) {
this._zeroEx.setProvider(provider, networkId);
} else {
this._zeroEx = new ZeroEx(provider, { networkId });
}
if (!_.isUndefined(this._blockchainWatcher)) {
this._blockchainWatcher.destroy();
}

View File

@@ -1,6 +1,5 @@
import { getOrderHashHex, isValidSignature } from '@0xproject/order-utils';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { colors } from '@0xproject/react-shared';
import { Order as ZeroExOrder } from '@0xproject/types';
import { BigNumber, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as accounting from 'accounting';
@@ -22,10 +21,10 @@ import { VisualOrder } from 'ts/components/visual_order';
import { Dispatcher } from 'ts/redux/dispatcher';
import { portalOrderSchema } from 'ts/schemas/portal_order_schema';
import { validator } from 'ts/schemas/validator';
import { AlertTypes, BlockchainErrs, Order, Token, TokenByAddress, WebsitePaths } from 'ts/types';
import { AlertTypes, BlockchainErrs, PortalOrder, Token, TokenByAddress, WebsitePaths } from 'ts/types';
import { analytics } from 'ts/utils/analytics';
import { constants } from 'ts/utils/constants';
import { errorReporter } from 'ts/utils/error_reporter';
import { orderParser } from 'ts/utils/order_parser';
import { utils } from 'ts/utils/utils';
interface FillOrderProps {
@@ -36,7 +35,7 @@ interface FillOrderProps {
networkId: number;
userAddress: string;
tokenByAddress: TokenByAddress;
initialOrder: Order;
initialOrder: PortalOrder;
dispatcher: Dispatcher;
lastForceTokenStateRefetch: number;
isFullWidth?: boolean;
@@ -49,7 +48,7 @@ interface FillOrderState {
globalErrMsg: string;
orderJSON: string;
orderJSONErrMsg: string;
parsedOrder: Order;
parsedOrder: PortalOrder;
didFillOrderSucceed: boolean;
didCancelOrderSucceed: boolean;
unavailableTakerAmount: BigNumber;
@@ -191,16 +190,18 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
);
}
private _renderVisualOrder(): React.ReactNode {
const takerTokenAddress = this.state.parsedOrder.signedOrder.takerTokenAddress;
const takerTokenAddress = assetDataUtils.decodeERC20AssetData(this.state.parsedOrder.signedOrder.takerAssetData)
.tokenAddress;
const takerToken = this.props.tokenByAddress[takerTokenAddress];
const orderTakerAmount = new BigNumber(this.state.parsedOrder.signedOrder.takerTokenAmount);
const orderMakerAmount = new BigNumber(this.state.parsedOrder.signedOrder.makerTokenAmount);
const orderTakerAmount = this.state.parsedOrder.signedOrder.takerAssetAmount;
const orderMakerAmount = this.state.parsedOrder.signedOrder.makerAssetAmount;
const takerAssetToken = {
amount: orderTakerAmount.minus(this.state.unavailableTakerAmount),
symbol: takerToken.symbol,
};
const fillToken = this.props.tokenByAddress[takerTokenAddress];
const makerTokenAddress = this.state.parsedOrder.signedOrder.makerTokenAddress;
const makerTokenAddress = assetDataUtils.decodeERC20AssetData(this.state.parsedOrder.signedOrder.makerAssetData)
.tokenAddress;
const makerToken = this.props.tokenByAddress[makerTokenAddress];
const makerAssetToken = {
amount: orderMakerAmount.times(takerAssetToken.amount).div(orderTakerAmount),
@@ -210,7 +211,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
amount: this.props.orderFillAmount,
symbol: takerToken.symbol,
};
const parsedOrderExpiration = new BigNumber(this.state.parsedOrder.signedOrder.expirationUnixTimestampSec);
const parsedOrderExpiration = this.state.parsedOrder.signedOrder.expirationTimeSeconds;
let orderReceiveAmount = 0;
if (!_.isUndefined(this.props.orderFillAmount)) {
@@ -222,7 +223,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
const isUserMaker =
!_.isUndefined(this.state.parsedOrder) &&
this.state.parsedOrder.signedOrder.maker === this.props.userAddress;
this.state.parsedOrder.signedOrder.makerAddress === this.props.userAddress;
const expiryDate = utils.convertToReadableDateTimeFromUnixTimestamp(parsedOrderExpiration);
return (
<div className="pt3 pb1">
@@ -233,11 +234,11 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
Maker:
</div>
<div className="col col-2 pr1">
<Identicon address={this.state.parsedOrder.signedOrder.maker} diameter={23} />
<Identicon address={this.state.parsedOrder.signedOrder.makerAddress} diameter={23} />
</div>
<div className="col col-6">
<EthereumAddress
address={this.state.parsedOrder.signedOrder.maker}
address={this.state.parsedOrder.signedOrder.makerAddress}
networkId={this.props.networkId}
/>
</div>
@@ -367,17 +368,19 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
if (!_.isEmpty(this.state.orderJSONErrMsg)) {
return;
}
const makerTokenIfExists = this.props.tokenByAddress[this.state.parsedOrder.signedOrder.makerTokenAddress];
const takerTokenIfExists = this.props.tokenByAddress[this.state.parsedOrder.signedOrder.takerTokenAddress];
const makerTokenAddress = assetDataUtils.decodeERC20AssetData(this.state.parsedOrder.signedOrder.makerAssetData)
.tokenAddress;
const takerTokenAddress = assetDataUtils.decodeERC20AssetData(this.state.parsedOrder.signedOrder.takerAssetData)
.tokenAddress;
const makerTokenIfExists = this.props.tokenByAddress[makerTokenAddress];
const takerTokenIfExists = this.props.tokenByAddress[takerTokenAddress];
const tokensToTrack: Token[] = [];
const isUnseenMakerToken = _.isUndefined(makerTokenIfExists);
const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && utils.isTokenTracked(makerTokenIfExists);
if (isUnseenMakerToken) {
tokensToTrack.push({
...this.state.parsedOrder.metadata.makerToken,
address: this.state.parsedOrder.signedOrder.makerTokenAddress,
address: makerTokenAddress,
iconUrl: undefined,
trackedTimestamp: undefined,
isRegistered: false,
@@ -390,7 +393,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
if (isUnseenTakerToken) {
tokensToTrack.push({
...this.state.parsedOrder.metadata.takerToken,
address: this.state.parsedOrder.signedOrder.takerTokenAddress,
address: takerTokenAddress,
iconUrl: undefined,
trackedTimestamp: undefined,
isRegistered: false,
@@ -411,10 +414,10 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
private async _validateFillOrderFireAndForgetAsync(orderJSON: string): Promise<void> {
let orderJSONErrMsg = '';
let parsedOrder: Order;
let parsedOrder: PortalOrder;
let orderHash: string;
try {
const order = JSON.parse(orderJSON);
const order = orderParser.parseJsonString(orderJSON);
const validationResult = validator.validate(order, portalOrderSchema);
if (validationResult.errors.length > 0) {
orderJSONErrMsg = 'Submitted order JSON is not a valid order';
@@ -422,36 +425,16 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
return;
}
parsedOrder = order;
const makerAmount = new BigNumber(parsedOrder.signedOrder.makerTokenAmount);
const takerAmount = new BigNumber(parsedOrder.signedOrder.takerTokenAmount);
const expiration = new BigNumber(parsedOrder.signedOrder.expirationUnixTimestampSec);
const salt = new BigNumber(parsedOrder.signedOrder.salt);
const parsedMakerFee = new BigNumber(parsedOrder.signedOrder.makerFee);
const parsedTakerFee = new BigNumber(parsedOrder.signedOrder.takerFee);
const zeroExOrder: ZeroExOrder = {
exchangeContractAddress: parsedOrder.signedOrder.exchangeContractAddress,
expirationUnixTimestampSec: expiration,
feeRecipient: parsedOrder.signedOrder.feeRecipient,
maker: parsedOrder.signedOrder.maker,
makerFee: parsedMakerFee,
makerTokenAddress: parsedOrder.signedOrder.makerTokenAddress,
makerTokenAmount: makerAmount,
salt,
taker: _.isEmpty(parsedOrder.signedOrder.taker)
? constants.NULL_ADDRESS
: parsedOrder.signedOrder.taker,
takerFee: parsedTakerFee,
takerTokenAddress: parsedOrder.signedOrder.takerTokenAddress,
takerTokenAmount: takerAmount,
};
orderHash = getOrderHashHex(zeroExOrder);
const signedOrder = parsedOrder.signedOrder;
orderHash = orderHashUtils.getOrderHashHex(signedOrder);
const exchangeContractAddr = this.props.blockchain.getExchangeContractAddressIfExists();
const signature = parsedOrder.signedOrder.ecSignature;
const isSignatureValid = isValidSignature(orderHash, signature, parsedOrder.signedOrder.maker);
if (exchangeContractAddr !== parsedOrder.signedOrder.exchangeContractAddress) {
const signature = signedOrder.signature;
const isSignatureValid = await this.props.blockchain.isValidSignatureAsync(
orderHash,
signature,
signedOrder.makerAddress,
);
if (exchangeContractAddr !== signedOrder.exchangeAddress) {
orderJSONErrMsg = 'This order was made on another network or using a deprecated Exchange contract';
parsedOrder = undefined;
} else if (!isSignatureValid) {
@@ -484,11 +467,15 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
this.props.dispatcher.updateUserSuppliedOrderCache(undefined);
} else {
unavailableTakerAmount = await this.props.blockchain.getUnavailableTakerAmountAsync(orderHash);
const makerTokenAddress = assetDataUtils.decodeERC20AssetData(parsedOrder.signedOrder.makerAssetData)
.tokenAddress;
const takerTokenAddress = assetDataUtils.decodeERC20AssetData(parsedOrder.signedOrder.takerAssetData)
.tokenAddress;
const isMakerTokenAddressInRegistry = await this.props.blockchain.isAddressInTokenRegistryAsync(
parsedOrder.signedOrder.makerTokenAddress,
makerTokenAddress,
);
const isTakerTokenAddressInRegistry = await this.props.blockchain.isAddressInTokenRegistryAsync(
parsedOrder.signedOrder.takerTokenAddress,
takerTokenAddress,
);
this.setState({
isMakerTokenAddressInRegistry,
@@ -537,7 +524,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
globalErrMsg = 'You must specify a fill amount';
}
const signedOrder = this.props.blockchain.portalOrderToZeroExOrder(parsedOrder);
const signedOrder = parsedOrder.signedOrder;
if (_.isEmpty(globalErrMsg)) {
try {
await this.props.blockchain.validateFillOrderThrowIfInvalidAsync(
@@ -546,7 +533,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
this.props.userAddress,
);
} catch (err) {
globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.signedOrder.taker);
globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.signedOrder.takerAddress);
}
}
if (!_.isEmpty(globalErrMsg)) {
@@ -611,18 +598,8 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
return;
}
let globalErrMsg = '';
const takerTokenAmount = new BigNumber(parsedOrder.signedOrder.takerTokenAmount);
const signedOrder = this.props.blockchain.portalOrderToZeroExOrder(parsedOrder);
const orderHash = getOrderHashHex(signedOrder);
const unavailableTakerAmount = await this.props.blockchain.getUnavailableTakerAmountAsync(orderHash);
const availableTakerTokenAmount = takerTokenAmount.minus(unavailableTakerAmount);
try {
await this.props.blockchain.validateCancelOrderThrowIfInvalidAsync(signedOrder, availableTakerTokenAmount);
} catch (err) {
globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.signedOrder.taker);
}
const signedOrder = parsedOrder.signedOrder;
const takerTokenAmount = signedOrder.takerAssetAmount;
if (!_.isEmpty(globalErrMsg)) {
this.setState({
isCancelling: false,
@@ -631,7 +608,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
return;
}
try {
await this.props.blockchain.cancelOrderAsync(signedOrder, availableTakerTokenAmount);
await this.props.blockchain.cancelOrderAsync(signedOrder);
this.setState({
isCancelling: false,
didCancelOrderSucceed: true,

View File

@@ -33,11 +33,7 @@ export class FillOrderJSON extends React.Component<FillOrderJSONProps, FillOrder
},
};
const hintOrderExpiryTimestamp = utils.initialOrderExpiryUnixTimestampSec();
const hintECSignature = {
r: '0xf01103f759e2289a28593eaf22e5820032...',
s: '937862111edcba395f8a9e0cc1b2c5e12320...',
v: 27,
};
const hintECSignature = '0x012761a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc33';
const hintSalt = generatePseudoRandomSalt();
const feeRecipient = constants.NULL_ADDRESS;
const hintOrder = utils.generateOrder(

View File

@@ -1,6 +1,6 @@
import { generatePseudoRandomSalt, getOrderHashHex } from '@0xproject/order-utils';
import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils';
import { colors } from '@0xproject/react-shared';
import { ECSignature, Order as ZeroExOrder } from '@0xproject/types';
import { Order as ZeroExOrder } from '@0xproject/types';
import { BigNumber, logUtils } from '@0xproject/utils';
import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog';
@@ -20,7 +20,16 @@ import { SwapIcon } from 'ts/components/ui/swap_icon';
import { Dispatcher } from 'ts/redux/dispatcher';
import { portalOrderSchema } from 'ts/schemas/portal_order_schema';
import { validator } from 'ts/schemas/validator';
import { AlertTypes, BlockchainErrs, HashData, Order, Side, SideToAssetToken, Token, TokenByAddress } from 'ts/types';
import {
AlertTypes,
BlockchainErrs,
HashData,
PortalOrder,
Side,
SideToAssetToken,
Token,
TokenByAddress,
} from 'ts/types';
import { analytics } from 'ts/utils/analytics';
import { constants } from 'ts/utils/constants';
import { errorReporter } from 'ts/utils/error_reporter';
@@ -41,7 +50,7 @@ interface GenerateOrderFormProps {
orderExpiryTimestamp: BigNumber;
networkId: number;
userAddress: string;
orderECSignature: ECSignature;
orderSignature: string;
orderTakerAddress: string;
orderSalt: BigNumber;
sideToAssetToken: SideToAssetToken;
@@ -212,7 +221,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
<OrderJSON
exchangeContractIfExists={exchangeContractIfExists}
orderExpiryTimestamp={this.props.orderExpiryTimestamp}
orderECSignature={this.props.orderECSignature}
orderSignature={this.props.orderSignature}
orderTakerAddress={this.props.orderTakerAddress}
orderMakerAddress={this.props.userAddress}
orderSalt={this.props.orderSalt}
@@ -294,12 +303,12 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
return false;
}
}
private async _signTransactionAsync(): Promise<Order | undefined> {
private async _signTransactionAsync(): Promise<PortalOrder | undefined> {
this.setState({
signingState: SigningState.SIGNING,
});
const exchangeContractAddr = this.props.blockchain.getExchangeContractAddressIfExists();
if (_.isUndefined(exchangeContractAddr)) {
const exchangeAddress = this.props.blockchain.getExchangeContractAddressIfExists();
if (_.isUndefined(exchangeAddress)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
this.setState({
signingState: SigningState.UNSIGNED,
@@ -308,28 +317,31 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
}
const hashData = this.props.hashData;
const makerAssetData = assetDataUtils.encodeERC20AssetData(hashData.depositTokenContractAddr);
const takerAssetData = assetDataUtils.encodeERC20AssetData(hashData.receiveTokenContractAddr);
const zeroExOrder: ZeroExOrder = {
exchangeContractAddress: exchangeContractAddr,
expirationUnixTimestampSec: hashData.orderExpiryTimestamp,
feeRecipient: hashData.feeRecipientAddress,
maker: hashData.orderMakerAddress,
senderAddress: constants.NULL_ADDRESS,
exchangeAddress,
expirationTimeSeconds: hashData.orderExpiryTimestamp,
feeRecipientAddress: hashData.feeRecipientAddress,
makerAddress: hashData.orderMakerAddress,
makerFee: hashData.makerFee,
makerTokenAddress: hashData.depositTokenContractAddr,
makerTokenAmount: hashData.depositAmount,
makerAssetData,
makerAssetAmount: hashData.depositAmount,
salt: hashData.orderSalt,
taker: hashData.orderTakerAddress,
takerAddress: hashData.orderTakerAddress,
takerFee: hashData.takerFee,
takerTokenAddress: hashData.receiveTokenContractAddr,
takerTokenAmount: hashData.receiveAmount,
takerAssetData,
takerAssetAmount: hashData.receiveAmount,
};
const orderHash = getOrderHashHex(zeroExOrder);
const orderHash = orderHashUtils.getOrderHashHex(zeroExOrder);
let globalErrMsg = '';
let order;
try {
const ecSignature = await this.props.blockchain.signOrderHashAsync(orderHash);
const signature = await this.props.blockchain.signOrderHashAsync(orderHash);
order = utils.generateOrder(
exchangeContractAddr,
exchangeAddress,
this.props.sideToAssetToken,
hashData.orderExpiryTimestamp,
this.props.orderTakerAddress,
@@ -337,7 +349,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
hashData.makerFee,
hashData.takerFee,
hashData.feeRecipientAddress,
ecSignature,
signature,
this.props.tokenByAddress,
hashData.orderSalt,
);

View File

@@ -1,9 +1,10 @@
import { getOrderHashHex } from '@0xproject/order-utils';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { Styles } from '@0xproject/react-shared';
import { Order } from '@0xproject/types';
import * as _ from 'lodash';
import * as React from 'react';
import ReactTooltip = require('react-tooltip');
import { Blockchain } from 'ts/blockchain';
import { FakeTextField } from 'ts/components/ui/fake_text_field';
import { HashData } from 'ts/types';
@@ -42,23 +43,26 @@ export class HashInput extends React.Component<HashInputProps, HashInputState> {
);
}
private _generateMessageHashHex(): string {
const exchangeContractAddress = this.props.blockchain.getExchangeContractAddressIfExists();
const exchangeAddress = this.props.blockchain.getExchangeContractAddressIfExists();
const hashData = this.props.hashData;
const makerAssetData = assetDataUtils.encodeERC20AssetData(hashData.depositTokenContractAddr);
const takerAssetData = assetDataUtils.encodeERC20AssetData(hashData.receiveTokenContractAddr);
const order: Order = {
exchangeContractAddress,
expirationUnixTimestampSec: hashData.orderExpiryTimestamp,
feeRecipient: hashData.feeRecipientAddress,
maker: _.isEmpty(hashData.orderMakerAddress) ? constants.NULL_ADDRESS : hashData.orderMakerAddress,
senderAddress: constants.NULL_ADDRESS,
exchangeAddress,
expirationTimeSeconds: hashData.orderExpiryTimestamp,
feeRecipientAddress: hashData.feeRecipientAddress,
makerAddress: _.isEmpty(hashData.orderMakerAddress) ? constants.NULL_ADDRESS : hashData.orderMakerAddress,
makerFee: hashData.makerFee,
makerTokenAddress: hashData.depositTokenContractAddr,
makerTokenAmount: hashData.depositAmount,
makerAssetData,
makerAssetAmount: hashData.depositAmount,
salt: hashData.orderSalt,
taker: hashData.orderTakerAddress,
takerAddress: hashData.orderTakerAddress,
takerFee: hashData.takerFee,
takerTokenAddress: hashData.receiveTokenContractAddr,
takerTokenAmount: hashData.receiveAmount,
takerAssetData,
takerAssetAmount: hashData.receiveAmount,
};
const orderHash = getOrderHashHex(order);
const orderHash = orderHashUtils.getOrderHashHex(order);
return orderHash;
}
}

View File

@@ -1,4 +1,3 @@
import { ECSignature } from '@0xproject/types';
import { BigNumber, fetchAsync, logUtils } from '@0xproject/utils';
import * as _ from 'lodash';
import Paper from 'material-ui/Paper';
@@ -14,7 +13,7 @@ import { utils } from 'ts/utils/utils';
interface OrderJSONProps {
exchangeContractIfExists: string;
orderExpiryTimestamp: BigNumber;
orderECSignature: ECSignature;
orderSignature: string;
orderTakerAddress: string;
orderMakerAddress: string;
orderSalt: BigNumber;
@@ -48,7 +47,7 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
this.props.orderMakerFee,
this.props.orderTakerFee,
this.props.orderFeeRecipient,
this.props.orderECSignature,
this.props.orderSignature,
this.props.tokenByAddress,
this.props.orderSalt,
);
@@ -169,7 +168,7 @@ You can see and fill it here: ${this.state.shareLink}`);
this.props.orderMakerFee,
this.props.orderTakerFee,
this.props.orderFeeRecipient,
this.props.orderECSignature,
this.props.orderSignature,
this.props.tokenByAddress,
this.props.orderSalt,
);

View File

@@ -39,7 +39,7 @@ import {
BlockchainErrs,
HashData,
ItemByAddress,
Order,
PortalOrder,
ProviderType,
ScreenWidths,
Token,
@@ -71,7 +71,7 @@ export interface PortalProps {
userEtherBalanceInWei?: BigNumber;
userAddress: string;
shouldBlockchainErrDialogBeOpen: boolean;
userSuppliedOrderCache: Order;
userSuppliedOrderCache: PortalOrder;
location: Location;
flashMessage?: string | React.ReactNode;
lastForceTokenStateRefetch: number;
@@ -114,11 +114,11 @@ const DOCUMENT_DESCRIPTION = 'Learn about and trade on 0x Relayers';
export class Portal extends React.Component<PortalProps, PortalState> {
private _blockchain: Blockchain;
private readonly _sharedOrderIfExists: Order;
private readonly _sharedOrderIfExists: PortalOrder;
private readonly _throttledScreenWidthUpdate: () => void;
constructor(props: PortalProps) {
super(props);
this._sharedOrderIfExists = orderParser.parse(window.location.search);
this._sharedOrderIfExists = orderParser.parseQueryString(window.location.search);
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER);
const hasAcceptedDisclaimer =

View File

@@ -1,4 +1,3 @@
import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as React from 'react';
import { connect } from 'react-redux';
@@ -20,7 +19,7 @@ interface ConnectedState {
blockchainErr: BlockchainErrs;
blockchainIsLoaded: boolean;
orderExpiryTimestamp: BigNumber;
orderECSignature: ECSignature;
orderSignature: string;
userAddress: string;
orderTakerAddress: string;
orderSalt: BigNumber;
@@ -34,7 +33,7 @@ const mapStateToProps = (state: State, _ownProps: GenerateOrderFormProps): Conne
blockchainErr: state.blockchainErr,
blockchainIsLoaded: state.blockchainIsLoaded,
orderExpiryTimestamp: state.orderExpiryTimestamp,
orderECSignature: state.orderECSignature,
orderSignature: state.orderSignature,
orderTakerAddress: state.orderTakerAddress,
orderSalt: state.orderSalt,
networkId: state.networkId,

View File

@@ -6,7 +6,7 @@ import { Dispatch } from 'redux';
import { Portal as PortalComponent, PortalProps as PortalComponentProps } from 'ts/components/portal/portal';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, Side, TokenByAddress } from 'ts/types';
import { BlockchainErrs, HashData, PortalOrder, ProviderType, ScreenWidths, Side, TokenByAddress } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
@@ -25,7 +25,7 @@ interface ConnectedState {
screenWidth: ScreenWidths;
shouldBlockchainErrDialogBeOpen: boolean;
userAddress: string;
userSuppliedOrderCache: Order;
userSuppliedOrderCache: PortalOrder;
flashMessage?: string | React.ReactNode;
translate: Translate;
isPortalOnboardingShowing: boolean;

View File

@@ -1,4 +1,3 @@
import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Dispatch } from 'redux';
import { State } from 'ts/redux/reducer';
@@ -7,7 +6,7 @@ import {
AssetToken,
BlockchainErrs,
Language,
Order,
PortalOrder,
ProviderType,
ScreenWidths,
Side,
@@ -50,7 +49,7 @@ export class Dispatcher {
type: ActionTypes.UpdateOrderSalt,
});
}
public updateUserSuppliedOrderCache(order: Order): void {
public updateUserSuppliedOrderCache(order: PortalOrder): void {
this._dispatch({
data: order,
type: ActionTypes.UpdateUserSuppliedOrderCache,
@@ -149,10 +148,10 @@ export class Dispatcher {
type: ActionTypes.ForceTokenStateRefetch,
});
}
public updateECSignature(ecSignature: ECSignature): void {
public updateSignature(signature: string): void {
this._dispatch({
data: ecSignature,
type: ActionTypes.UpdateOrderECSignature,
data: signature,
type: ActionTypes.UpdateOrderSignature,
});
}
public updateUserWeiBalance(balance?: BigNumber): void {

View File

@@ -1,5 +1,4 @@
import { generatePseudoRandomSalt } from '@0xproject/order-utils';
import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as moment from 'moment';
@@ -7,7 +6,7 @@ import {
Action,
ActionTypes,
BlockchainErrs,
Order,
PortalOrder,
ProviderType,
ScreenWidths,
Side,
@@ -31,7 +30,7 @@ export interface State {
orderExpiryTimestamp: BigNumber;
orderFillAmount: BigNumber;
orderTakerAddress: string;
orderECSignature: ECSignature;
orderSignature: string;
orderSalt: BigNumber;
nodeVersion: string;
screenWidth: ScreenWidths;
@@ -45,7 +44,7 @@ export interface State {
isPortalOnboardingShowing: boolean;
hasPortalOnboardingBeenClosed: boolean;
// Note: cache of supplied orderJSON in fill order step. Do not use for anything else.
userSuppliedOrderCache: Order;
userSuppliedOrderCache: PortalOrder;
// Docs
docsVersion: string;
@@ -65,11 +64,7 @@ export const INITIAL_STATE: State = {
networkId: undefined,
orderExpiryTimestamp: utils.initialOrderExpiryUnixTimestampSec(),
orderFillAmount: undefined,
orderECSignature: {
r: '',
s: '',
v: 27,
},
orderSignature: '',
orderTakerAddress: constants.NULL_ADDRESS,
orderSalt: generatePseudoRandomSalt(),
nodeVersion: undefined,
@@ -90,7 +85,6 @@ export const INITIAL_STATE: State = {
// Docs
docsVersion: DEFAULT_DOCS_VERSION,
availableDocVersions: [DEFAULT_DOCS_VERSION],
// Shared
flashMessage: undefined,
providerType: ProviderType.Injected,
@@ -207,10 +201,10 @@ export function reducer(state: State = INITIAL_STATE, action: Action): State {
lastForceTokenStateRefetch: moment().unix(),
};
case ActionTypes.UpdateOrderECSignature: {
case ActionTypes.UpdateOrderSignature: {
return {
...state,
orderECSignature: action.data,
orderSignature: action.data,
};
}

View File

@@ -1,7 +1,7 @@
export const portalOrderSchema = {
id: '/PortalOrder',
properties: {
signedOrder: { $ref: '/SignedOrder' },
signedOrder: { $ref: '/signedOrderSchema' },
metadata: { $ref: '/OrderMetadata' },
},
required: ['signedOrder', 'metadata'],

View File

@@ -1,4 +1,4 @@
import { ECSignature } from '@0xproject/types';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Provider } from 'ethereum-types';
import * as React from 'react';
@@ -56,28 +56,12 @@ export interface OrderToken {
decimals: number;
}
export interface SignedOrder {
maker: string;
taker: string;
makerTokenAddress: string;
takerTokenAddress: string;
makerFee: string;
takerFee: string;
makerTokenAmount: string;
takerTokenAmount: string;
expirationUnixTimestampSec: string;
feeRecipient: string;
salt: string;
ecSignature: ECSignature;
exchangeContractAddress: string;
}
export interface OrderMetadata {
makerToken: OrderToken;
takerToken: OrderToken;
}
export interface Order {
export interface PortalOrder {
signedOrder: SignedOrder;
metadata: OrderMetadata;
}
@@ -120,7 +104,7 @@ export enum ActionTypes {
UpdateChosenAssetTokenAddress = 'UPDATE_CHOSEN_ASSET_TOKEN_ADDRESS',
UpdateOrderTakerAddress = 'UPDATE_ORDER_TAKER_ADDRESS',
UpdateOrderSalt = 'UPDATE_ORDER_SALT',
UpdateOrderECSignature = 'UPDATE_ORDER_EC_SIGNATURE',
UpdateOrderSignature = 'UPDATE_ORDER_SIGNATURE',
UpdateTokenByAddress = 'UPDATE_TOKEN_BY_ADDRESS',
RemoveTokenFromTokenByAddress = 'REMOVE_TOKEN_FROM_TOKEN_BY_ADDRESS',
ForceTokenStateRefetch = 'FORCE_TOKEN_STATE_REFETCH',

View File

@@ -1,5 +1,6 @@
import { assetDataUtils } from '@0xproject/order-utils';
import * as _ from 'lodash';
import { ObjectMap, Order } from 'ts/types';
import { ObjectMap, PortalOrder } from 'ts/types';
import { utils } from 'ts/utils/utils';
export interface HeapAnalytics {
@@ -53,12 +54,16 @@ export class Analytics {
}
// tslint:enable:no-floating-promises
// Custom methods
public trackOrderEvent(eventName: string, order: Order): void {
public trackOrderEvent(eventName: string, order: PortalOrder): void {
const takerTokenAmount = order.signedOrder.takerAssetAmount.toString();
const makerTokenAmount = order.signedOrder.makerAssetAmount.toString();
const takerToken = assetDataUtils.decodeERC20AssetData(order.signedOrder.takerAssetData).tokenAddress;
const makerToken = assetDataUtils.decodeERC20AssetData(order.signedOrder.makerAssetData).tokenAddress;
const orderLoggingData = {
takerTokenAmount: order.signedOrder.takerTokenAmount,
makeTokenAmount: order.signedOrder.makerTokenAmount,
takerToken: order.metadata.takerToken.symbol,
makerToken: order.metadata.makerToken.symbol,
takerTokenAmount,
makerTokenAmount,
takerToken,
makerToken,
};
this.track(eventName, orderLoggingData);
}

View File

@@ -1,12 +1,13 @@
import { orderParsingUtils } from '@0xproject/order-utils';
import { logUtils } from '@0xproject/utils';
import * as _ from 'lodash';
import { portalOrderSchema } from 'ts/schemas/portal_order_schema';
import { validator } from 'ts/schemas/validator';
import { Order } from 'ts/types';
import { PortalOrder } from 'ts/types';
export const orderParser = {
parse(queryString: string): Order | undefined {
parseQueryString(queryString: string): PortalOrder | undefined {
if (queryString.length === 0) {
return undefined;
}
@@ -28,6 +29,22 @@ export const orderParser = {
logUtils.log(`Invalid shared order: ${validationResult.errors}`);
return undefined;
}
return order;
const signedOrder = _.get(order, 'signedOrder');
const convertedSignedOrder = orderParsingUtils.convertOrderStringFieldsToBigNumber(signedOrder);
const result = {
...order,
signedOrder: convertedSignedOrder,
};
return result;
},
parseJsonString(orderJson: string): PortalOrder {
const order = JSON.parse(orderJson);
const signedOrder = _.get(order, 'signedOrder');
const convertedSignedOrder = orderParsingUtils.convertOrderStringFieldsToBigNumber(signedOrder);
const result = {
...order,
signedOrder: convertedSignedOrder,
};
return result;
},
};

View File

@@ -1,7 +1,7 @@
import { ContractWrappersError, ExchangeContractErrs } from '@0xproject/contract-wrappers';
import { OrderError } from '@0xproject/order-utils';
import { ContractWrappersError } from '@0xproject/contract-wrappers';
import { assetDataUtils, OrderError } from '@0xproject/order-utils';
import { constants as sharedConstants, Networks } from '@0xproject/react-shared';
import { ECSignature, Provider } from '@0xproject/types';
import { ExchangeContractErrs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as bowser from 'bowser';
@@ -10,13 +10,14 @@ import * as _ from 'lodash';
import * as moment from 'moment';
import * as numeral from 'numeral';
import { Provider } from 'ethereum-types';
import {
AccountState,
BlockchainCallErrs,
BrowserType,
Environments,
OperatingSystemType,
Order,
PortalOrder,
Providers,
ProviderType,
ScreenWidths,
@@ -64,35 +65,36 @@ export const utils = {
return formattedDate;
},
generateOrder(
exchangeContractAddress: string,
exchangeAddress: string,
sideToAssetToken: SideToAssetToken,
expirationUnixTimestampSec: BigNumber,
expirationTimeSeconds: BigNumber,
orderTakerAddress: string,
orderMakerAddress: string,
makerFee: BigNumber,
takerFee: BigNumber,
feeRecipient: string,
ecSignature: ECSignature,
feeRecipientAddress: string,
signature: string,
tokenByAddress: TokenByAddress,
orderSalt: BigNumber,
): Order {
): PortalOrder {
const makerToken = tokenByAddress[sideToAssetToken[Side.Deposit].address];
const takerToken = tokenByAddress[sideToAssetToken[Side.Receive].address];
const order = {
signedOrder: {
maker: orderMakerAddress,
taker: orderTakerAddress,
makerFee: makerFee.toString(),
takerFee: takerFee.toString(),
makerTokenAmount: sideToAssetToken[Side.Deposit].amount.toString(),
takerTokenAmount: sideToAssetToken[Side.Receive].amount.toString(),
makerTokenAddress: makerToken.address,
takerTokenAddress: takerToken.address,
expirationUnixTimestampSec: expirationUnixTimestampSec.toString(),
feeRecipient,
salt: orderSalt.toString(),
ecSignature,
exchangeContractAddress,
senderAddress: constants.NULL_ADDRESS,
makerAddress: orderMakerAddress,
takerAddress: orderTakerAddress,
makerFee,
takerFee,
makerAssetAmount: sideToAssetToken[Side.Deposit].amount,
takerAssetAmount: sideToAssetToken[Side.Receive].amount,
makerAssetData: assetDataUtils.encodeERC20AssetData(makerToken.address),
takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken.address),
expirationTimeSeconds,
feeRecipientAddress,
salt: orderSalt,
signature,
exchangeAddress,
},
metadata: {
makerToken: {
@@ -231,10 +233,10 @@ export const utils = {
const ContractWrappersErrorToHumanReadableError: { [error: string]: string } = {
[ContractWrappersError.ExchangeContractDoesNotExist]: 'Exchange contract does not exist',
[ContractWrappersError.EtherTokenContractDoesNotExist]: 'EtherToken contract does not exist',
[ContractWrappersError.TokenTransferProxyContractDoesNotExist]:
'TokenTransferProxy contract does not exist',
[ContractWrappersError.TokenRegistryContractDoesNotExist]: 'TokenRegistry contract does not exist',
[ContractWrappersError.TokenContractDoesNotExist]: 'Token contract does not exist',
[ContractWrappersError.ERC20ProxyContractDoesNotExist]: 'ERC20 proxy contract des not exist',
[ContractWrappersError.ERC721ProxyContractDoesNotExist]: 'ERC721 proxy contract des not exist',
[ContractWrappersError.ERC20TokenContractDoesNotExist]: 'ERC20 token contract does not exist',
[ContractWrappersError.ERC721TokenContractDoesNotExist]: 'ERC721 token contract does not exist',
[ContractWrappersError.ZRXContractDoesNotExist]: 'ZRX contract does not exist',
[BlockchainCallErrs.UserHasNoAssociatedAddresses]: 'User has no addresses available',
[OrderError.InvalidSignature]: 'Order signature is not valid',
@@ -247,12 +249,9 @@ export const utils = {
} = {
[ExchangeContractErrs.OrderFillExpired]: 'This order has expired',
[ExchangeContractErrs.OrderCancelExpired]: 'This order has expired',
[ExchangeContractErrs.OrderCancelAmountZero]: "Order cancel amount can't be 0",
[ExchangeContractErrs.OrderAlreadyCancelledOrFilled]:
'This order has already been completely filled or cancelled',
[ExchangeContractErrs.OrderCancelled]: 'This order has been cancelled',
[ExchangeContractErrs.OrderFillAmountZero]: "Order fill amount can't be 0",
[ExchangeContractErrs.OrderRemainingFillAmountZero]:
'This order has already been completely filled or cancelled',
[ExchangeContractErrs.OrderRemainingFillAmountZero]: 'This order has already been completely filled',
[ExchangeContractErrs.OrderFillRoundingError]:
'Rounding error will occur when filling this order. Please try filling a different amount.',
[ExchangeContractErrs.InsufficientTakerBalance]:

252
yarn.lock
View File

@@ -19,6 +19,23 @@
ethers "3.0.22"
lodash "4.17.10"
"0x.js@^0.38.6":
version "0.38.6"
resolved "https://registry.yarnpkg.com/0x.js/-/0x.js-0.38.6.tgz#f6cb2b6ef9aea2ff7696c923095e0b794c1d84fc"
dependencies:
"@0xproject/assert" "^0.2.14"
"@0xproject/base-contract" "^0.3.6"
"@0xproject/contract-wrappers" "^0.1.1"
"@0xproject/order-utils" "^0.0.9"
"@0xproject/order-watcher" "^0.0.8"
"@0xproject/sol-compiler" "^0.5.4"
"@0xproject/types" "^0.8.2"
"@0xproject/typescript-typings" "^0.4.3"
"@0xproject/utils" "^0.7.3"
"@0xproject/web3-wrapper" "^0.7.3"
ethers "3.0.22"
lodash "4.17.10"
"8fold-marked@0.3.9":
version "0.3.9"
resolved "https://registry.yarnpkg.com/8fold-marked/-/8fold-marked-0.3.9.tgz#bb89c645612f8ccfaffac1ca6e3c11f168c9cf59"
@@ -493,16 +510,6 @@
npmlog "^4.1.2"
write-file-atomic "^2.3.0"
"@0xproject/assert@^0.2.12", "@0xproject/assert@^0.2.14":
version "0.2.14"
resolved "https://registry.yarnpkg.com/@0xproject/assert/-/assert-0.2.14.tgz#7d5a373fedc8eb482716b730f4dddf3ef33bfa29"
dependencies:
"@0xproject/json-schemas" "^0.8.3"
"@0xproject/typescript-typings" "^0.4.3"
"@0xproject/utils" "^0.7.3"
lodash "4.17.10"
valid-url "1.0.9"
"@0xproject/assert@^0.2.13":
version "0.2.13"
resolved "https://registry.yarnpkg.com/@0xproject/assert/-/assert-0.2.13.tgz#8eb0e16cd6d802eae1b0ab86d344360ea0038331"
@@ -513,7 +520,17 @@
lodash "4.17.10"
valid-url "1.0.9"
"@0xproject/base-contract@^0.3.4", "@0xproject/base-contract@^0.3.5", "@0xproject/base-contract@^0.3.6":
"@0xproject/assert@^0.2.14":
version "0.2.14"
resolved "https://registry.yarnpkg.com/@0xproject/assert/-/assert-0.2.14.tgz#7d5a373fedc8eb482716b730f4dddf3ef33bfa29"
dependencies:
"@0xproject/json-schemas" "^0.8.3"
"@0xproject/typescript-typings" "^0.4.3"
"@0xproject/utils" "^0.7.3"
lodash "4.17.10"
valid-url "1.0.9"
"@0xproject/base-contract@^0.3.5", "@0xproject/base-contract@^0.3.6":
version "0.3.6"
resolved "https://registry.yarnpkg.com/@0xproject/base-contract/-/base-contract-0.3.6.tgz#c6d742ce2904bdd9e77524d99ba2438d3aae8a40"
dependencies:
@@ -538,27 +555,7 @@
sinon "^4.0.0"
websocket "^1.0.25"
"@0xproject/contract-wrappers@^0.0.5":
version "0.0.5"
resolved "https://registry.yarnpkg.com/@0xproject/contract-wrappers/-/contract-wrappers-0.0.5.tgz#36f91afb7de51478f9d2e4e0a3c4e685b3d18f28"
dependencies:
"@0xproject/assert" "^0.2.12"
"@0xproject/base-contract" "^0.3.4"
"@0xproject/fill-scenarios" "^0.0.4"
"@0xproject/json-schemas" "^0.8.1"
"@0xproject/order-utils" "^0.0.7"
"@0xproject/types" "^0.8.1"
"@0xproject/typescript-typings" "^0.4.1"
"@0xproject/utils" "^0.7.1"
"@0xproject/web3-wrapper" "^0.7.1"
ethereumjs-blockstream "2.0.7"
ethereumjs-util "5.1.5"
ethers "3.0.22"
js-sha3 "0.7.0"
lodash "4.17.10"
uuid "3.2.1"
"@0xproject/contract-wrappers@^0.1.0":
"@0xproject/contract-wrappers@^0.1.0", "@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"
dependencies:
@@ -579,19 +576,6 @@
lodash "4.17.10"
uuid "3.2.1"
"@0xproject/fill-scenarios@^0.0.4":
version "0.0.4"
resolved "https://registry.yarnpkg.com/@0xproject/fill-scenarios/-/fill-scenarios-0.0.4.tgz#4d23c75abda7e9f117b698c0b8b142af07e0c69e"
dependencies:
"@0xproject/base-contract" "^0.3.4"
"@0xproject/order-utils" "^0.0.7"
"@0xproject/types" "^0.8.1"
"@0xproject/typescript-typings" "^0.4.1"
"@0xproject/utils" "^0.7.1"
"@0xproject/web3-wrapper" "^0.7.1"
ethers "3.0.22"
lodash "4.17.10"
"@0xproject/fill-scenarios@^0.0.5":
version "0.0.5"
resolved "https://registry.yarnpkg.com/@0xproject/fill-scenarios/-/fill-scenarios-0.0.5.tgz#a62a240ae40423b9b73ecc0b1fc2abb58b76621c"
@@ -618,15 +602,6 @@
ethers "3.0.22"
lodash "4.17.10"
"@0xproject/json-schemas@^0.8.1", "@0xproject/json-schemas@^0.8.3":
version "0.8.3"
resolved "https://registry.yarnpkg.com/@0xproject/json-schemas/-/json-schemas-0.8.3.tgz#455e6219a6bd05e990392165192a983a9ab89f26"
dependencies:
"@0xproject/typescript-typings" "^0.4.3"
"@types/node" "9.6.0"
jsonschema "1.2.2"
lodash.values "4.3.0"
"@0xproject/json-schemas@^0.8.2":
version "0.8.2"
resolved "https://registry.yarnpkg.com/@0xproject/json-schemas/-/json-schemas-0.8.2.tgz#9d3f446e546ce0c959cf7beb45d41ac60476a78c"
@@ -636,21 +611,14 @@
jsonschema "1.2.2"
lodash.values "4.3.0"
"@0xproject/order-utils@^0.0.7":
version "0.0.7"
resolved "https://registry.yarnpkg.com/@0xproject/order-utils/-/order-utils-0.0.7.tgz#eaa465782ea5745bdad54e1a851533172d993b7c"
"@0xproject/json-schemas@^0.8.3":
version "0.8.3"
resolved "https://registry.yarnpkg.com/@0xproject/json-schemas/-/json-schemas-0.8.3.tgz#455e6219a6bd05e990392165192a983a9ab89f26"
dependencies:
"@0xproject/assert" "^0.2.12"
"@0xproject/json-schemas" "^0.8.1"
"@0xproject/types" "^0.8.1"
"@0xproject/typescript-typings" "^0.4.1"
"@0xproject/utils" "^0.7.1"
"@0xproject/web3-wrapper" "^0.7.1"
"@0xproject/typescript-typings" "^0.4.3"
"@types/node" "9.6.0"
bn.js "4.11.7"
ethereumjs-abi "0.6.5"
ethereumjs-util "5.1.5"
lodash "4.17.10"
jsonschema "1.2.2"
lodash.values "4.3.0"
"@0xproject/order-utils@^0.0.8":
version "0.0.8"
@@ -704,6 +672,26 @@
ethers "3.0.22"
lodash "4.17.10"
"@0xproject/order-watcher@^0.0.8":
version "0.0.8"
resolved "https://registry.yarnpkg.com/@0xproject/order-watcher/-/order-watcher-0.0.8.tgz#cfba4c39ca8c5d39e076276479383d0aae022c6d"
dependencies:
"@0xproject/assert" "^0.2.14"
"@0xproject/base-contract" "^0.3.6"
"@0xproject/contract-wrappers" "^0.1.1"
"@0xproject/fill-scenarios" "^0.0.6"
"@0xproject/json-schemas" "^0.8.3"
"@0xproject/order-utils" "^0.0.9"
"@0xproject/types" "^0.8.2"
"@0xproject/typescript-typings" "^0.4.3"
"@0xproject/utils" "^0.7.3"
"@0xproject/web3-wrapper" "^0.7.3"
bintrees "1.0.2"
ethereum-types "^0.0.2"
ethereumjs-blockstream "5.0.0"
ethers "3.0.22"
lodash "4.17.10"
"@0xproject/sol-compiler@^0.5.3", "@0xproject/sol-compiler@^0.5.4":
version "0.5.4"
resolved "https://registry.yarnpkg.com/@0xproject/sol-compiler/-/sol-compiler-0.5.4.tgz#3e0b04b0c02c5ec046ebb962b5ed20978c6b4cdd"
@@ -741,7 +729,7 @@
dependencies:
bignumber.js "~4.1.0"
"@0xproject/types@^0.8.1", "@0xproject/types@^0.8.2":
"@0xproject/types@^0.8.2":
version "0.8.2"
resolved "https://registry.yarnpkg.com/@0xproject/types/-/types-0.8.2.tgz#6f936b73bfb6f017b5102002d97da0881da92d1b"
dependencies:
@@ -755,7 +743,7 @@
"@0xproject/types" "^0.5.0"
bignumber.js "~4.1.0"
"@0xproject/typescript-typings@^0.4.1", "@0xproject/typescript-typings@^0.4.2", "@0xproject/typescript-typings@^0.4.3":
"@0xproject/typescript-typings@^0.4.2", "@0xproject/typescript-typings@^0.4.3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@0xproject/typescript-typings/-/typescript-typings-0.4.3.tgz#f99f939a43f2764ad7182fcd78a71212a1d76d96"
dependencies:
@@ -763,7 +751,7 @@
bignumber.js "~4.1.0"
ethereum-types "^0.0.2"
"@0xproject/utils@^0.7.1", "@0xproject/utils@^0.7.2", "@0xproject/utils@^0.7.3":
"@0xproject/utils@^0.7.2", "@0xproject/utils@^0.7.3":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@0xproject/utils/-/utils-0.7.3.tgz#ffa7c6da9bf0dd3e13694f185dcfc48a8981ff05"
dependencies:
@@ -777,7 +765,7 @@
lodash "4.17.10"
web3 "0.20.6"
"@0xproject/web3-wrapper@^0.7.1", "@0xproject/web3-wrapper@^0.7.2", "@0xproject/web3-wrapper@^0.7.3":
"@0xproject/web3-wrapper@^0.7.2", "@0xproject/web3-wrapper@^0.7.3":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@0xproject/web3-wrapper/-/web3-wrapper-0.7.3.tgz#9bd50b034b92fd505b6766b6e225f014b6d08b08"
dependencies:
@@ -950,6 +938,22 @@
version "0.6.0"
resolved "https://registry.yarnpkg.com/@types/depcheck/-/depcheck-0.6.0.tgz#13c8654983feb0916f45c40b2d9fafe0c8b0e4a8"
"@types/detect-node@2.0.0":
version "2.0.0"
resolved "https://registry.npmjs.org/@types/detect-node/-/detect-node-2.0.0.tgz#696e024ddd105c72bbc6a2e3f97902a2886f2c3f"
"@types/eth-lightwallet@^3.0.0":
version "3.0.0"
resolved "https://registry.npmjs.org/@types/eth-lightwallet/-/eth-lightwallet-3.0.0.tgz#9be5b59dc6fb3fcdb01e65c2c2a79cd601f72dd4"
dependencies:
"@types/node" "*"
"@types/ethereum-protocol@*":
version "1.0.0"
resolved "https://registry.npmjs.org/@types/ethereum-protocol/-/ethereum-protocol-1.0.0.tgz#416e3827d5fdfa4658b0045b35a008747871b271"
dependencies:
bignumber.js "7.2.1"
"@types/ethereumjs-abi@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@types/ethereumjs-abi/-/ethereumjs-abi-0.6.0.tgz#72d21083a36d9288821b62905e04b15e0c12175d"
@@ -995,6 +999,12 @@
dependencies:
"@types/node" "*"
"@types/ganache-core@^2.1.0":
version "2.1.0"
resolved "https://registry.npmjs.org/@types/ganache-core/-/ganache-core-2.1.0.tgz#b6702857a239d483b79f008f3205bbbc17f080e0"
dependencies:
"@types/ethereum-protocol" "*"
"@types/glob@*", "@types/glob@5.0.35", "@types/glob@^5.0.33":
version "5.0.35"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a"
@@ -1118,6 +1128,10 @@
version "5.2.3"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.3.tgz#11f3a5629d67cd444fa6c94536576244e6a52ea9"
"@types/newman@^3.9.0":
version "3.9.0"
resolved "https://registry.npmjs.org/@types/newman/-/newman-3.9.0.tgz#f46427e8f633545dd94e8df0c251e22145f88227"
"@types/nock@^9.1.2":
version "9.1.3"
resolved "https://registry.yarnpkg.com/@types/nock/-/nock-9.1.3.tgz#1d445679375b9e25afd449dc56585f81729454e8"
@@ -1286,9 +1300,9 @@
version "0.0.7"
resolved "https://registry.yarnpkg.com/@types/sleep/-/sleep-0.0.7.tgz#0572b5d06978b4305671c614b0f68b4640ce7d43"
"@types/solidity-parser-antlr@^0.2.1":
"@types/solidity-parser-antlr@^0.2.0":
version "0.2.1"
resolved "https://registry.yarnpkg.com/@types/solidity-parser-antlr/-/solidity-parser-antlr-0.2.1.tgz#29ff386773a72a06c8a9c40c666d2a1cea53c2ed"
resolved "https://registry.npmjs.org/@types/solidity-parser-antlr/-/solidity-parser-antlr-0.2.1.tgz#29ff386773a72a06c8a9c40c666d2a1cea53c2ed"
"@types/tmp@^0.0.33":
version "0.0.33"
@@ -1304,6 +1318,12 @@
version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/valid-url/-/valid-url-1.0.2.tgz#60fa435ce24bfd5ba107b8d2a80796aeaf3a8f45"
"@types/web3-provider-engine@^14.0.0":
version "14.0.0"
resolved "https://registry.npmjs.org/@types/web3-provider-engine/-/web3-provider-engine-14.0.0.tgz#43adc3b39dc9812b82aef8cd2d66577665ad59b0"
dependencies:
"@types/ethereum-protocol" "*"
"@types/websocket@^0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-0.0.39.tgz#aa971e24f9c1455fe2a57ee3e69c7d395016b12a"
@@ -1411,9 +1431,9 @@ aes-js@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d"
aes-js@^0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d"
aes-js@^3.1.1:
version "3.1.1"
resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.1.1.tgz#89fd1f94ae51b4c72d62466adc1a7323ff52f072"
ajv-keywords@^2.1.0:
version "2.1.1"
@@ -2479,10 +2499,6 @@ balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
base-x@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/base-x/-/base-x-1.1.0.tgz#42d3d717474f9ea02207f6d1aa1f426913eeb7ac"
base-x@^3.0.2:
version "3.0.4"
resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77"
@@ -2587,6 +2603,10 @@ big.js@^3.1.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
bignumber.js@7.2.1:
version "7.2.1"
resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2":
version "2.0.7"
resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
@@ -2890,7 +2910,7 @@ browserslist@^2.1.2:
caniuse-lite "^1.0.30000792"
electron-to-chromium "^1.3.30"
bs58@=4.0.1:
bs58@=4.0.1, bs58@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a"
dependencies:
@@ -2900,18 +2920,13 @@ bs58@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d"
bs58@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-3.1.0.tgz#d4c26388bf4804cac714141b1945aa47e5eb248e"
bs58check@^2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc"
dependencies:
base-x "^1.1.0"
bs58check@^1.0.8:
version "1.3.4"
resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-1.3.4.tgz#c52540073749117714fa042c3047eb8f9151cbf8"
dependencies:
bs58 "^3.1.0"
bs58 "^4.0.0"
create-hash "^1.1.0"
safe-buffer "^5.1.2"
btoa@1.1.2:
version "1.1.2"
@@ -5255,14 +5270,6 @@ ethereumjs-block@~1.2.2:
ethereumjs-util "^4.0.1"
merkle-patricia-tree "^2.1.2"
ethereumjs-blockstream@2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/ethereumjs-blockstream/-/ethereumjs-blockstream-2.0.7.tgz#8e791d18d517f13e0ba928892dda545dc930936b"
dependencies:
immutable "3.8.1"
source-map-support "0.4.14"
uuid "3.0.1"
ethereumjs-blockstream@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ethereumjs-blockstream/-/ethereumjs-blockstream-5.0.0.tgz#63bfe9185757329a32822d5815562eb1dcd75d71"
@@ -5297,7 +5304,7 @@ ethereumjs-util@5.1.5, ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumj
safe-buffer "^5.1.1"
secp256k1 "^3.0.1"
ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0:
ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6"
dependencies:
@@ -5351,17 +5358,18 @@ ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4:
rustbn.js "~0.1.1"
safe-buffer "^5.1.1"
ethereumjs-wallet@0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb"
ethereumjs-wallet@~0.6.0:
version "0.6.2"
resolved "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.2.tgz#67244b6af3e8113b53d709124b25477b64aeccda"
dependencies:
aes-js "^0.2.3"
bs58check "^1.0.8"
ethereumjs-util "^4.4.0"
hdkey "^0.7.0"
aes-js "^3.1.1"
bs58check "^2.1.2"
ethereumjs-util "^5.2.0"
hdkey "^1.0.0"
safe-buffer "^5.1.2"
scrypt.js "^0.2.0"
utf8 "^2.1.1"
uuid "^2.0.1"
utf8 "^3.0.0"
uuid "^3.3.2"
ethers@0xproject/ethers.js#eip-838-reasons, ethers@3.0.22:
version "3.0.18"
@@ -6120,7 +6128,7 @@ ganache-core@0xProject/ganache-core#monorepo-dep:
ethereumjs-tx "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default"
ethereumjs-util "^5.2.0"
ethereumjs-vm "2.3.5"
ethereumjs-wallet "0.6.0"
ethereumjs-wallet "~0.6.0"
fake-merkle-patricia-tree "~1.0.1"
heap "~0.2.6"
js-scrypt "^0.2.0"
@@ -6802,13 +6810,21 @@ hawk@~6.0.2:
hoek "4.x.x"
sntp "2.x.x"
hdkey@^0.7.0, hdkey@^0.7.1:
hdkey@^0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632"
dependencies:
coinstring "^2.0.0"
secp256k1 "^3.0.1"
hdkey@^1.0.0:
version "1.1.0"
resolved "https://registry.npmjs.org/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29"
dependencies:
coinstring "^2.0.0"
safe-buffer "^5.1.1"
secp256k1 "^3.0.1"
he@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
@@ -7080,10 +7096,6 @@ immediate@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c"
immutable@3.8.1:
version "3.8.1"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.1.tgz#200807f11ab0f72710ea485542de088075f68cd2"
immutable@3.8.2:
version "3.8.2"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
@@ -12791,12 +12803,6 @@ source-map-resolve@^0.5.0:
source-map-url "^0.4.0"
urix "^0.1.0"
source-map-support@0.4.14:
version "0.4.14"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.14.tgz#9d4463772598b86271b4f523f6c1f4e02a7d6aef"
dependencies:
source-map "^0.5.6"
source-map-support@0.5.6, source-map-support@^0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13"
@@ -14311,6 +14317,10 @@ utf8@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96"
utf8@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1"
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"