aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website/ts
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-09-28 19:08:12 +0800
committerFabio Berger <me@fabioberger.com>2018-09-28 19:08:12 +0800
commitba7de7204d29d4004c347190be7a3b8c84951b82 (patch)
tree9dddbd1ded45484a6cb968cdf799bf5ce991477b /packages/website/ts
parentf3ad64aa1c2930affbfd074316b5f407580b7523 (diff)
parenta737cfa004ee1dc18be935f61fb9c289ed5623fd (diff)
downloaddexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.gz
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.bz2
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.lz
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.xz
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.tar.zst
dexon-sol-tools-ba7de7204d29d4004c347190be7a3b8c84951b82.zip
merge development
Diffstat (limited to 'packages/website/ts')
-rw-r--r--packages/website/ts/artifacts/Exchange.json610
-rw-r--r--packages/website/ts/blockchain.ts209
-rw-r--r--packages/website/ts/components/dialogs/blockchain_err_dialog.tsx2
-rw-r--r--packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx4
-rw-r--r--packages/website/ts/components/dialogs/ledger_config_dialog.tsx2
-rw-r--r--packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx2
-rw-r--r--packages/website/ts/components/dialogs/send_dialog.tsx4
-rw-r--r--packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx4
-rw-r--r--packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx2
-rw-r--r--packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx2
-rw-r--r--packages/website/ts/components/fill_order.tsx113
-rw-r--r--packages/website/ts/components/fill_order_json.tsx6
-rw-r--r--packages/website/ts/components/fill_warning_dialog.tsx4
-rw-r--r--packages/website/ts/components/generate_order/asset_picker.tsx4
-rw-r--r--packages/website/ts/components/generate_order/generate_order_form.tsx54
-rw-r--r--packages/website/ts/components/inputs/hash_input.tsx28
-rw-r--r--packages/website/ts/components/inputs/token_amount_input.tsx2
-rw-r--r--packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx4
-rw-r--r--packages/website/ts/components/order_json.tsx7
-rw-r--r--packages/website/ts/components/portal/portal.tsx10
-rw-r--r--packages/website/ts/components/relayer_index/relayer_index.tsx6
-rw-r--r--packages/website/ts/components/token_balances.tsx20
-rw-r--r--packages/website/ts/components/top_bar/top_bar.tsx14
-rw-r--r--packages/website/ts/components/ui/button.tsx1
-rw-r--r--packages/website/ts/components/ui/lifecycle_raised_button.tsx2
-rw-r--r--packages/website/ts/components/ui/text.tsx2
-rw-r--r--packages/website/ts/components/ui/typed_text.tsx75
-rw-r--r--packages/website/ts/components/wallet/body_overlay.tsx6
-rw-r--r--packages/website/ts/containers/connect_documentation.ts2
-rw-r--r--packages/website/ts/containers/contract_wrappers_documentation.ts3
-rw-r--r--packages/website/ts/containers/ethereum_types_documentation.ts1
-rw-r--r--packages/website/ts/containers/generate_order_form.ts5
-rw-r--r--packages/website/ts/containers/order_utils_documentation.ts1
-rw-r--r--packages/website/ts/containers/order_watcher_documentation.ts1
-rw-r--r--packages/website/ts/containers/portal.ts4
-rw-r--r--packages/website/ts/containers/smart_contracts_documentation.ts11
-rw-r--r--packages/website/ts/containers/sol_compiler_documentation.ts2
-rw-r--r--packages/website/ts/containers/sol_cov_documentation.ts2
-rw-r--r--packages/website/ts/containers/subproviders_documentation.ts3
-rw-r--r--packages/website/ts/containers/web3_wrapper_documentation.ts3
-rw-r--r--packages/website/ts/containers/zero_ex_js_documentation.ts36
-rw-r--r--packages/website/ts/globals.d.ts1
-rw-r--r--packages/website/ts/index.tsx3
-rw-r--r--packages/website/ts/pages/about/about.tsx44
-rw-r--r--packages/website/ts/pages/documentation/doc_page.tsx26
-rw-r--r--packages/website/ts/pages/landing/landing.tsx536
-rw-r--r--packages/website/ts/redux/dispatcher.ts11
-rw-r--r--packages/website/ts/redux/reducer.ts18
-rw-r--r--packages/website/ts/schemas/portal_order_schema.ts2
-rw-r--r--packages/website/ts/types.ts34
-rw-r--r--packages/website/ts/utils/analytics.ts18
-rw-r--r--packages/website/ts/utils/configs.ts27
-rw-r--r--packages/website/ts/utils/constants.ts7
-rw-r--r--packages/website/ts/utils/doc_utils.ts4
-rw-r--r--packages/website/ts/utils/order_parser.ts23
-rw-r--r--packages/website/ts/utils/token_address_overrides.ts24
-rw-r--r--packages/website/ts/utils/utils.ts71
57 files changed, 743 insertions, 1379 deletions
diff --git a/packages/website/ts/artifacts/Exchange.json b/packages/website/ts/artifacts/Exchange.json
deleted file mode 100644
index af8db7360..000000000
--- a/packages/website/ts/artifacts/Exchange.json
+++ /dev/null
@@ -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"
- }
- }
-}
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index 45994be5f..c420bbf3a 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -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,16 @@ 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 { 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';
@@ -48,7 +43,6 @@ import {
InjectedProviderObservable,
InjectedProviderUpdate,
InjectedWeb3,
- Order as PortalOrder,
Providers,
ProviderType,
Side,
@@ -65,9 +59,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;
@@ -75,7 +66,7 @@ const providerToName: { [provider: string]: string } = {
[Providers.Metamask]: constants.PROVIDER_NAME_METAMASK,
[Providers.Parity]: constants.PROVIDER_NAME_PARITY_SIGNER,
[Providers.Mist]: constants.PROVIDER_NAME_MIST,
- [Providers.Toshi]: constants.PROVIDER_NAME_TOSHI,
+ [Providers.CoinbaseWallet]: constants.PROVIDER_NAME_COINBASE_WALLET,
[Providers.Cipher]: constants.PROVIDER_NAME_CIPHER,
};
@@ -83,6 +74,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,9 +222,15 @@ 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);
- return !_.isUndefined(tokenIfExists);
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ const tokenIfExists = await this._zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
+ // HACK: Override token addresses on testnets
+ const tokenSymbolToAddressOverrides = tokenAddressOverrides[this.networkId];
+ let isTokenAddressInOverrides = false;
+ if (!_.isUndefined(tokenSymbolToAddressOverrides)) {
+ isTokenAddressInOverrides = _.values(tokenSymbolToAddressOverrides).includes(tokenAddress);
+ }
+ return !_.isUndefined(tokenIfExists) || isTokenAddressInOverrides;
}
public getLedgerDerivationPathIfExists(): string {
if (_.isUndefined(this._ledgerSubprovider)) {
@@ -266,7 +264,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 +305,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 +330,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;
- }
- public async cancelOrderAsync(signedOrder: SignedOrder, cancelTakerTokenAmount: BigNumber): Promise<BigNumber> {
+ 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): 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 +381,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 +422,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 +430,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 +521,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 +634,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 +679,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 +712,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 +726,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 +776,22 @@ 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 tokenSymbolToAddressOverrides = tokenAddressOverrides[this.networkId];
+ if (!_.isUndefined(tokenAddressOverrides)) {
+ // HACK: Override token addresses on testnets
+ tokenRegistryTokens = _.map(tokenRegistryTokens, (token: ZeroExToken) => {
+ const overrideIfExists = tokenSymbolToAddressOverrides[token.symbol];
+ if (!_.isUndefined(overrideIfExists)) {
+ return {
+ ...token,
+ address: overrideIfExists,
+ };
+ }
+ return token;
+ });
+ }
}
const tokenByAddress: TokenByAddress = {};
_.each(tokenRegistryTokens, (t: ZeroExToken) => {
@@ -877,6 +871,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();
}
diff --git a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
index c8e10303f..18c060991 100644
--- a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
+++ b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
@@ -22,7 +22,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
key="blockchainErrOk"
label="Ok"
primary={true}
- onTouchTap={this.props.toggleDialogFn.bind(this.props.toggleDialogFn, false)}
+ onClick={this.props.toggleDialogFn.bind(this.props.toggleDialogFn, false)}
/>,
];
diff --git a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
index 5f4bf8519..f2cfb279a 100644
--- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
+++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
@@ -54,8 +54,8 @@ export class EthWethConversionDialog extends React.Component<
}
public render(): React.ReactNode {
const convertDialogActions = [
- <FlatButton key="cancel" label="Cancel" onTouchTap={this._onCancel.bind(this)} />,
- <FlatButton key="convert" label="Convert" primary={true} onTouchTap={this._onConvertClick.bind(this)} />,
+ <FlatButton key="cancel" label="Cancel" onClick={this._onCancel.bind(this)} />,
+ <FlatButton key="convert" label="Convert" primary={true} onClick={this._onConvertClick.bind(this)} />,
];
const title = this.props.direction === Side.Deposit ? 'Wrap ETH' : 'Unwrap WETH';
return !_.isUndefined(this.props.etherBalanceInWei) ? (
diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
index d2f373d67..fbc6c868b 100644
--- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
+++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
@@ -64,7 +64,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
}
public render(): React.ReactNode {
const dialogActions = [
- <FlatButton key="ledgerConnectCancel" label="Cancel" onTouchTap={this._onClose.bind(this)} />,
+ <FlatButton key="ledgerConnectCancel" label="Cancel" onClick={this._onClose.bind(this)} />,
];
const dialogTitle =
this.state.stepIndex === LedgerSteps.CONNECT ? 'Connect to your Ledger' : 'Select desired address';
diff --git a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
index 41a17fe96..ef295762b 100644
--- a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
+++ b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
@@ -13,7 +13,7 @@ export const PortalDisclaimerDialog = (props: PortalDisclaimerDialogProps) => {
<Dialog
title="0x Portal Disclaimer"
titleStyle={{ fontWeight: 100 }}
- actions={[<FlatButton key="portalAgree" label="I Agree" onTouchTap={props.onToggleDialog} />]}
+ actions={[<FlatButton key="portalAgree" label="I Agree" onClick={props.onToggleDialog} />]}
open={props.isOpen}
onRequestClose={props.onToggleDialog}
autoScrollBodyContent={true}
diff --git a/packages/website/ts/components/dialogs/send_dialog.tsx b/packages/website/ts/components/dialogs/send_dialog.tsx
index c1179dbd0..2754b153f 100644
--- a/packages/website/ts/components/dialogs/send_dialog.tsx
+++ b/packages/website/ts/components/dialogs/send_dialog.tsx
@@ -38,13 +38,13 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState
}
public render(): React.ReactNode {
const transferDialogActions = [
- <FlatButton key="cancelTransfer" label="Cancel" onTouchTap={this._onCancel.bind(this)} />,
+ <FlatButton key="cancelTransfer" label="Cancel" onClick={this._onCancel.bind(this)} />,
<FlatButton
key="sendTransfer"
disabled={this._hasErrors()}
label="Send"
primary={true}
- onTouchTap={this._onSendClick.bind(this)}
+ onClick={this._onSendClick.bind(this)}
/>,
];
return (
diff --git a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
index 3751ce06f..c8d5af6b6 100644
--- a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
+++ b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
@@ -43,12 +43,12 @@ export class TrackTokenConfirmationDialog extends React.Component<
<FlatButton
key="trackNo"
label="No"
- onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)}
+ onClick={this._onTrackConfirmationRespondedAsync.bind(this, false)}
/>,
<FlatButton
key="trackYes"
label="Yes"
- onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)}
+ onClick={this._onTrackConfirmationRespondedAsync.bind(this, true)}
/>,
]}
open={this.props.isOpen}
diff --git a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx
index 3ebab03ef..afbb30b82 100644
--- a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx
+++ b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx
@@ -14,7 +14,7 @@ export const U2fNotSupportedDialog = (props: U2fNotSupportedDialogProps) => {
<Dialog
title="U2F Not Supported"
titleStyle={{ fontWeight: 100 }}
- actions={[<FlatButton key="u2fNo" label="Ok" onTouchTap={props.onToggleDialog} />]}
+ actions={[<FlatButton key="u2fNo" label="Ok" onClick={props.onToggleDialog} />]}
open={props.isOpen}
onRequestClose={props.onToggleDialog}
autoScrollBodyContent={true}
diff --git a/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx
index 78b270c1e..cf2c4dda5 100644
--- a/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx
+++ b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx
@@ -14,7 +14,7 @@ export const WrappedEthSectionNoticeDialog = (props: WrappedEthSectionNoticeDial
title="Dedicated Wrapped Ether Section"
titleStyle={{ fontWeight: 100 }}
actions={[
- <FlatButton key="acknowledgeWrapEthSection" label="Sounds good" onTouchTap={props.onToggleDialog} />,
+ <FlatButton key="acknowledgeWrapEthSection" label="Sounds good" onClick={props.onToggleDialog} />,
]}
open={props.isOpen}
onRequestClose={props.onToggleDialog}
diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx
index 7da2e0870..3c3155349 100644
--- a/packages/website/ts/components/fill_order.tsx
+++ b/packages/website/ts/components/fill_order.tsx
@@ -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,
diff --git a/packages/website/ts/components/fill_order_json.tsx b/packages/website/ts/components/fill_order_json.tsx
index 90eedbb18..1ecc426bd 100644
--- a/packages/website/ts/components/fill_order_json.tsx
+++ b/packages/website/ts/components/fill_order_json.tsx
@@ -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(
diff --git a/packages/website/ts/components/fill_warning_dialog.tsx b/packages/website/ts/components/fill_warning_dialog.tsx
index 45c492221..4821aaabe 100644
--- a/packages/website/ts/components/fill_warning_dialog.tsx
+++ b/packages/website/ts/components/fill_warning_dialog.tsx
@@ -18,12 +18,12 @@ export const FillWarningDialog = (props: FillWarningDialogProps) => {
<FlatButton
key="fillWarningCancel"
label="Cancel"
- onTouchTap={() => props.onToggleDialog(didCancel)} // tslint:disable-line:jsx-no-lambda
+ onClick={() => props.onToggleDialog(didCancel)} // tslint:disable-line:jsx-no-lambda
/>,
<FlatButton
key="fillWarningContinue"
label="Fill Order"
- onTouchTap={() => props.onToggleDialog(!didCancel)} // tslint:disable-line:jsx-no-lambda
+ onClick={() => props.onToggleDialog(!didCancel)} // tslint:disable-line:jsx-no-lambda
/>,
]}
open={props.isOpen}
diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx
index 2dca3483f..98aad6c62 100644
--- a/packages/website/ts/components/generate_order/asset_picker.tsx
+++ b/packages/website/ts/components/generate_order/asset_picker.tsx
@@ -73,12 +73,12 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
<FlatButton
key="noTracking"
label="No"
- onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)}
+ onClick={this._onTrackConfirmationRespondedAsync.bind(this, false)}
/>,
<FlatButton
key="yesTrack"
label="Yes"
- onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)}
+ onClick={this._onTrackConfirmationRespondedAsync.bind(this, true)}
/>,
],
},
diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx
index 72efab033..ec153c005 100644
--- a/packages/website/ts/components/generate_order/generate_order_form.tsx
+++ b/packages/website/ts/components/generate_order/generate_order_form.tsx
@@ -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,
);
diff --git a/packages/website/ts/components/inputs/hash_input.tsx b/packages/website/ts/components/inputs/hash_input.tsx
index 8d9cdfc0b..5125ec4de 100644
--- a/packages/website/ts/components/inputs/hash_input.tsx
+++ b/packages/website/ts/components/inputs/hash_input.tsx
@@ -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;
}
}
diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx
index 93ef516cf..db093fb68 100644
--- a/packages/website/ts/components/inputs/token_amount_input.tsx
+++ b/packages/website/ts/components/inputs/token_amount_input.tsx
@@ -111,7 +111,7 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok
<span>
Insufficient allowance.{' '}
<Link
- to={`${WebsitePaths.Portal}/balances`}
+ to={`${WebsitePaths.Portal}/account`}
style={{ cursor: 'pointer', color: colors.darkestGrey }}
>
Set allowance
diff --git a/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx b/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
index d618c8318..1035d4ad9 100644
--- a/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
+++ b/packages/website/ts/components/onboarding/install_wallet_onboarding_step.tsx
@@ -12,7 +12,7 @@ export const InstallWalletOnboardingStep: React.StatelessComponent<InstallWallet
const followupText = isOnMobile
? `Please revisit this site in your mobile dApp browser to continue!`
: `Please refresh the page once you've done this to continue!`;
- const downloadText = isOnMobile ? 'Get the Toshi Wallet' : 'Get the MetaMask extension';
+ const downloadText = isOnMobile ? 'Get Coinbase Wallet' : 'Get the MetaMask extension';
return (
<div className="flex items-center flex-column">
<Text>First, you need to connect to a wallet. This will be used across all 0x relayers and dApps.</Text>
@@ -21,7 +21,7 @@ export const InstallWalletOnboardingStep: React.StatelessComponent<InstallWallet
height="50px"
width="50px"
borderRadius="22%"
- src={isOnMobile ? '/images/toshi_logo.jpg' : '/images/metamask_icon.png'}
+ src={isOnMobile ? '/images/coinbase_wallet_logo.png' : '/images/metamask_icon.png'}
/>
<Container marginLeft="10px">
<a href={downloadLink} target="_blank">
diff --git a/packages/website/ts/components/order_json.tsx b/packages/website/ts/components/order_json.tsx
index cf06f10c8..a2a53a523 100644
--- a/packages/website/ts/components/order_json.tsx
+++ b/packages/website/ts/components/order_json.tsx
@@ -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,
);
diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx
index ff11880e3..b42954f60 100644
--- a/packages/website/ts/components/portal/portal.tsx
+++ b/packages/website/ts/components/portal/portal.tsx
@@ -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 =
@@ -545,7 +545,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
<Section
header={!isMobile && <TextHeader labelText="0x Relayers" />}
body={
- <Container className="flex flex-column items-center">
+ <Container className="flex flex-column">
{isMobile && (
<Container marginTop="20px" marginBottom="20px">
{this._renderStartOnboarding()}
diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx
index 4aea1bbbb..91dbeb27a 100644
--- a/packages/website/ts/components/relayer_index/relayer_index.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_index.tsx
@@ -56,7 +56,11 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde
</div>
);
} else {
- const numberOfColumns = this._numberOfColumnsForScreenWidth(this.props.screenWidth);
+ const numberOfRelayers = this.state.relayerInfos.length;
+ const numberOfColumns = Math.min(
+ numberOfRelayers,
+ this._numberOfColumnsForScreenWidth(this.props.screenWidth),
+ );
return (
<GridList
cellHeight={CELL_HEIGHT}
diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx
index 969ef32ff..5965ad9bd 100644
--- a/packages/website/ts/components/token_balances.tsx
+++ b/packages/website/ts/components/token_balances.tsx
@@ -165,7 +165,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
key="errorOkBtn"
label="Ok"
primary={true}
- onTouchTap={this._onErrorDialogToggle.bind(this, false)}
+ onClick={this._onErrorDialogToggle.bind(this, false)}
/>,
];
const isTestNetwork = utils.isTestNetwork(this.props.networkId);
@@ -337,14 +337,8 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
const isMintable =
(_.includes(configs.SYMBOLS_OF_MINTABLE_KOVAN_TOKENS, token.symbol) &&
this.props.networkId === sharedConstants.NETWORK_ID_BY_NAME[Networks.Kovan]) ||
- (_.includes(configs.SYMBOLS_OF_MINTABLE_RINKEBY_ROPSTEN_TOKENS, token.symbol) &&
- _.includes(
- [
- sharedConstants.NETWORK_ID_BY_NAME[Networks.Rinkeby],
- sharedConstants.NETWORK_ID_BY_NAME[Networks.Ropsten],
- ],
- this.props.networkId,
- ));
+ (_.includes(configs.SYMBOLS_OF_MINTABLE_ROPSTEN_TOKENS, token.symbol) &&
+ this.props.networkId === sharedConstants.NETWORK_ID_BY_NAME[Networks.Ropsten]);
return (
<TableRow key={token.address} style={{ height: TOKEN_TABLE_ROW_HEIGHT }}>
<TableRowColumn colSpan={tokenColSpan}>
@@ -392,14 +386,6 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
onClickAsyncFn={this._onMintTestTokensAsync.bind(this, token)}
/>
)}
- {token.symbol === ZRX_TOKEN_SYMBOL && (
- <LifeCycleRaisedButton
- labelReady="Request"
- labelLoading="Sending..."
- labelComplete="Sent!"
- onClickAsyncFn={this._faucetRequestAsync.bind(this, false)}
- />
- )}
</TableRowColumn>
)}
{this.props.screenWidth !== ScreenWidths.Sm && (
diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx
index 8f1137b44..c2d753e31 100644
--- a/packages/website/ts/components/top_bar/top_bar.tsx
+++ b/packages/website/ts/components/top_bar/top_bar.tsx
@@ -132,7 +132,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
const fullWidthClasses = isExpandedDisplayType ? 'pr4' : '';
const logoUrl = isNightVersion ? '/images/protocol_logo_white.png' : '/images/protocol_logo_black.png';
const menuClasses = `col col-${
- isExpandedDisplayType ? '4' : '5'
+ isExpandedDisplayType ? '4' : '6'
} ${fullWidthClasses} lg-pr0 md-pr2 sm-hide xs-hide`;
const menuIconStyle = {
fontSize: 25,
@@ -185,6 +185,13 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
isExternal={false}
/>
<TopBarMenuItem
+ title={this.props.translate.get(Key.Careers, Deco.Cap)}
+ path={`${WebsitePaths.Careers}`}
+ style={styles.menuItem}
+ isNightVersion={isNightVersion}
+ isExternal={false}
+ />
+ <TopBarMenuItem
title={this.props.translate.get(Key.TradeCallToAction, Deco.Cap)}
path={`${WebsitePaths.Portal}`}
isPrimary={true}
@@ -289,11 +296,14 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
<Link to={`${WebsitePaths.About}`} className="text-decoration-none">
<MenuItem className="py2">{this.props.translate.get(Key.About, Deco.Cap)}</MenuItem>
</Link>
+ <Link to={`${WebsitePaths.Careers}`} className="text-decoration-none">
+ <MenuItem className="py2">{this.props.translate.get(Key.Careers, Deco.Cap)}</MenuItem>
+ </Link>
<a className="text-decoration-none" target="_blank" href={constants.URL_BLOG}>
<MenuItem className="py2">{this.props.translate.get(Key.Blog, Deco.Cap)}</MenuItem>
</a>
<Link to={`${WebsitePaths.FAQ}`} className="text-decoration-none">
- <MenuItem className="py2" onTouchTap={this._onMenuButtonClick.bind(this)}>
+ <MenuItem className="py2" onClick={this._onMenuButtonClick.bind(this)}>
{this.props.translate.get(Key.Faq, Deco.Cap)}
</MenuItem>
</Link>
diff --git a/packages/website/ts/components/ui/button.tsx b/packages/website/ts/components/ui/button.tsx
index 2952c8859..75ba7bcff 100644
--- a/packages/website/ts/components/ui/button.tsx
+++ b/packages/website/ts/components/ui/button.tsx
@@ -96,4 +96,5 @@ export const CallToAction: React.StatelessComponent<CallToActionProps> = ({
CallToAction.defaultProps = {
type: 'dark',
fontSize: '14px',
+ padding: '0.9em 1.6em',
};
diff --git a/packages/website/ts/components/ui/lifecycle_raised_button.tsx b/packages/website/ts/components/ui/lifecycle_raised_button.tsx
index 380fbc77d..0bb99b9d8 100644
--- a/packages/website/ts/components/ui/lifecycle_raised_button.tsx
+++ b/packages/website/ts/components/ui/lifecycle_raised_button.tsx
@@ -71,7 +71,7 @@ export class LifeCycleRaisedButton extends React.Component<LifeCycleRaisedButton
style={{ width: '100%' }}
backgroundColor={this.props.backgroundColor}
labelColor={this.props.labelColor}
- onTouchTap={this.onClickAsync.bind(this)}
+ onClick={this.onClickAsync.bind(this)}
disabled={this.props.isDisabled || this.state.buttonState !== ButtonState.READY}
/>
);
diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx
index 734483564..cd8f290e3 100644
--- a/packages/website/ts/components/ui/text.tsx
+++ b/packages/website/ts/components/ui/text.tsx
@@ -20,6 +20,7 @@ export interface TextProps {
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
hoverColor?: string;
noWrap?: boolean;
+ display?: string;
}
const PlainText: React.StatelessComponent<TextProps> = ({ children, className, onClick, Tag }) => (
@@ -41,6 +42,7 @@ export const Text = styled(PlainText)`
${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)}` : '')};
}
diff --git a/packages/website/ts/components/ui/typed_text.tsx b/packages/website/ts/components/ui/typed_text.tsx
new file mode 100644
index 000000000..6d38580b9
--- /dev/null
+++ b/packages/website/ts/components/ui/typed_text.tsx
@@ -0,0 +1,75 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+import Typist from 'react-typist';
+
+import { Text, TextProps } from 'ts/components/ui/text';
+
+import 'react-typist/dist/Typist.css';
+
+export interface TypedTextProps extends TextProps {
+ textList: string[];
+ shouldRepeat?: boolean;
+ wordDelayMs?: number;
+ avgKeystrokeDelayMs?: number;
+ stdKeystrokeDelay?: number;
+}
+
+export interface TypedTextState {
+ cycleCount: number;
+}
+
+export class TypedText extends React.Component<TypedTextProps, TypedTextState> {
+ public static defaultProps = {
+ shouldRepeat: false,
+ avgKeystrokeDelayMs: 90,
+ wordDelayMs: 1000,
+ };
+ public state = {
+ cycleCount: 0,
+ };
+ public render(): React.ReactNode {
+ const {
+ textList,
+ shouldRepeat,
+ wordDelayMs,
+ avgKeystrokeDelayMs,
+ stdKeystrokeDelay,
+ // tslint:disable-next-line
+ ...textProps
+ } = this.props;
+ const { cycleCount } = this.state;
+ if (_.isEmpty(textList)) {
+ return null;
+ }
+ const typistChildren: React.ReactNode[] = [];
+ _.forEach(textList, text => {
+ typistChildren.push(
+ <Text key={`text-${text}-${cycleCount}`} {...textProps}>
+ {text}
+ </Text>,
+ );
+ if (wordDelayMs) {
+ typistChildren.push(<Typist.Delay key={`delay-${text}-${cycleCount}`} ms={wordDelayMs} />);
+ }
+ typistChildren.push(<Typist.Backspace key={`backspace-${text}-${cycleCount}`} count={text.length} />);
+ });
+ return (
+ <Typist
+ avgTypingDelay={avgKeystrokeDelayMs}
+ stdTypingDelay={stdKeystrokeDelay}
+ className="inline"
+ key={`typist-key-${cycleCount}`}
+ onTypingDone={this._onTypingDone.bind(this)}
+ >
+ {typistChildren}
+ </Typist>
+ );
+ }
+ private _onTypingDone(): void {
+ if (this.props.shouldRepeat) {
+ this.setState({
+ cycleCount: this.state.cycleCount + 1,
+ });
+ }
+ }
+}
diff --git a/packages/website/ts/components/wallet/body_overlay.tsx b/packages/website/ts/components/wallet/body_overlay.tsx
index 26359d0d2..3795f0eaa 100644
--- a/packages/website/ts/components/wallet/body_overlay.tsx
+++ b/packages/website/ts/components/wallet/body_overlay.tsx
@@ -13,7 +13,7 @@ import { AccountState, ProviderType } from 'ts/types';
import { utils } from 'ts/utils/utils';
const METAMASK_IMG_SRC = '/images/metamask_icon.png';
-const TOSHI_IMG_SRC = '/images/toshi_logo.jpg';
+const COINBASE_WALLET_IMG_SRC = '/images/coinbase_wallet_logo.png';
export interface BodyOverlayProps {
dispatcher: Dispatcher;
@@ -116,8 +116,8 @@ const UseDifferentWallet = (props: UseDifferentWallet) => {
const GetWalletCallToAction = () => {
const [downloadLink, isOnMobile] = utils.getBestWalletDownloadLinkAndIsMobile();
- const imageUrl = isOnMobile ? TOSHI_IMG_SRC : METAMASK_IMG_SRC;
- const text = isOnMobile ? 'Get Toshi Wallet' : 'Get MetaMask Wallet';
+ const imageUrl = isOnMobile ? COINBASE_WALLET_IMG_SRC : METAMASK_IMG_SRC;
+ const text = isOnMobile ? 'Get Coinbase Wallet' : 'Get MetaMask Wallet';
return (
<a href={downloadLink} target="_blank" style={{ textDecoration: 'none' }}>
<Island
diff --git a/packages/website/ts/containers/connect_documentation.ts b/packages/website/ts/containers/connect_documentation.ts
index 90137243c..a728abe2c 100644
--- a/packages/website/ts/containers/connect_documentation.ts
+++ b/packages/website/ts/containers/connect_documentation.ts
@@ -1,4 +1,4 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
diff --git a/packages/website/ts/containers/contract_wrappers_documentation.ts b/packages/website/ts/containers/contract_wrappers_documentation.ts
index fd8599192..1e1735846 100644
--- a/packages/website/ts/containers/contract_wrappers_documentation.ts
+++ b/packages/website/ts/containers/contract_wrappers_documentation.ts
@@ -1,4 +1,4 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { DocPackages } from 'ts/types';
-import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
diff --git a/packages/website/ts/containers/ethereum_types_documentation.ts b/packages/website/ts/containers/ethereum_types_documentation.ts
index e0bf9a83e..2b6d6e64d 100644
--- a/packages/website/ts/containers/ethereum_types_documentation.ts
+++ b/packages/website/ts/containers/ethereum_types_documentation.ts
@@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { DocPackages } from 'ts/types';
-import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
diff --git a/packages/website/ts/containers/generate_order_form.ts b/packages/website/ts/containers/generate_order_form.ts
index 92296dbab..bc9d6f524 100644
--- a/packages/website/ts/containers/generate_order_form.ts
+++ b/packages/website/ts/containers/generate_order_form.ts
@@ -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,
diff --git a/packages/website/ts/containers/order_utils_documentation.ts b/packages/website/ts/containers/order_utils_documentation.ts
index 47ac35268..b54c30a1e 100644
--- a/packages/website/ts/containers/order_utils_documentation.ts
+++ b/packages/website/ts/containers/order_utils_documentation.ts
@@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { DocPackages } from 'ts/types';
-import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
diff --git a/packages/website/ts/containers/order_watcher_documentation.ts b/packages/website/ts/containers/order_watcher_documentation.ts
index 2fa2a9d61..59a018847 100644
--- a/packages/website/ts/containers/order_watcher_documentation.ts
+++ b/packages/website/ts/containers/order_watcher_documentation.ts
@@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { DocPackages } from 'ts/types';
-import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
diff --git a/packages/website/ts/containers/portal.ts b/packages/website/ts/containers/portal.ts
index 6747cdf4e..4d7ff2f55 100644
--- a/packages/website/ts/containers/portal.ts
+++ b/packages/website/ts/containers/portal.ts
@@ -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;
diff --git a/packages/website/ts/containers/smart_contracts_documentation.ts b/packages/website/ts/containers/smart_contracts_documentation.ts
index 4f4479c83..8d69afe71 100644
--- a/packages/website/ts/containers/smart_contracts_documentation.ts
+++ b/packages/website/ts/containers/smart_contracts_documentation.ts
@@ -11,29 +11,28 @@ import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
const IntroMarkdownV1 = require('md/docs/smart_contracts/1.0.0/introduction');
+const IntroMarkdownV2 = require('md/docs/smart_contracts/2.0.0/introduction');
/* tslint:enable:no-var-requires */
const docsInfoConfig: DocsInfoConfig = {
id: DocPackages.SmartContracts,
packageName: 'contracts',
- type: SupportedDocJson.Doxity,
+ type: SupportedDocJson.SolDoc,
displayName: '0x Smart Contracts',
packageUrl: 'https://github.com/0xProject/contracts',
markdownMenu: {
introduction: [Sections.Introduction],
- contracts: [Sections.Exchange, Sections.TokenRegistry, Sections.ZRXToken, Sections.TokenTransferProxy],
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
[Sections.Introduction]: IntroMarkdownV1,
},
+ '2.0.0': {
+ [Sections.Introduction]: IntroMarkdownV2,
+ },
},
markdownSections: {
Introduction: Sections.Introduction,
- Exchange: Sections.Exchange,
- TokenTransferProxy: Sections.TokenTransferProxy,
- TokenRegistry: Sections.TokenRegistry,
- ZRXToken: Sections.ZRXToken,
},
contractsByVersionByNetworkId: {
'1.0.0': {
diff --git a/packages/website/ts/containers/sol_compiler_documentation.ts b/packages/website/ts/containers/sol_compiler_documentation.ts
index 7cde68e5c..20f26ed1d 100644
--- a/packages/website/ts/containers/sol_compiler_documentation.ts
+++ b/packages/website/ts/containers/sol_compiler_documentation.ts
@@ -1,4 +1,4 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
diff --git a/packages/website/ts/containers/sol_cov_documentation.ts b/packages/website/ts/containers/sol_cov_documentation.ts
index a457cbc1e..27efd641e 100644
--- a/packages/website/ts/containers/sol_cov_documentation.ts
+++ b/packages/website/ts/containers/sol_cov_documentation.ts
@@ -1,4 +1,4 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
diff --git a/packages/website/ts/containers/subproviders_documentation.ts b/packages/website/ts/containers/subproviders_documentation.ts
index 43f06b4ed..28b2e9508 100644
--- a/packages/website/ts/containers/subproviders_documentation.ts
+++ b/packages/website/ts/containers/subproviders_documentation.ts
@@ -1,4 +1,4 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { DocPackages } from 'ts/types';
-import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
diff --git a/packages/website/ts/containers/web3_wrapper_documentation.ts b/packages/website/ts/containers/web3_wrapper_documentation.ts
index 13924fde8..dc9d23304 100644
--- a/packages/website/ts/containers/web3_wrapper_documentation.ts
+++ b/packages/website/ts/containers/web3_wrapper_documentation.ts
@@ -1,4 +1,4 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -6,7 +6,6 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { DocPackages } from 'ts/types';
-import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts
index 367d3e064..2a3afd86c 100644
--- a/packages/website/ts/containers/zero_ex_js_documentation.ts
+++ b/packages/website/ts/containers/zero_ex_js_documentation.ts
@@ -1,4 +1,4 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -6,18 +6,21 @@ import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentatio
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { DocPackages } from 'ts/types';
-import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
-const IntroMarkdownV1 = require('md/docs/0xjs/1.0.0/introduction');
-const InstallationMarkdownV1 = require('md/docs/0xjs/1.0.0/installation');
-const AsyncMarkdownV1 = require('md/docs/0xjs/1.0.0/async');
-const ErrorsMarkdownV1 = require('md/docs/0xjs/1.0.0/errors');
-const versioningMarkdownV1 = require('md/docs/0xjs/1.0.0/versioning');
+const IntroMarkdownV0 = require('md/docs/0xjs/0.0.1/introduction');
+const InstallationMarkdownV0 = require('md/docs/0xjs/0.0.1/installation');
+const AsyncMarkdownV0 = require('md/docs/0xjs/0.0.1/async');
+const ErrorsMarkdownV0 = require('md/docs/0xjs/0.0.1/errors');
+const versioningMarkdownV0 = require('md/docs/0xjs/0.0.1/versioning');
+
+const IntroMarkdownV1 = require('md/docs/0xjs/1.0.1/introduction');
+const InstallationMarkdownV1 = require('md/docs/0xjs/1.0.1/installation');
+const AsyncMarkdownV1 = require('md/docs/0xjs/1.0.1/async');
+const ErrorsMarkdownV1 = ErrorsMarkdownV0;
+const versioningMarkdownV1 = require('md/docs/0xjs/1.0.1/versioning');
-const IntroMarkdownV2 = require('md/docs/0xjs/2.0.0/introduction');
-const versioningMarkdownV2 = require('md/docs/0xjs/2.0.0/versioning');
/* tslint:enable:no-var-requires */
const markdownSections = {
@@ -42,17 +45,16 @@ const docsInfoConfig: DocsInfoConfig = {
},
sectionNameToMarkdownByVersion: {
'0.0.1': {
+ [markdownSections.introduction]: IntroMarkdownV0,
+ [markdownSections.installation]: InstallationMarkdownV0,
+ [markdownSections.versioning]: versioningMarkdownV0,
+ [markdownSections.async]: AsyncMarkdownV0,
+ [markdownSections.errors]: ErrorsMarkdownV0,
+ },
+ '1.0.1': {
[markdownSections.introduction]: IntroMarkdownV1,
[markdownSections.installation]: InstallationMarkdownV1,
- [markdownSections.async]: AsyncMarkdownV1,
- [markdownSections.errors]: ErrorsMarkdownV1,
[markdownSections.versioning]: versioningMarkdownV1,
- },
- '1.0.0-rc.1': {
- [markdownSections.introduction]: IntroMarkdownV2,
- [markdownSections.versioning]: versioningMarkdownV2,
- // These are the same as for V1
- [markdownSections.installation]: InstallationMarkdownV1,
[markdownSections.async]: AsyncMarkdownV1,
[markdownSections.errors]: ErrorsMarkdownV1,
},
diff --git a/packages/website/ts/globals.d.ts b/packages/website/ts/globals.d.ts
index 719c2708a..eb8892aea 100644
--- a/packages/website/ts/globals.d.ts
+++ b/packages/website/ts/globals.d.ts
@@ -10,6 +10,7 @@ declare module '*.json' {
export default json;
/* tslint:enable */
}
+declare module 'web3-provider-engine/subproviders/filters';
// This will be defined by default in TS 2.4
// Source: https://github.com/Microsoft/TypeScript/issues/12364
diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx
index e81b1bf07..c476f2358 100644
--- a/packages/website/ts/index.tsx
+++ b/packages/website/ts/index.tsx
@@ -3,7 +3,6 @@ import * as React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
-import * as injectTapEventPlugin from 'react-tap-event-plugin';
import { MetaTags } from 'ts/components/meta_tags';
import { About } from 'ts/containers/about';
import { DocsHome } from 'ts/containers/docs_home';
@@ -18,8 +17,6 @@ import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage';
import { store } from 'ts/redux/store';
import { WebsiteLegacyPaths, WebsitePaths } from 'ts/types';
import { muiTheme } from 'ts/utils/mui_theme';
-// Polyfills
-injectTapEventPlugin();
// Check if we've introduced an update that requires us to clear the tradeHistory local storage entries
tradeHistoryStorage.clearIfRequired();
diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx
index 519e4be5e..e097578bc 100644
--- a/packages/website/ts/pages/about/about.tsx
+++ b/packages/website/ts/pages/about/about.tsx
@@ -194,7 +194,7 @@ const teamRow6: ProfileInfo[] = [
const teamRow7: ProfileInfo[] = [
{
name: 'Clay Robbins',
- title: 'Business Development Lead',
+ title: 'Ecosystem Development Lead',
description: `Growth & Business Development. Previously product and partnerships at Square. Economics at Dartmouth College.`,
image: 'images/team/clay.png',
linkedIn: 'https://www.linkedin.com/in/robbinsclay/',
@@ -206,9 +206,34 @@ const teamRow7: ProfileInfo[] = [
image: 'images/team/matt.jpg',
linkedIn: 'https://www.linkedin.com/in/mattytay/',
},
+ {
+ name: 'Eugene Aumson',
+ title: 'Engineer',
+ description: `Developer Experience. Previously senior software engineer in foreign exchange applications at Bloomberg LP.`,
+ image: 'images/team/gene.jpg',
+ linkedIn: 'https://www.linkedin.com/in/aumson/',
+ github: 'https://github.com/feuGeneA',
+ },
+];
+
+const teamRow8: ProfileInfo[] = [
+ {
+ name: 'Weijie Wu',
+ title: 'Research Fellow',
+ description: `Researching decentralized governance. Previously Researcher at Huawei and Assistant Professor at Shanghai Jiao Tong University. PhD in Computer Science at The Chinese University of Hong Kong.`,
+ image: 'images/team/weijie.png',
+ linkedIn: 'https://www.linkedin.com/in/weijiewu/',
+ },
+ {
+ name: 'Rahul Singireddy',
+ title: 'Relayer Success Manager',
+ description: `Previously community at Zeppelin, growth at Dharma, and cryptocurrency contributor at Forbes. Symbolic Systems at Stanford.`,
+ image: 'images/team/rahul.png',
+ linkedIn: 'https://www.linkedin.com/in/rahul-singireddy-3037908a/',
+ },
];
-const advisors: ProfileInfo[] = [
+const advisors1: ProfileInfo[] = [
{
name: 'Fred Ehrsam',
description: 'Co-founder of Coinbase. Previously FX trader at Goldman Sachs.',
@@ -232,6 +257,9 @@ const advisors: ProfileInfo[] = [
github: 'https://github.com/joeykrug',
angellist: 'https://angel.co/joeykrug',
},
+];
+
+const advisors2: ProfileInfo[] = [
{
name: 'Linda Xie',
description: 'Co-founder of Scalar Capital. Previously PM at Coinbase.',
@@ -240,6 +268,14 @@ const advisors: ProfileInfo[] = [
medium: 'https://medium.com/@linda.xie',
twitter: 'https://twitter.com/ljxie',
},
+ {
+ name: 'David Sacks',
+ description: 'General Partner at Craft Ventures. Original COO of PayPal. Founder of Yammer.',
+ image: '/images/advisors/david.png',
+ linkedIn: 'https://www.linkedin.com/in/davidoliversacks/',
+ medium: 'https://medium.com/@davidsacks',
+ twitter: 'https://twitter.com/DavidSacks',
+ },
];
export interface AboutProps {
@@ -304,6 +340,7 @@ export class About extends React.Component<AboutProps, AboutState> {
<div className="clearfix">{this._renderProfiles(teamRow5)}</div>
<div className="clearfix">{this._renderProfiles(teamRow6)}</div>
<div className="clearfix">{this._renderProfiles(teamRow7)}</div>
+ <div className="clearfix">{this._renderProfiles(teamRow8)}</div>
</div>
<div className="pt3 pb2">
<div
@@ -316,7 +353,8 @@ export class About extends React.Component<AboutProps, AboutState> {
>
Advisors:
</div>
- <div className="clearfix">{this._renderProfiles(advisors)}</div>
+ <div className="clearfix">{this._renderProfiles(advisors1)}</div>
+ <div className="clearfix">{this._renderProfiles(advisors2)}</div>
</div>
<div className="mx-auto py4 sm-px3" style={{ maxWidth: 308 }}>
<div className="pb2" style={styles.weAreHiring}>
diff --git a/packages/website/ts/pages/documentation/doc_page.tsx b/packages/website/ts/pages/documentation/doc_page.tsx
index 9c144b93f..6f029b6a2 100644
--- a/packages/website/ts/pages/documentation/doc_page.tsx
+++ b/packages/website/ts/pages/documentation/doc_page.tsx
@@ -1,4 +1,11 @@
-import { DocAgnosticFormat, DocsInfo, Documentation } from '@0xproject/react-docs';
+import {
+ DocAgnosticFormat,
+ DocsInfo,
+ Documentation,
+ GeneratedDocJson,
+ SupportedDocJson,
+ TypeDocUtils,
+} from '@0xproject/react-docs';
import findVersions = require('find-versions');
import * as _ from 'lodash';
import * as React from 'react';
@@ -128,7 +135,22 @@ export class DocPage extends React.Component<DocPageProps, DocPageState> {
const versionFilePathToFetch = versionToFilePath[versionToFetch];
const versionDocObj = await docUtils.getJSONDocFileAsync(versionFilePathToFetch, docBucketRoot);
- const docAgnosticFormat = this.props.docsInfo.convertToDocAgnosticFormat(versionDocObj);
+ let docAgnosticFormat;
+ if (this.props.docsInfo.type === SupportedDocJson.TypeDoc) {
+ docAgnosticFormat = new TypeDocUtils(
+ versionDocObj as GeneratedDocJson,
+ this.props.docsInfo,
+ ).convertToDocAgnosticFormat();
+ } else if (this.props.docsInfo.type === SupportedDocJson.SolDoc) {
+ // documenting solidity.
+ docAgnosticFormat = versionDocObj as DocAgnosticFormat;
+ // HACK: need to modify docsInfo like convertToDocAgnosticFormat() would do
+ this.props.docsInfo.menu.Contracts = [];
+ _.each(docAgnosticFormat, (docObj, contractName) => {
+ this.props.docsInfo.sections[contractName] = contractName;
+ this.props.docsInfo.menu.Contracts.push(contractName);
+ });
+ }
if (!this._isUnmounted) {
this.setState({
diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx
index 78f5fc3c1..388e83d51 100644
--- a/packages/website/ts/pages/landing/landing.tsx
+++ b/packages/website/ts/pages/landing/landing.tsx
@@ -8,6 +8,9 @@ import { SubscribeForm } from 'ts/components/forms/subscribe_form';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { CallToAction } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
+import { Image } from 'ts/components/ui/image';
+import { Text } from 'ts/components/ui/text';
+import { TypedText } from 'ts/components/ui/typed_text';
import { Dispatcher } from 'ts/redux/dispatcher';
import { Deco, Key, Language, ScreenWidths, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
@@ -19,11 +22,7 @@ interface BoxContent {
description: string;
imageUrl: string;
classNames: string;
-}
-interface AssetType {
- title: string;
- imageUrl: string;
- style?: React.CSSProperties;
+ maxWidth: number;
}
interface UseCase {
imageUrl: string;
@@ -31,7 +30,6 @@ interface UseCase {
description: string;
classNames: string;
style?: React.CSSProperties;
- projectIconUrls: string[];
}
interface Project {
logoFileName: string;
@@ -39,74 +37,24 @@ interface Project {
}
const THROTTLE_TIMEOUT = 100;
-const WHATS_NEW_TITLE = '18 ideas for 0x relayers in 2018';
-const WHATS_NEW_URL = 'https://blog.0xproject.com/18-ideas-for-0x-relayers-in-2018-80a1498b955f';
-
-const relayersAndDappProjects: Project[] = [
- {
- logoFileName: 'ercdex.png',
- projectUrl: constants.PROJECT_URL_ERC_DEX,
- },
- {
- logoFileName: 'radar_relay.png',
- projectUrl: constants.PROJECT_URL_RADAR_RELAY,
- },
- {
- logoFileName: 'paradex.png',
- projectUrl: constants.PROJECT_URL_PARADEX,
- },
- {
- logoFileName: 'the_ocean.png',
- projectUrl: constants.PROJECT_URL_0CEAN,
- },
- {
- logoFileName: 'dydx.png',
- projectUrl: constants.PROJECT_URL_DYDX,
- },
- {
- logoFileName: 'ethfinex.png',
- projectUrl: constants.PROJECT_URL_ETHFINEX,
- },
- {
- logoFileName: 'melonport.png',
- projectUrl: constants.PROJECT_URL_MELONPORT,
- },
- {
- logoFileName: 'maker.png',
- projectUrl: constants.PROJECT_URL_MAKER,
- },
- {
- logoFileName: 'dharma.png',
- projectUrl: constants.PROJECT_URL_DHARMA,
- },
- {
- logoFileName: 'lendroid.png',
- projectUrl: constants.PROJECT_URL_LENDROID,
- },
- {
- logoFileName: 'district0x.png',
- projectUrl: constants.PROJECT_URL_DISTRICT_0X,
- },
- {
- logoFileName: 'aragon.png',
- projectUrl: constants.PROJECT_URL_ARAGON,
- },
- {
- logoFileName: 'blocknet.png',
- projectUrl: constants.PROJECT_URL_BLOCKNET,
- },
- {
- logoFileName: 'imtoken.png',
- projectUrl: constants.PROJECT_URL_IMTOKEN,
- },
- {
- logoFileName: 'augur.png',
- projectUrl: constants.PROJECT_URL_AUGUR,
- },
- {
- logoFileName: 'anx.png',
- projectUrl: constants.PROJECT_URL_OPEN_ANX,
- },
+const WHATS_NEW_TITLE = '0x Protocol v2 is Live!';
+const WHATS_NEW_URL = 'https://blog.0xproject.com/0x-protocol-v2-0-is-live-183aac180149';
+const TITLE_STYLE: React.CSSProperties = {
+ fontFamily: 'Roboto Mono',
+ color: colors.grey,
+ fontWeight: 300,
+ letterSpacing: 3,
+};
+const ROTATING_LIST = [
+ 'tokens',
+ 'game items',
+ 'digital art',
+ 'futures',
+ 'stocks',
+ 'derivatives',
+ 'loans',
+ 'cats',
+ 'everything',
];
const relayerProjects: Project[] = [
@@ -199,21 +147,13 @@ export class Landing extends React.Component<LandingProps, LandingState> {
/>
{this._renderHero()}
{this._renderProjects(
- relayersAndDappProjects,
- this.props.translate.get(Key.ProjectsHeader, Deco.Upper),
- colors.projectsGrey,
- false,
- )}
- {this._renderTokenizationSection()}
- {this._renderProtocolSection()}
- {this._renderProjects(
relayerProjects,
this.props.translate.get(Key.RelayersHeader, Deco.Upper),
- colors.heroGrey,
+ colors.projectsGrey,
true,
)}
{this._renderInfoBoxes()}
- {this._renderBuildingBlocksSection()}
+ {this._renderTokenizationSection()}
{this._renderUseCases()}
{this._renderCallToAction()}
<Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
@@ -222,15 +162,18 @@ export class Landing extends React.Component<LandingProps, LandingState> {
}
private _renderHero(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
- const left = 'col lg-col-7 md-col-7 col-12 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center';
+ const left = 'col lg-col-6 md-col-6 col-12 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center';
+ const flexClassName = isSmallScreen
+ ? 'flex items-center flex-column justify-center'
+ : 'flex items-center justify-center';
return (
<div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}>
<div className="mx-auto max-width-4 clearfix">
{this._renderWhatsNew()}
- <div className="lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-mt4 md-mt4 sm-mt2 sm-mb4 clearfix">
- <div className="col lg-col-5 md-col-5 col-12 sm-center">
- <img src="/images/landing/hero_chip_image.png" height={isSmallScreen ? 300 : 395} />
- </div>
+ <div className={`${flexClassName} lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-mt4 md-mt4 sm-mt2 sm-mb4`}>
+ <Container marginTop="30px" marginBottom="30px" marginLeft="15px" marginRight="15px">
+ <Image src="/images/landing/0x_homepage.svg" maxWidth="100%" height="auto" />
+ </Container>
<div className={left} style={{ color: colors.white, height: 390, lineHeight: '390px' }}>
<div
className="inline-block lg-align-middle md-align-middle sm-align-top"
@@ -239,37 +182,46 @@ export class Landing extends React.Component<LandingProps, LandingState> {
lineHeight: '36px',
}}
>
- <div
+ <Text
className="sm-pb2"
- style={{
- fontFamily: 'Roboto Mono',
- fontSize: isSmallScreen ? 26 : 34,
- }}
+ fontFamily="Roboto"
+ display="inline-block"
+ fontColor={colors.grey300}
+ fontWeight={500}
+ lineHeight="1.3em"
+ fontSize={isSmallScreen ? '28px' : '36px'}
>
{this.props.translate.get(Key.TopHeader, Deco.Cap)}
- </div>
- <div
- className="pt2 h5 sm-mx-auto"
- style={{
- maxWidth: 446,
- fontFamily: 'Roboto Mono',
- lineHeight: 1.7,
- fontWeight: 300,
- }}
+ {this.props.translate.getLanguage() === Language.English && (
+ <React.Fragment>
+ {' '}
+ for{' '}
+ <TypedText
+ fontFamily="Roboto"
+ display="inline-block"
+ fontColor={colors.white}
+ fontWeight={700}
+ lineHeight="1.3em"
+ fontSize={isSmallScreen ? '28px' : '36px'}
+ textList={ROTATING_LIST}
+ shouldRepeat={true}
+ />
+ </React.Fragment>
+ )}
+ </Text>
+ <Container
+ className={`pt3 flex clearfix sm-mx-auto ${isSmallScreen ? 'justify-center' : ''}`}
>
- {this.props.translate.get(Key.TopTagline)}
- </div>
- <Container className="pt3 clearfix sm-mx-auto" maxWidth="390px">
- <div className="lg-pr2 md-pr2 lg-col lg-col-6 sm-center sm-col sm-col-12 mb2">
+ <Container paddingRight="20px">
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
- <CallToAction width="175px" type="light">
+ <CallToAction type="light">
{this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
</CallToAction>
</Link>
- </div>
- <div className="lg-col lg-col-6 sm-center sm-col sm-col-12">
+ </Container>
+ <div>
<Link to={WebsitePaths.Portal} className="text-decoration-none">
- <CallToAction width="175px">
+ <CallToAction>
{this.props.translate.get(Key.TradeCallToAction, Deco.Cap)}
</CallToAction>
</Link>
@@ -287,19 +239,24 @@ export class Landing extends React.Component<LandingProps, LandingState> {
return (
<div className="sm-center sm-px1">
<a href={WHATS_NEW_URL} target="_blank" className="inline-block text-decoration-none">
- <div className="flex sm-pl0 md-pl2 lg-pl0" style={{ fontFamily: 'Roboto Mono', fontWeight: 600 }}>
- <div
- className="mr1 px1"
- style={{
- backgroundColor: colors.white,
- borderRadius: 3,
- color: colors.heroGrey,
- height: 23,
- }}
+ <div className="flex items-center sm-pl0 md-pl2 lg-pl0">
+ <Container
+ paddingTop="3px"
+ paddingLeft="8px"
+ paddingBottom="3px"
+ paddingRight="8px"
+ backgroundColor={colors.white}
+ borderRadius={6}
>
- New
- </div>
- <div style={{ color: colors.darkGrey }}>{WHATS_NEW_TITLE}</div>
+ <Text fontSize="14px" fontWeight={500} fontColor={colors.heroGrey}>
+ New
+ </Text>
+ </Container>
+ <Container marginLeft="12px">
+ <Text fontSize="16px" fontWeight={500} fontColor={colors.grey300}>
+ {WHATS_NEW_TITLE}
+ </Text>
+ </Container>
</div>
</a>
</div>
@@ -344,16 +301,10 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
});
- const titleStyle: React.CSSProperties = {
- fontFamily: 'Roboto Mono',
- color: colors.grey,
- fontWeight: 300,
- letterSpacing: 3,
- };
return (
<div className={`clearfix py4 ${isTitleCenter && 'center'}`} style={{ backgroundColor }}>
<div className="mx-auto max-width-4 clearfix sm-px3">
- <div className="h4 pb3 lg-pl0 md-pl3 sm-pl2" style={titleStyle}>
+ <div className="h4 pb3 lg-pl0 md-pl3 sm-pl2" style={TITLE_STYLE}>
{title}
</div>
<div className="clearfix">{projectList}</div>
@@ -368,7 +319,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
>
{this.props.translate.get(Key.FullListPrompt)}{' '}
<Link
- to={`${WebsitePaths.Wiki}#List-of-Projects-Using-0x-Protocol`}
+ to={WebsitePaths.Portal}
className="text-decoration-none underline"
style={{ color: colors.landingLinkGrey }}
>
@@ -402,7 +353,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
>
{this.props.translate.get(Key.TokenizedSectionDescription, Deco.Cap)}
</div>
- <div className="flex pt1 sm-px3">{this._renderAssetTypes()}</div>
+ <div className="flex pt1 sm-px3">{this._renderMissionAndValuesButton()}</div>
</div>
</div>
{!isSmallScreen && this._renderTokenCloud()}
@@ -410,116 +361,6 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
}
- private _renderProtocolSection(): React.ReactNode {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
- return (
- <div className="clearfix pt4" style={{ backgroundColor: colors.heroGrey }}>
- <div className="mx-auto max-width-4 pt4 clearfix">
- <div className="col lg-col-6 md-col-6 col-12 sm-center">
- <img src="/images/landing/relayer_diagram.png" height={isSmallScreen ? 326 : 426} />
- </div>
- <div
- className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-mx-auto"
- style={{
- color: colors.beigeWhite,
- maxWidth: isSmallScreen ? 'none' : 445,
- height: 430,
- lineHeight: '430px',
- }}
- >
- <div
- className="inline-block lg-align-middle md-align-middle sm-align-top"
- style={{ lineHeight: '43px' }}
- >
- <div
- className="lg-h1 md-h1 sm-h2 pb1 sm-pt3 sm-center"
- style={{ fontFamily: 'Roboto Mono' }}
- >
- <div>{this.props.translate.get(Key.OffChainOrderRelay, Deco.Cap)}</div>
- <div> {this.props.translate.get(Key.OnChainSettlement, Deco.Cap)}</div>
- </div>
- <div
- className="pb2 pt2 h5 sm-center sm-px3 sm-mx-auto"
- style={{
- fontFamily: 'Roboto Mono',
- lineHeight: 1.7,
- fontWeight: 300,
- maxWidth: 445,
- }}
- >
- {this.props.translate.get(Key.OffChainOnChainDescription, Deco.Cap)}
- </div>
- </div>
- </div>
- </div>
- </div>
- );
- }
- private _renderBuildingBlocksSection(): React.ReactNode {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
- const descriptionStyle: React.CSSProperties = {
- fontFamily: 'Roboto Mono',
- lineHeight: isSmallScreen ? 1.5 : 2,
- fontWeight: 300,
- fontSize: 15,
- maxWidth: isSmallScreen ? 375 : 'none',
- };
- const callToActionStyle: React.CSSProperties = {
- fontFamily: 'Roboto Mono',
- fontSize: 15,
- fontWeight: 300,
- maxWidth: isSmallScreen ? 375 : 441,
- };
- return (
- <div className="clearfix lg-pt4 md-pt4" style={{ backgroundColor: colors.heroGrey }}>
- <div className="mx-auto max-width-4 lg-pt4 md-pt4 lg-mb4 md-mb4 sm-mb2 clearfix">
- {isSmallScreen && this._renderBlockChipImage()}
- <div
- className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-px3"
- style={{ color: colors.beigeWhite }}
- >
- <div
- className="pb1 lg-pt4 md-pt4 sm-pt3 lg-h1 md-h1 sm-h2 sm-px3 sm-center"
- style={{ fontFamily: 'Roboto Mono' }}
- >
- {this.props.translate.get(Key.BuildingBlockSectionHeader, Deco.Cap)}
- </div>
- <div className="pb3 pt2 sm-mx-auto sm-center" style={descriptionStyle}>
- {this.props.translate.get(Key.BuildingBlockSectionDescription, Deco.Cap)}
- </div>
- <div className="sm-mx-auto sm-center" style={callToActionStyle}>
- {this.props.translate.get(Key.DevToolsPrompt, Deco.Cap)}{' '}
- <Link
- to={WebsitePaths.ZeroExJs}
- className="text-decoration-none underline"
- style={{ color: colors.beigeWhite, fontFamily: 'Roboto Mono' }}
- >
- 0x.js
- </Link>{' '}
- {this.props.translate.get(Key.And)}{' '}
- <Link
- to={WebsitePaths.SmartContracts}
- className="text-decoration-none underline"
- style={{ color: colors.beigeWhite, fontFamily: 'Roboto Mono' }}
- >
- {this.props.translate.get(Key.SmartContract)}
- </Link>{' '}
- {this.props.translate.get(Key.Docs)}
- </div>
- </div>
- {!isSmallScreen && this._renderBlockChipImage()}
- </div>
- </div>
- );
- }
- private _renderBlockChipImage(): React.ReactNode {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
- return (
- <div className="col lg-col-6 md-col-6 col-12 sm-center">
- <img src="/images/landing/0x_chips.png" height={isSmallScreen ? 240 : 368} />
- </div>
- );
- }
private _renderTokenCloud(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return (
@@ -528,48 +369,16 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
}
- private _renderAssetTypes(): React.ReactNode {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
- const assetTypes: AssetType[] = [
- {
- title: this.props.translate.get(Key.Currency, Deco.Cap),
- imageUrl: '/images/landing/currency.png',
- },
- {
- title: this.props.translate.get(Key.TraditionalAssets, Deco.Cap),
- imageUrl: '/images/landing/stocks.png',
- style: {
- paddingLeft: isSmallScreen ? 41 : 56,
- paddingRight: isSmallScreen ? 41 : 56,
- },
- },
- {
- title: this.props.translate.get(Key.DigitalGoods, Deco.Cap),
- imageUrl: '/images/landing/digital_goods.png',
- },
- ];
- const assets = _.map(assetTypes, (assetType: AssetType) => {
- const style = _.isUndefined(assetType.style) ? {} : assetType.style;
- return (
- <div key={`asset-${assetType.title}`} className="center" style={{ opacity: 0.8, ...style }}>
- <div>
- <img src={assetType.imageUrl} height="80" />
- </div>
- <div
- style={{
- fontFamily: 'Roboto Mono',
- fontSize: 13.5,
- fontWeight: 400,
- color: colors.darkestGrey,
- lineHeight: 1.4,
- }}
- >
- {assetType.title}
- </div>
- </div>
- );
- });
- return assets;
+ private _renderMissionAndValuesButton(): React.ReactNode {
+ return (
+ <a
+ href={constants.URL_MISSION_AND_VALUES_BLOG_POST}
+ target="_blank"
+ className="inline-block text-decoration-none"
+ >
+ <CallToAction>{this.props.translate.get(Key.OurMissionAndValues, Deco.CapWords)}</CallToAction>
+ </a>
+ );
}
private _renderInfoBoxes(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
@@ -586,27 +395,34 @@ export class Landing extends React.Component<LandingProps, LandingState> {
description: this.props.translate.get(Key.BenefitOneDescription, Deco.Cap),
imageUrl: '/images/landing/distributed_network.png',
classNames: '',
+ maxWidth: 160,
},
{
title: this.props.translate.get(Key.BenefitTwoTitle, Deco.Cap),
description: this.props.translate.get(Key.BenefitTwoDescription, Deco.Cap),
imageUrl: '/images/landing/liquidity.png',
classNames: 'mx-auto',
+ maxWidth: 160,
},
{
title: this.props.translate.get(Key.BenefitThreeTitle, Deco.Cap),
description: this.props.translate.get(Key.BenefitThreeDescription, Deco.Cap),
- imageUrl: '/images/landing/open_source.png',
+ imageUrl: '/images/landing/exchange_everywhere.png',
classNames: 'right',
+ maxWidth: 130,
},
];
const boxes = _.map(boxContents, (boxContent: BoxContent) => {
return (
<div key={`box-${boxContent.title}`} className="col lg-col-4 md-col-4 col-12 sm-pb4">
<div className={`center sm-mx-auto ${!isSmallScreen && boxContent.classNames}`} style={boxStyle}>
- <div>
- <img src={boxContent.imageUrl} style={{ height: 210 }} />
- </div>
+ <Container className="flex items-center" height="210px">
+ <img
+ className="mx-auto"
+ src={boxContent.imageUrl}
+ style={{ height: 'auto', maxWidth: boxContent.maxWidth }}
+ />
+ </Container>
<div className="h3" style={{ color: 'black', fontFamily: 'Roboto Mono' }}>
{boxContent.title}
</div>
@@ -617,15 +433,9 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
});
- const titleStyle: React.CSSProperties = {
- fontFamily: 'Roboto Mono',
- color: colors.grey,
- fontWeight: 300,
- letterSpacing: 3,
- };
return (
<div className="clearfix" style={{ backgroundColor: colors.heroGrey }}>
- <div className="center pb3 pt4" style={titleStyle}>
+ <div className="center pb3 pt4" style={TITLE_STYLE}>
{this.props.translate.get(Key.BenefitsHeader, Deco.Upper)}
</div>
<div className="mx-auto pb4 sm-mt2 clearfix" style={{ maxWidth: '60em' }}>
@@ -634,53 +444,92 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
}
- private _renderUseCases(): React.ReactNode {
+ private _getUseCases(): UseCase[] {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
-
- const useCases: UseCase[] = [
- {
- imageUrl: '/images/landing/governance_icon.png',
- type: this.props.translate.get(Key.DecentralizedGovernance, Deco.Upper),
- description: this.props.translate.get(Key.DecentralizedGovernanceDescription, Deco.Cap),
- projectIconUrls: ['/images/landing/aragon.png'],
- classNames: 'lg-px2 md-px2',
- },
- {
- imageUrl: '/images/landing/prediction_market_icon.png',
- type: this.props.translate.get(Key.PredictionMarkets, Deco.Upper),
- description: this.props.translate.get(Key.PredictionMarketsDescription, Deco.Cap),
- projectIconUrls: ['/images/landing/augur.png'],
- classNames: 'lg-px2 md-px2',
- },
- {
- imageUrl: '/images/landing/stable_tokens_icon.png',
- type: this.props.translate.get(Key.StableTokens, Deco.Upper),
- description: this.props.translate.get(Key.StableTokensDescription, Deco.Cap),
- projectIconUrls: ['/images/landing/maker.png'],
- classNames: 'lg-px2 md-px2',
- },
- {
- imageUrl: '/images/landing/loans_icon.png',
- type: this.props.translate.get(Key.DecentralizedLoans, Deco.Upper),
- description: this.props.translate.get(Key.DecentralizedLoansDescription, Deco.Cap),
- projectIconUrls: ['/images/landing/dharma.png', '/images/landing/lendroid.png'],
- classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6',
- style: {
- width: 291,
- float: 'right',
- marginTop: !isSmallScreen ? 38 : 0,
+ const isEnglish = this.props.translate.getLanguage() === Language.English;
+ if (isEnglish) {
+ return [
+ {
+ imageUrl: '/images/landing/governance_icon.png',
+ type: this.props.translate.get(Key.GamingAndCollectables, Deco.Upper),
+ description: this.props.translate.get(Key.GamingAndCollectablesDescription, Deco.Cap),
+ classNames: 'lg-px2 md-px2',
},
- },
- {
- imageUrl: '/images/landing/fund_management_icon.png',
- type: this.props.translate.get(Key.FundManagement, Deco.Upper),
- description: this.props.translate.get(Key.FundManagementDescription, Deco.Cap),
- projectIconUrls: ['/images/landing/melonport.png'],
- classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6',
- style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 },
- },
- ];
-
+ {
+ imageUrl: '/images/landing/prediction_market_icon.png',
+ type: this.props.translate.get(Key.PredictionMarkets, Deco.Upper),
+ description: this.props.translate.get(Key.PredictionMarketsDescription, Deco.Cap),
+ classNames: 'lg-px2 md-px2',
+ },
+ {
+ imageUrl: '/images/landing/fund_management_icon.png',
+ type: this.props.translate.get(Key.OrderBooks, Deco.Upper),
+ description: this.props.translate.get(Key.OrderBooksDescription, Deco.Cap),
+ classNames: 'lg-px2 md-px2',
+ },
+ {
+ imageUrl: '/images/landing/loans_icon.png',
+ type: this.props.translate.get(Key.DecentralizedLoans, Deco.Upper),
+ description: this.props.translate.get(Key.DecentralizedLoansDescription, Deco.Cap),
+ classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6',
+ style: {
+ width: 291,
+ float: 'right',
+ marginTop: !isSmallScreen ? 38 : 0,
+ },
+ },
+ {
+ imageUrl: '/images/landing/stable_tokens_icon.png',
+ type: this.props.translate.get(Key.StableTokens, Deco.Upper),
+ description: this.props.translate.get(Key.StableTokensDescription, Deco.Cap),
+ classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6',
+ style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 },
+ },
+ ];
+ } else {
+ return [
+ {
+ imageUrl: '/images/landing/governance_icon.png',
+ type: this.props.translate.get(Key.DecentralizedGovernance, Deco.Upper),
+ description: this.props.translate.get(Key.DecentralizedGovernanceDescription, Deco.Cap),
+ classNames: 'lg-px2 md-px2',
+ },
+ {
+ imageUrl: '/images/landing/prediction_market_icon.png',
+ type: this.props.translate.get(Key.PredictionMarkets, Deco.Upper),
+ description: this.props.translate.get(Key.PredictionMarketsDescription, Deco.Cap),
+ classNames: 'lg-px2 md-px2',
+ },
+ {
+ imageUrl: '/images/landing/stable_tokens_icon.png',
+ type: this.props.translate.get(Key.StableTokens, Deco.Upper),
+ description: this.props.translate.get(Key.StableTokensDescription, Deco.Cap),
+ classNames: 'lg-px2 md-px2',
+ },
+ {
+ imageUrl: '/images/landing/loans_icon.png',
+ type: this.props.translate.get(Key.DecentralizedLoans, Deco.Upper),
+ description: this.props.translate.get(Key.DecentralizedLoansDescription, Deco.Cap),
+ classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6',
+ style: {
+ width: 291,
+ float: 'right',
+ marginTop: !isSmallScreen ? 38 : 0,
+ },
+ },
+ {
+ imageUrl: '/images/landing/fund_management_icon.png',
+ type: this.props.translate.get(Key.FundManagement, Deco.Upper),
+ description: this.props.translate.get(Key.FundManagementDescription, Deco.Cap),
+ classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6',
+ style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 },
+ },
+ ];
+ }
+ }
+ private _renderUseCases(): React.ReactNode {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
+ const useCases = this._getUseCases();
const cases = _.map(useCases, (useCase: UseCase) => {
const style = _.isUndefined(useCase.style) || isSmallScreen ? {} : useCase.style;
const useCaseBoxStyle = {
@@ -715,7 +564,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
lineHeight: 1.5,
fontSize: 14,
overflow: 'hidden',
- height: 104,
+ height: 124,
}}
>
{useCase.description}
@@ -725,7 +574,10 @@ export class Landing extends React.Component<LandingProps, LandingState> {
);
});
return (
- <div className="clearfix pb4 lg-pt2 md-pt2 sm-pt4" style={{ backgroundColor: colors.heroGrey }}>
+ <div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}>
+ <div className="center h4 pb3 lg-pl0 md-pl3 sm-pl2" style={TITLE_STYLE}>
+ {this.props.translate.get(Key.UseCasesHeader, Deco.Upper)}
+ </div>
<div className="mx-auto pb4 pt3 mt1 sm-mt2 clearfix" style={{ maxWidth: '67em' }}>
{cases}
</div>
diff --git a/packages/website/ts/redux/dispatcher.ts b/packages/website/ts/redux/dispatcher.ts
index db008d319..c418cab3f 100644
--- a/packages/website/ts/redux/dispatcher.ts
+++ b/packages/website/ts/redux/dispatcher.ts
@@ -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 {
diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts
index 1bc4611e0..f54801639 100644
--- a/packages/website/ts/redux/reducer.ts
+++ b/packages/website/ts/redux/reducer.ts
@@ -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,
};
}
diff --git a/packages/website/ts/schemas/portal_order_schema.ts b/packages/website/ts/schemas/portal_order_schema.ts
index ea8aeabc6..15e61f5e4 100644
--- a/packages/website/ts/schemas/portal_order_schema.ts
+++ b/packages/website/ts/schemas/portal_order_schema.ts
@@ -1,7 +1,7 @@
export const portalOrderSchema = {
id: '/PortalOrder',
properties: {
- signedOrder: { $ref: '/SignedOrder' },
+ signedOrder: { $ref: '/signedOrderSchema' },
metadata: { $ref: '/OrderMetadata' },
},
required: ['signedOrder', 'metadata'],
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index a1325d9bc..eeb0efaea 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -1,4 +1,4 @@
-import { ECSignature } from '@0xproject/types';
+import { ObjectMap, 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',
@@ -415,6 +399,7 @@ export enum Key {
OffChainOnChainDescription = 'OFFCHAIN_ONCHAIN_DESCRIPTION',
RelayersHeader = 'RELAYERS_HEADER',
BenefitsHeader = 'BENEFITS_HEADER',
+ UseCasesHeader = 'USE_CASES_HEADER',
BenefitOneTitle = 'BENEFIT_ONE_TITLE',
BenefitOneDescription = 'BENEFIT_ONE_DESCRIPTION',
BenefitTwoTitle = 'BENEFIT_TWO_TITLE',
@@ -436,6 +421,10 @@ export enum Key {
DecentralizedLoansDescription = 'DECENTRALIZED_LOANS_DESCRIPTION',
FundManagement = 'FUND_MANAGEMENT',
FundManagementDescription = 'FUND_MANAGEMENT_DESCRIPTION',
+ GamingAndCollectables = 'GAMING_AND_COLLECTABLES',
+ GamingAndCollectablesDescription = 'GAMING_AND_COLLECTABLES_DESCRIPTION',
+ OrderBooks = 'ORDER_BOOKS',
+ OrderBooksDescription = 'ORDER_BOOKS_DESCRIPTION',
FinalCallToAction = 'FINAL_CALL_TO_ACTION',
Documentation = 'DOCUMENTATION',
Community = 'COMMUNITY',
@@ -482,6 +471,7 @@ export enum Key {
LiveChat = 'LIVE_CHAT',
LibrariesAndTools = 'LIBRARIES_AND_TOOLS',
More = 'MORE',
+ OurMissionAndValues = 'OUR_MISSION_AND_VALUES',
}
export enum SmartContractDocSections {
@@ -515,7 +505,7 @@ export enum Providers {
Parity = 'PARITY',
Metamask = 'METAMASK',
Mist = 'MIST',
- Toshi = 'TOSHI',
+ CoinbaseWallet = 'COINBASE_WALLET',
Cipher = 'CIPHER',
}
@@ -543,10 +533,6 @@ export interface OutdatedWrappedEtherByNetworkId {
export type ItemByAddress<T> = ObjectMap<T>;
-export interface ObjectMap<T> {
- [key: string]: T;
-}
-
export type TokenStateByAddress = ItemByAddress<TokenState>;
export interface TokenState {
diff --git a/packages/website/ts/utils/analytics.ts b/packages/website/ts/utils/analytics.ts
index e5a1ddfa4..3aae317b0 100644
--- a/packages/website/ts/utils/analytics.ts
+++ b/packages/website/ts/utils/analytics.ts
@@ -1,5 +1,7 @@
+import { assetDataUtils } from '@0xproject/order-utils';
+import { ObjectMap } from '@0xproject/types';
import * as _ from 'lodash';
-import { ObjectMap, Order } from 'ts/types';
+import { PortalOrder } from 'ts/types';
import { utils } from 'ts/utils/utils';
export interface HeapAnalytics {
@@ -53,12 +55,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);
}
diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts
index a1c64f9cb..7b74eccfb 100644
--- a/packages/website/ts/utils/configs.ts
+++ b/packages/website/ts/utils/configs.ts
@@ -18,7 +18,7 @@ export const configs = {
DOMAIN_PRODUCTION: '0xproject.com',
GOOGLE_ANALYTICS_ID: 'UA-98720122-1',
LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22',
- LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2018-7-5',
+ LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2018-9-7',
OUTDATED_WRAPPED_ETHERS: [
{
42: {
@@ -44,27 +44,6 @@ export const configs = {
[3]: [`https://ropsten.infura.io/${INFURA_API_KEY}`],
[4]: [`https://rinkeby.infura.io/${INFURA_API_KEY}`],
} as PublicNodeUrlsByNetworkId,
- SYMBOLS_OF_MINTABLE_KOVAN_TOKENS: ['MKR', 'MLN', 'GNT', 'DGD', 'REP'],
- SYMBOLS_OF_MINTABLE_RINKEBY_ROPSTEN_TOKENS: [
- 'TKN0',
- 'TKN1',
- 'TKN2',
- 'TKN3',
- 'TKN4',
- 'TKN5',
- 'TKN6',
- 'TKN7',
- 'TKN8',
- 'TKN9',
- 'TKN10',
- 'TKN11',
- 'TKN12',
- 'TKN13',
- 'TKN14',
- 'TKN15',
- 'TKN16',
- 'TKN17',
- 'TKN18',
- 'TKN19',
- ],
+ SYMBOLS_OF_MINTABLE_KOVAN_TOKENS: ['ZRX', 'MKR', 'MLN', 'GNT', 'DGD', 'REP'],
+ SYMBOLS_OF_MINTABLE_ROPSTEN_TOKENS: ['ZRX', 'MKR', 'MLN', 'GNT', 'DGD', 'REP'],
};
diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts
index 24d4101f4..0809fb438 100644
--- a/packages/website/ts/utils/constants.ts
+++ b/packages/website/ts/utils/constants.ts
@@ -24,13 +24,14 @@ export const constants = {
NETWORK_ID_MAINNET: 1,
NETWORK_ID_KOVAN: 42,
NETWORK_ID_TESTRPC: 50,
+ NETWORK_ID_ROPSTEN: 3,
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
PROVIDER_NAME_LEDGER: 'Ledger',
PROVIDER_NAME_METAMASK: 'MetaMask',
PROVIDER_NAME_PARITY_SIGNER: 'Parity Signer',
PROVIDER_NAME_MIST: 'Mist',
PROVIDER_NAME_CIPHER: 'Cipher Browser',
- PROVIDER_NAME_TOSHI: 'Toshi',
+ PROVIDER_NAME_COINBASE_WALLET: 'Coinbase Wallet',
PROVIDER_NAME_GENERIC: 'Injected Web3',
PROVIDER_NAME_PUBLIC: '0x Public',
ROLLBAR_ACCESS_TOKEN: '32c39bfa4bb6440faedc1612a9c13d28',
@@ -76,8 +77,8 @@ export const constants = {
URL_FORUM: 'https://forum.0xproject.com',
URL_METAMASK_CHROME_STORE: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
URL_METAMASK_FIREFOX_STORE: 'https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/',
- URL_TOSHI_IOS_APP_STORE: 'https://itunes.apple.com/us/app/toshi-ethereum-wallet/id1278383455?mt=8',
- URL_TOSHI_ANDROID_APP_STORE: 'https://play.google.com/store/apps/details?id=org.toshi&hl=en_US',
+ URL_COINBASE_WALLET_IOS_APP_STORE: 'https://itunes.apple.com/us/app/coinbase-wallet/id1278383455?mt=8',
+ URL_COINBASE_WALLET_ANDROID_APP_STORE: 'https://play.google.com/store/apps/details?id=org.toshi&hl=en',
URL_METAMASK_HOMEPAGE: 'https://metamask.io/',
URL_METAMASK_OPERA_STORE: 'https://addons.opera.com/en/extensions/details/metamask/',
URL_MIST_DOWNLOAD: 'https://github.com/ethereum/mist/releases',
diff --git a/packages/website/ts/utils/doc_utils.ts b/packages/website/ts/utils/doc_utils.ts
index e313648bd..0e1d9ea6e 100644
--- a/packages/website/ts/utils/doc_utils.ts
+++ b/packages/website/ts/utils/doc_utils.ts
@@ -1,4 +1,4 @@
-import { DoxityDocObj, GeneratedDocJson } from '@0xproject/react-docs';
+import { DocAgnosticFormat, GeneratedDocJson } from '@0xproject/react-docs';
import { fetchAsync, logUtils } from '@0xproject/utils';
import * as _ from 'lodash';
import { S3FileObject, VersionToFilePath } from 'ts/types';
@@ -70,7 +70,7 @@ export const docUtils = {
});
return versionFilePaths;
},
- async getJSONDocFileAsync(filePath: string, s3DocJsonRoot: string): Promise<GeneratedDocJson | DoxityDocObj> {
+ async getJSONDocFileAsync(filePath: string, s3DocJsonRoot: string): Promise<GeneratedDocJson | DocAgnosticFormat> {
const endpoint = `${s3DocJsonRoot}/${filePath}`;
const response = await fetchAsync(endpoint);
if (response.status !== 200) {
diff --git a/packages/website/ts/utils/order_parser.ts b/packages/website/ts/utils/order_parser.ts
index be08da80e..816200e3b 100644
--- a/packages/website/ts/utils/order_parser.ts
+++ b/packages/website/ts/utils/order_parser.ts
@@ -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;
},
};
diff --git a/packages/website/ts/utils/token_address_overrides.ts b/packages/website/ts/utils/token_address_overrides.ts
new file mode 100644
index 000000000..e7e916273
--- /dev/null
+++ b/packages/website/ts/utils/token_address_overrides.ts
@@ -0,0 +1,24 @@
+import { ObjectMap } from '@0xproject/types';
+import { constants } from 'ts/utils/constants';
+
+// Map of networkId -> tokenSymbol -> tokenAddress
+export type TokenOverrides = ObjectMap<ObjectMap<string>>;
+
+export const tokenAddressOverrides: TokenOverrides = {
+ [constants.NETWORK_ID_KOVAN]: {
+ ZRX: '0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa',
+ REP: '0x8cb3971b8eb709c14616bd556ff6683019e90d9c',
+ DGD: '0xa4f468c9c692eb6b4b8b06270dae7a2cfeedcde9',
+ GNT: '0x31fb614e223706f15d0d3c5f4b08bdf0d5c78623',
+ MKR: '0x7b6b10caa9e8e9552ba72638ea5b47c25afea1f3',
+ MLN: '0x17e394d1df6ce29d042195ea38411a98ff3ead94',
+ },
+ [constants.NETWORK_ID_ROPSTEN]: {
+ ZRX: '0xff67881f8d12f372d91baae9752eb3631ff0ed00',
+ REP: '0xb0b443fe0e8a04c4c85e8fda9c5c1ccc057d6653',
+ DGD: '0xc4895a5aafa2708d6bc1294e20ec839aad156b1d',
+ GNT: '0x7f8acc55a359ca4517c30510566ac35b800f7cac',
+ MKR: '0x06732516acd125b6e83c127752ed5f027e1b276e',
+ MLN: '0x823ebe83d39115536274a8617e00a1ff3544fd63',
+ },
+};
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index 39bbd404c..d083e0ffc 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -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]:
@@ -324,7 +323,7 @@ export const utils = {
} else if ((provider as any).isMetaMask) {
parsedProviderName = Providers.Metamask;
} else if (!_.isUndefined(_.get(window, 'SOFA'))) {
- parsedProviderName = Providers.Toshi;
+ parsedProviderName = Providers.CoinbaseWallet;
} else if (!_.isUndefined(_.get(window, '__CIPHER__'))) {
parsedProviderName = Providers.Cipher;
}
@@ -454,14 +453,14 @@ export const utils = {
if (isOnMobile) {
switch (operatingSystem) {
case OperatingSystemType.Android:
- downloadLink = constants.URL_TOSHI_ANDROID_APP_STORE;
+ downloadLink = constants.URL_COINBASE_WALLET_ANDROID_APP_STORE;
break;
case OperatingSystemType.iOS:
- downloadLink = constants.URL_TOSHI_IOS_APP_STORE;
+ downloadLink = constants.URL_COINBASE_WALLET_IOS_APP_STORE;
break;
default:
- // Toshi is only supported on these mobile OSes - just default to iOS
- downloadLink = constants.URL_TOSHI_IOS_APP_STORE;
+ // Coinbase wallet is only supported on these mobile OSes - just default to iOS
+ downloadLink = constants.URL_COINBASE_WALLET_IOS_APP_STORE;
}
} else {
switch (browserType) {