Merge branch 'development' into feature/updateReadmes

* development: (35 commits)
  Remove etherToken from smart contract docs
  Update new WETH addresses and localStorage clearance key
  Fix merge
  Remove re-assignment
  Fix scrolling topBar on Portal
  Fix overflow issue on calculated fillAmount
  Fix faulty import
  Refactor remaining _.assign to spread operator
  Move muiTheme into it's own module
  Add WETH
  remove extra space
  Remove binding on prop passed callbacks
  Add airtable tasks to TODO's
  Refactor configs and constants, standardize on uppercase/snakecase, alphebetize, rename for logical grouping
  Sort colors into color spectrum
  remove unused style
  standarize on `grey` over `gray` spelling and other color related fixes
  Standardize colors to always be in uppercase hex and consolidate material-ui greys
  Consolidate all custom colors and material-ui colors into a colors module
  Remove unused `location` prop
  ...
This commit is contained in:
Brandon Millman
2017-12-19 17:51:09 -05:00
73 changed files with 1110 additions and 1027 deletions

View File

@@ -20,6 +20,7 @@
"dependencies": { "dependencies": {
"0x.js": "~0.27.2", "0x.js": "~0.27.2",
"@0xproject/subproviders": "^0.1.0", "@0xproject/subproviders": "^0.1.0",
"@0xproject/utils": "^0.1.0",
"accounting": "^0.4.1", "accounting": "^0.4.1",
"basscss": "^8.0.3", "basscss": "^8.0.3",
"bignumber.js": "~4.1.0", "bignumber.js": "~4.1.0",

View File

@@ -77,21 +77,21 @@ export class Blockchain {
} }
private static getNameGivenProvider(provider: Web3.Provider): string { private static getNameGivenProvider(provider: Web3.Provider): string {
if (!_.isUndefined((provider as any).isMetaMask)) { if (!_.isUndefined((provider as any).isMetaMask)) {
return constants.METAMASK_PROVIDER_NAME; return constants.PROVIDER_NAME_METAMASK;
} }
// HACK: We use the fact that Parity Signer's provider is an instance of their // HACK: We use the fact that Parity Signer's provider is an instance of their
// internal `Web3FrameProvider` class. // internal `Web3FrameProvider` class.
const isParitySigner = _.startsWith(provider.constructor.toString(), 'function Web3FrameProvider'); const isParitySigner = _.startsWith(provider.constructor.toString(), 'function Web3FrameProvider');
if (isParitySigner) { if (isParitySigner) {
return constants.PARITY_SIGNER_PROVIDER_NAME; return constants.PROVIDER_NAME_PARITY_SIGNER;
} }
return constants.GENERIC_PROVIDER_NAME; return constants.PROVIDER_NAME_GENERIC;
} }
private static async getProviderAsync(injectedWeb3: Web3, networkIdIfExists: number) { private static async getProviderAsync(injectedWeb3: Web3, networkIdIfExists: number) {
const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3); const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3);
const publicNodeUrlsIfExistsForNetworkId = constants.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkIdIfExists]; const publicNodeUrlsIfExistsForNetworkId = configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkIdIfExists];
const isPublicNodeAvailableForNetworkId = !_.isUndefined(publicNodeUrlsIfExistsForNetworkId); const isPublicNodeAvailableForNetworkId = !_.isUndefined(publicNodeUrlsIfExistsForNetworkId);
let provider; let provider;
@@ -114,11 +114,11 @@ export class Blockchain {
// injected into their browser. // injected into their browser.
provider = new ProviderEngine(); provider = new ProviderEngine();
provider.addProvider(new FilterSubprovider()); provider.addProvider(new FilterSubprovider());
const networkId = configs.isMainnetEnabled ? const networkId = configs.IS_MAINNET_ENABLED ?
constants.MAINNET_NETWORK_ID : constants.NETWORK_ID_MAINNET :
constants.TESTNET_NETWORK_ID; constants.NETWORK_ID_TESTNET;
provider.addProvider(new RedundantRPCSubprovider( provider.addProvider(new RedundantRPCSubprovider(
constants.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
)); ));
provider.start(); provider.start();
} }
@@ -135,11 +135,11 @@ export class Blockchain {
const isConnected = !_.isUndefined(newNetworkId); const isConnected = !_.isUndefined(newNetworkId);
if (!isConnected) { if (!isConnected) {
this.networkId = newNetworkId; this.networkId = newNetworkId;
this.dispatcher.encounteredBlockchainError(BlockchainErrs.DISCONNECTED_FROM_ETHEREUM_NODE); this.dispatcher.encounteredBlockchainError(BlockchainErrs.DisconnectedFromEthereumNode);
this.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
} else if (this.networkId !== newNetworkId) { } else if (this.networkId !== newNetworkId) {
this.networkId = newNetworkId; this.networkId = newNetworkId;
this.dispatcher.encounteredBlockchainError(''); this.dispatcher.encounteredBlockchainError(BlockchainErrs.NoError);
await this.fetchTokenInformationAsync(); await this.fetchTokenInformationAsync();
await this.rehydrateStoreWithContractEvents(); await this.rehydrateStoreWithContractEvents();
} }
@@ -158,6 +158,14 @@ export class Blockchain {
} }
public async isAddressInTokenRegistryAsync(tokenAddress: string): Promise<boolean> { public async isAddressInTokenRegistryAsync(tokenAddress: string): Promise<boolean> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.'); utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
// HACK: temporarily whitelist the new WETH token address `as if` they were
// already in the tokenRegistry.
// TODO: Remove this hack once we've updated the TokenRegistries
// Airtable task: https://airtable.com/tblFe0Q9JuKJPYbTn/viwsOG2Y97qdIeCIO/recv3VGmIorFzHBVz
if (configs.SHOULD_DEPRECATE_OLD_WETH_TOKEN &&
tokenAddress === configs.NEW_WRAPPED_ETHERS[this.networkId]) {
return true;
}
const tokenIfExists = await this.zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress); const tokenIfExists = await this.zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
return !_.isUndefined(tokenIfExists); return !_.isUndefined(tokenIfExists);
} }
@@ -186,7 +194,7 @@ export class Blockchain {
// later on in the logic. // later on in the logic.
let provider; let provider;
switch (providerType) { switch (providerType) {
case ProviderType.LEDGER: { case ProviderType.Ledger: {
const isU2FSupported = await utils.isU2FSupportedAsync(); const isU2FSupported = await utils.isU2FSupportedAsync();
if (!isU2FSupported) { if (!isU2FSupported) {
throw new Error('Cannot update providerType to LEDGER without U2F support'); throw new Error('Cannot update providerType to LEDGER without U2F support');
@@ -205,11 +213,11 @@ export class Blockchain {
this.ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs); this.ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs);
provider.addProvider(this.ledgerSubprovider); provider.addProvider(this.ledgerSubprovider);
provider.addProvider(new FilterSubprovider()); provider.addProvider(new FilterSubprovider());
const networkId = configs.isMainnetEnabled ? const networkId = configs.IS_MAINNET_ENABLED ?
constants.MAINNET_NETWORK_ID : constants.NETWORK_ID_MAINNET :
constants.TESTNET_NETWORK_ID; constants.NETWORK_ID_TESTNET;
provider.addProvider(new RedundantRPCSubprovider( provider.addProvider(new RedundantRPCSubprovider(
constants.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId], configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
)); ));
provider.start(); provider.start();
this.web3Wrapper.destroy(); this.web3Wrapper.destroy();
@@ -220,7 +228,7 @@ export class Blockchain {
break; break;
} }
case ProviderType.INJECTED: { case ProviderType.Injected: {
if (_.isUndefined(this.cachedProvider)) { if (_.isUndefined(this.cachedProvider)) {
return; // Going from injected to injected, so we noop return; // Going from injected to injected, so we noop
} }
@@ -241,8 +249,8 @@ export class Blockchain {
await this.fetchTokenInformationAsync(); await this.fetchTokenInformationAsync();
} }
public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise<void> { public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise<void> {
utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TOKEN_ADDRESS_IS_INVALID); utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TokenAddressIsInvalid);
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.'); utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
const txHash = await this.zeroEx.token.setProxyAllowanceAsync( const txHash = await this.zeroEx.token.setProxyAllowanceAsync(
@@ -258,7 +266,7 @@ export class Blockchain {
token.address, this.userAddress, toAddress, amountInBaseUnits, token.address, this.userAddress, toAddress, amountInBaseUnits,
); );
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.tx); const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.Tx);
this.dispatcher.showFlashMessage(React.createElement(TokenSendCompleted, { this.dispatcher.showFlashMessage(React.createElement(TokenSendCompleted, {
etherScanLinkIfExists, etherScanLinkIfExists,
token, token,
@@ -294,7 +302,7 @@ export class Blockchain {
} }
public async fillOrderAsync(signedOrder: SignedOrder, public async fillOrderAsync(signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber): Promise<BigNumber> { fillTakerTokenAmount: BigNumber): Promise<BigNumber> {
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const shouldThrowOnInsufficientBalanceOrAllowance = true; const shouldThrowOnInsufficientBalanceOrAllowance = true;
@@ -346,7 +354,7 @@ export class Blockchain {
return this.web3Wrapper.isAddress(lowercaseAddress); return this.web3Wrapper.isAddress(lowercaseAddress);
} }
public async pollTokenBalanceAsync(token: Token) { public async pollTokenBalanceAsync(token: Token) {
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const [currBalance] = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, token.address); const [currBalance] = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, token.address);
@@ -375,7 +383,7 @@ export class Blockchain {
return signatureData; return signatureData;
} }
public async mintTestTokensAsync(token: Token) { public async mintTestTokensAsync(token: Token) {
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const mintableContract = await this.instantiateContractIfExistsAsync(MintableArtifacts, token.address); const mintableContract = await this.instantiateContractIfExistsAsync(MintableArtifacts, token.address);
await mintableContract.mint(constants.MINT_AMOUNT, { await mintableContract.mint(constants.MINT_AMOUNT, {
@@ -390,14 +398,14 @@ export class Blockchain {
} }
public async convertEthToWrappedEthTokensAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> { public async convertEthToWrappedEthTokensAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.'); utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const txHash = await this.zeroEx.etherToken.depositAsync(etherTokenAddress, amount, this.userAddress); const txHash = await this.zeroEx.etherToken.depositAsync(etherTokenAddress, amount, this.userAddress);
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
} }
public async convertWrappedEthTokensToEthAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> { public async convertWrappedEthTokensToEthAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.'); utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const txHash = await this.zeroEx.etherToken.withdrawAsync(etherTokenAddress, amount, this.userAddress); const txHash = await this.zeroEx.etherToken.withdrawAsync(etherTokenAddress, amount, this.userAddress);
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash); await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
@@ -463,7 +471,7 @@ export class Blockchain {
} }
private async showEtherScanLinkAndAwaitTransactionMinedAsync( private async showEtherScanLinkAndAwaitTransactionMinedAsync(
txHash: string): Promise<TransactionReceiptWithDecodedLogs> { txHash: string): Promise<TransactionReceiptWithDecodedLogs> {
const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.tx); const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.Tx);
this.dispatcher.showFlashMessage(React.createElement(TransactionSubmitted, { this.dispatcher.showFlashMessage(React.createElement(TransactionSubmitted, {
etherScanLinkIfExists, etherScanLinkIfExists,
})); }));
@@ -491,7 +499,7 @@ export class Blockchain {
} }
private async startListeningForExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise<void> { private async startListeningForExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise<void> {
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.'); utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES); utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
// Fetch historical logs // Fetch historical logs
await this.fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues); await this.fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues);
@@ -591,19 +599,19 @@ export class Blockchain {
_.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => { _.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => {
// HACK: For now we have a hard-coded list of iconUrls for the dummyTokens // HACK: For now we have a hard-coded list of iconUrls for the dummyTokens
// TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry // TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry
const iconUrl = constants.iconUrlBySymbol[t.symbol]; const iconUrl = configs.ICON_URL_BY_SYMBOL[t.symbol];
// HACK: Temporarily we hijack the WETH addresses fetched from the tokenRegistry // HACK: Temporarily we hijack the WETH addresses fetched from the tokenRegistry
// so that we can take our time with actually updating it. This ensures that when // so that we can take our time with actually updating it. This ensures that when
// we deploy the new WETH page, everyone will re-fill their trackedTokens with the // we deploy the new WETH page, everyone will re-fill their trackedTokens with the
// new canonical WETH. // new canonical WETH.
// TODO: Remove this hack once we've updated the TokenRegistries // TODO: Remove this hack once we've updated the TokenRegistries
// Airtable task: https://airtable.com/tblFe0Q9JuKJPYbTn/viwsOG2Y97qdIeCIO/recv3VGmIorFzHBVz
let address = t.address; let address = t.address;
if (t.symbol === 'WETH') { if (configs.SHOULD_DEPRECATE_OLD_WETH_TOKEN && t.symbol === 'WETH') {
if (this.networkId === 1) { const newEtherTokenAddressIfExists = configs.NEW_WRAPPED_ETHERS[this.networkId];
address = '0xe495bcacaf29a0eb00fb67b86e9cd2a994dd55d8'; if (!_.isUndefined(newEtherTokenAddressIfExists)) {
} else if (this.networkId === 42) { address = newEtherTokenAddressIfExists;
address = '0x739e78d6bebbdf24105a5145fa04436589d1cbd9'; }
}
} }
const token: Token = { const token: Token = {
iconUrl, iconUrl,
@@ -639,9 +647,9 @@ export class Blockchain {
const provider = await Blockchain.getProviderAsync(injectedWeb3, networkIdIfExists); const provider = await Blockchain.getProviderAsync(injectedWeb3, networkIdIfExists);
const networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists : const networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists :
configs.isMainnetEnabled ? configs.IS_MAINNET_ENABLED ?
constants.MAINNET_NETWORK_ID : constants.NETWORK_ID_MAINNET :
constants.TESTNET_NETWORK_ID; constants.NETWORK_ID_TESTNET;
const zeroExConfigs = { const zeroExConfigs = {
networkId, networkId,
}; };
@@ -661,7 +669,7 @@ export class Blockchain {
const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3); const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3);
const providerName = doesInjectedWeb3Exist ? const providerName = doesInjectedWeb3Exist ?
Blockchain.getNameGivenProvider(injectedWeb3.currentProvider) : Blockchain.getNameGivenProvider(injectedWeb3.currentProvider) :
constants.PUBLIC_PROVIDER_NAME; constants.PROVIDER_NAME_PUBLIC;
this.dispatcher.updateInjectedProviderName(providerName); this.dispatcher.updateInjectedProviderName(providerName);
} }
private async fetchTokenInformationAsync() { private async fetchTokenInformationAsync() {
@@ -686,7 +694,7 @@ export class Blockchain {
let trackedTokensIfExists = trackedTokenStorage.getTrackedTokensIfExists(this.userAddress, this.networkId); let trackedTokensIfExists = trackedTokenStorage.getTrackedTokensIfExists(this.userAddress, this.networkId);
const tokenRegistryTokens = _.values(tokenRegistryTokensByAddress); const tokenRegistryTokens = _.values(tokenRegistryTokensByAddress);
if (_.isUndefined(trackedTokensIfExists)) { if (_.isUndefined(trackedTokensIfExists)) {
trackedTokensIfExists = _.map(configs.defaultTrackedTokenSymbols, symbol => { trackedTokensIfExists = _.map(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, symbol => {
const token = _.find(tokenRegistryTokens, t => t.symbol === symbol); const token = _.find(tokenRegistryTokens, t => t.symbol === symbol);
token.isTracked = true; token.isTracked = true;
return token; return token;
@@ -709,11 +717,11 @@ export class Blockchain {
await this.updateTokenBalancesAndAllowancesAsync(trackedTokensIfExists); await this.updateTokenBalancesAndAllowancesAsync(trackedTokensIfExists);
const mostPopularTradingPairTokens: Token[] = [ const mostPopularTradingPairTokens: Token[] = [
_.find(allTokens, {symbol: configs.defaultTrackedTokenSymbols[0]}), _.find(allTokens, {symbol: configs.DEFAULT_TRACKED_TOKEN_SYMBOLS[0]}),
_.find(allTokens, {symbol: configs.defaultTrackedTokenSymbols[1]}), _.find(allTokens, {symbol: configs.DEFAULT_TRACKED_TOKEN_SYMBOLS[1]}),
]; ];
this.dispatcher.updateChosenAssetTokenAddress(Side.deposit, mostPopularTradingPairTokens[0].address); this.dispatcher.updateChosenAssetTokenAddress(Side.Deposit, mostPopularTradingPairTokens[0].address);
this.dispatcher.updateChosenAssetTokenAddress(Side.receive, mostPopularTradingPairTokens[1].address); this.dispatcher.updateChosenAssetTokenAddress(Side.Receive, mostPopularTradingPairTokens[1].address);
this.dispatcher.updateBlockchainIsLoaded(true); this.dispatcher.updateBlockchainIsLoaded(true);
} }
private async instantiateContractIfExistsAsync(artifact: any, address?: string): Promise<ContractInstance> { private async instantiateContractIfExistsAsync(artifact: any, address?: string): Promise<ContractInstance> {
@@ -733,7 +741,7 @@ export class Blockchain {
const doesContractExist = await this.doesContractExistAtAddressAsync(contractAddress); const doesContractExist = await this.doesContractExistAtAddressAsync(contractAddress);
if (!doesContractExist) { if (!doesContractExist) {
utils.consoleLog(`Contract does not exist: ${artifact.contract_name} at ${contractAddress}`); utils.consoleLog(`Contract does not exist: ${artifact.contract_name} at ${contractAddress}`);
throw new Error(BlockchainCallErrs.CONTRACT_DOES_NOT_EXIST); throw new Error(BlockchainCallErrs.ContractDoesNotExist);
} }
} }
@@ -746,10 +754,10 @@ export class Blockchain {
const errMsg = `${err}`; const errMsg = `${err}`;
utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`); utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`);
if (_.includes(errMsg, 'not been deployed to detected network')) { if (_.includes(errMsg, 'not been deployed to detected network')) {
throw new Error(BlockchainCallErrs.CONTRACT_DOES_NOT_EXIST); throw new Error(BlockchainCallErrs.ContractDoesNotExist);
} else { } else {
await errorReporter.reportAsync(err); await errorReporter.reportAsync(err);
throw new Error(BlockchainCallErrs.UNHANDLED_ERROR); throw new Error(BlockchainCallErrs.UnhandledError);
} }
} }
} }

View File

@@ -1,10 +1,10 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog'; import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Blockchain} from 'ts/blockchain'; import {Blockchain} from 'ts/blockchain';
import {BlockchainErrs} from 'ts/types'; import {BlockchainErrs} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs'; import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
@@ -46,22 +46,22 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
); );
} }
private getTitle(hasWalletAddress: boolean) { private getTitle(hasWalletAddress: boolean) {
if (this.props.blockchainErr === BlockchainErrs.A_CONTRACT_NOT_DEPLOYED_ON_NETWORK) { if (this.props.blockchainErr === BlockchainErrs.AContractNotDeployedOnNetwork) {
return '0x smart contracts not found'; return '0x smart contracts not found';
} else if (!hasWalletAddress) { } else if (!hasWalletAddress) {
return 'Enable wallet communication'; return 'Enable wallet communication';
} else if (this.props.blockchainErr === BlockchainErrs.DISCONNECTED_FROM_ETHEREUM_NODE) { } else if (this.props.blockchainErr === BlockchainErrs.DisconnectedFromEthereumNode) {
return 'Disconnected from Ethereum network'; return 'Disconnected from Ethereum network';
} else { } else {
return 'Unexpected error'; return 'Unexpected error';
} }
} }
private renderExplanation(hasWalletAddress: boolean) { private renderExplanation(hasWalletAddress: boolean) {
if (this.props.blockchainErr === BlockchainErrs.A_CONTRACT_NOT_DEPLOYED_ON_NETWORK) { if (this.props.blockchainErr === BlockchainErrs.AContractNotDeployedOnNetwork) {
return this.renderContractsNotDeployedExplanation(); return this.renderContractsNotDeployedExplanation();
} else if (!hasWalletAddress) { } else if (!hasWalletAddress) {
return this.renderNoWalletFoundExplanation(); return this.renderNoWalletFoundExplanation();
} else if (this.props.blockchainErr === BlockchainErrs.DISCONNECTED_FROM_ETHEREUM_NODE) { } else if (this.props.blockchainErr === BlockchainErrs.DisconnectedFromEthereumNode) {
return this.renderDisconnectedFromNode(); return this.renderDisconnectedFromNode();
} else { } else {
return this.renderUnexpectedErrorExplanation(); return this.renderUnexpectedErrorExplanation();
@@ -71,9 +71,9 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
return ( return (
<div> <div>
You were disconnected from the backing Ethereum node. You were disconnected from the backing Ethereum node.
{' '}If using <a href={constants.METAMASK_CHROME_STORE_URL} target="_blank"> {' '}If using <a href={constants.URL_METAMASK_CHROME_STORE} target="_blank">
Metamask Metamask
</a> or <a href={constants.MIST_DOWNLOAD_URL} target="_blank">Mist</a> try refreshing </a> or <a href={constants.URL_MIST_DOWNLOAD} target="_blank">Mist</a> try refreshing
{' '}the page. If using a locally hosted Ethereum node, make sure it's still running. {' '}the page. If using a locally hosted Ethereum node, make sure it's still running.
</div> </div>
); );
@@ -97,7 +97,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
<h4>1. Metamask chrome extension</h4> <h4>1. Metamask chrome extension</h4>
<div> <div>
You can install the{' '} You can install the{' '}
<a href={constants.METAMASK_CHROME_STORE_URL} target="_blank"> <a href={constants.URL_METAMASK_CHROME_STORE} target="_blank">
Metamask Metamask
</a> Chrome extension Ethereum wallet. Once installed and set up, refresh this page. </a> Chrome extension Ethereum wallet. Once installed and set up, refresh this page.
<div className="pt1"> <div className="pt1">
@@ -107,11 +107,11 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
</div> </div>
<h4>Parity Signer</h4> <h4>Parity Signer</h4>
<div> <div>
The <a href={constants.PARITY_CHROME_STORE_URL} target="_blank">Parity Signer The <a href={constants.URL_PARITY_CHROME_STORE} target="_blank">Parity Signer
Chrome extension</a>{' '}lets you connect to a locally running Parity node. Chrome extension</a>{' '}lets you connect to a locally running Parity node.
Make sure you have started your local Parity node with{' '} Make sure you have started your local Parity node with{' '}
{configs.isMainnetEnabled && '`parity ui` or'} `parity --chain kovan ui`{' '} {configs.IS_MAINNET_ENABLED && '`parity ui` or'} `parity --chain kovan ui`{' '}
in order to connect to {configs.isMainnetEnabled ? 'mainnet or Kovan respectively.' : 'Kovan.'} in order to connect to {configs.IS_MAINNET_ENABLED ? 'mainnet or Kovan respectively.' : 'Kovan.'}
</div> </div>
<div className="pt2"> <div className="pt2">
<span className="bold">Note:</span> <span className="bold">Note:</span>
@@ -130,24 +130,24 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
{' '}currently connected to (network Id: {this.props.networkId}). {' '}currently connected to (network Id: {this.props.networkId}).
{' '}In order to use the 0x portal dApp, {' '}In order to use the 0x portal dApp,
{' '}please connect to the {' '}please connect to the
{' '}{constants.TESTNET_NAME} testnet (network Id: {constants.TESTNET_NETWORK_ID}) {' '}{constants.TESTNET_NAME} testnet (network Id: {constants.NETWORK_ID_TESTNET})
{configs.isMainnetEnabled ? {configs.IS_MAINNET_ENABLED ?
` or ${constants.MAINNET_NAME} (network Id: ${constants.MAINNET_NETWORK_ID}).` : ` or ${constants.MAINNET_NAME} (network Id: ${constants.NETWORK_ID_MAINNET}).` :
`.` `.`
} }
</div> </div>
<h4>Metamask</h4> <h4>Metamask</h4>
<div> <div>
If you are using{' '} If you are using{' '}
<a href={constants.METAMASK_CHROME_STORE_URL} target="_blank"> <a href={constants.URL_METAMASK_CHROME_STORE} target="_blank">
Metamask Metamask
</a>, you can switch networks in the top left corner of the extension popover. </a>, you can switch networks in the top left corner of the extension popover.
</div> </div>
<h4>Parity Signer</h4> <h4>Parity Signer</h4>
<div> <div>
If using the <a href={constants.PARITY_CHROME_STORE_URL} target="_blank">Parity Signer If using the <a href={constants.URL_PARITY_CHROME_STORE} target="_blank">Parity Signer
Chrome extension</a>, make sure to start your local Parity node with{' '} Chrome extension</a>, make sure to start your local Parity node with{' '}
{configs.isMainnetEnabled ? {configs.IS_MAINNET_ENABLED ?
'`parity ui` or `parity --chain Kovan ui` in order to connect to mainnet \ '`parity ui` or `parity --chain Kovan ui` in order to connect to mainnet \
or Kovan respectively.' : or Kovan respectively.' :
'`parity --chain kovan ui` in order to connect to Kovan.' '`parity --chain kovan ui` in order to connect to Kovan.'

View File

@@ -5,8 +5,7 @@ import * as React from 'react';
import {EthAmountInput} from 'ts/components/inputs/eth_amount_input'; import {EthAmountInput} from 'ts/components/inputs/eth_amount_input';
import {TokenAmountInput} from 'ts/components/inputs/token_amount_input'; import {TokenAmountInput} from 'ts/components/inputs/token_amount_input';
import {Side, Token, TokenState} from 'ts/types'; import {Side, Token, TokenState} from 'ts/types';
import {colors} from 'ts/utils/colors';
const DARK_BLUE = '#4D5481';
interface EthWethConversionDialogProps { interface EthWethConversionDialogProps {
direction: Side; direction: Side;
@@ -47,7 +46,7 @@ export class EthWethConversionDialog extends
onTouchTap={this.onConvertClick.bind(this)} onTouchTap={this.onConvertClick.bind(this)}
/>, />,
]; ];
const title = this.props.direction === Side.deposit ? 'Wrap ETH' : 'Unwrap WETH'; const title = this.props.direction === Side.Deposit ? 'Wrap ETH' : 'Unwrap WETH';
return ( return (
<Dialog <Dialog
title={title} title={title}
@@ -61,10 +60,10 @@ export class EthWethConversionDialog extends
); );
} }
private renderConversionDialogBody() { private renderConversionDialogBody() {
const explanation = this.props.direction === Side.deposit ? const explanation = this.props.direction === Side.Deposit ?
'Convert your Ether into a tokenized, tradable form.' : 'Convert your Ether into a tokenized, tradable form.' :
'Convert your Wrapped Ether back into it\'s native form.'; 'Convert your Wrapped Ether back into it\'s native form.';
const isWrappedVersion = this.props.direction === Side.receive; const isWrappedVersion = this.props.direction === Side.Receive;
return ( return (
<div> <div>
<div className="pb2"> <div className="pb2">
@@ -75,7 +74,7 @@ export class EthWethConversionDialog extends
{this.renderCurrency(isWrappedVersion)} {this.renderCurrency(isWrappedVersion)}
<div style={{paddingTop: 68}}> <div style={{paddingTop: 68}}>
<i <i
style={{fontSize: 28, color: DARK_BLUE}} style={{fontSize: 28, color: colors.darkBlue}}
className="zmdi zmdi-arrow-right" className="zmdi zmdi-arrow-right"
/> />
</div> </div>
@@ -85,7 +84,7 @@ export class EthWethConversionDialog extends
className="pt2 mx-auto" className="pt2 mx-auto"
style={{width: 245}} style={{width: 245}}
> >
{this.props.direction === Side.receive ? {this.props.direction === Side.Receive ?
<TokenAmountInput <TokenAmountInput
token={this.props.token} token={this.props.token}
tokenState={this.props.tokenState} tokenState={this.props.tokenState}
@@ -109,7 +108,16 @@ export class EthWethConversionDialog extends
className="pt1" className="pt1"
style={{fontSize: 12}} style={{fontSize: 12}}
> >
1 ETH = 1 WETH <div className="left">1 ETH = 1 WETH</div>
{this.props.direction === Side.Receive &&
<div
className="right"
onClick={this.onMaxClick.bind(this)}
style={{color: colors.darkBlue, textDecoration: 'underline', cursor: 'pointer'}}
>
Max
</div>
}
</div> </div>
</div> </div>
</div> </div>
@@ -124,7 +132,7 @@ export class EthWethConversionDialog extends
<div className="mx-auto pt2"> <div className="mx-auto pt2">
<div <div
className="center" className="center"
style={{color: DARK_BLUE}} style={{color: colors.darkBlue}}
> >
{name} {name}
</div> </div>
@@ -137,6 +145,11 @@ export class EthWethConversionDialog extends
</div> </div>
); );
} }
private onMaxClick() {
this.setState({
value: this.props.tokenState.balance,
});
}
private onValueChange(isValid: boolean, amount?: BigNumber) { private onValueChange(isValid: boolean, amount?: BigNumber) {
this.setState({ this.setState({
value: amount, value: amount,

View File

@@ -2,7 +2,6 @@ import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog'; import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import {colors} from 'material-ui/styles';
import { import {
Table, Table,
TableBody, TableBody,
@@ -17,6 +16,8 @@ import ReactTooltip = require('react-tooltip');
import {Blockchain} from 'ts/blockchain'; import {Blockchain} from 'ts/blockchain';
import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button'; import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button';
import {Dispatcher} from 'ts/redux/dispatcher'; import {Dispatcher} from 'ts/redux/dispatcher';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
@@ -52,7 +53,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
stepIndex: LedgerSteps.CONNECT, stepIndex: LedgerSteps.CONNECT,
userAddresses: [], userAddresses: [],
addressBalances: [], addressBalances: [],
derivationPath: constants.DEFAULT_DERIVATION_PATH, derivationPath: configs.DEFAULT_DERIVATION_PATH,
derivationErrMsg: '', derivationErrMsg: '',
}; };
} }
@@ -146,7 +147,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
<div className="overflow-hidden" style={{width: 180}}> <div className="overflow-hidden" style={{width: 180}}>
<TextField <TextField
floatingLabelFixed={true} floatingLabelFixed={true}
floatingLabelStyle={{color: colors.grey500}} floatingLabelStyle={{color: colors.grey}}
floatingLabelText="Update path derivation (advanced)" floatingLabelText="Update path derivation (advanced)"
value={this.state.derivationPath} value={this.state.derivationPath}
errorText={this.state.derivationErrMsg} errorText={this.state.derivationErrMsg}
@@ -170,7 +171,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
const balance = this.state.addressBalances[i]; const balance = this.state.addressBalances[i];
const addressTooltipId = `address-${userAddress}`; const addressTooltipId = `address-${userAddress}`;
const balanceTooltipId = `balance-${userAddress}`; const balanceTooltipId = `balance-${userAddress}`;
const networkName = constants.networkNameById[this.props.networkId]; const networkName = constants.NETWORK_NAME_BY_ID[this.props.networkId];
// We specifically prefix kovan ETH. // We specifically prefix kovan ETH.
// TODO: We should probably add prefixes for all networks // TODO: We should probably add prefixes for all networks
const isKovanNetwork = networkName === 'Kovan'; const isKovanNetwork = networkName === 'Kovan';

View File

@@ -1,7 +1,7 @@
import Dialog from 'material-ui/Dialog'; import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
interface PortalDisclaimerDialogProps { interface PortalDisclaimerDialogProps {
isOpen: boolean; isOpen: boolean;
@@ -17,11 +17,11 @@ export function PortalDisclaimerDialog(props: PortalDisclaimerDialogProps) {
<FlatButton <FlatButton
key="portalAgree" key="portalAgree"
label="I Agree" label="I Agree"
onTouchTap={props.onToggleDialog.bind(this)} onTouchTap={props.onToggleDialog}
/>, />,
]} ]}
open={props.isOpen} open={props.isOpen}
onRequestClose={props.onToggleDialog.bind(this)} onRequestClose={props.onToggleDialog}
autoScrollBodyContent={true} autoScrollBodyContent={true}
modal={true} modal={true}
> >

View File

@@ -73,7 +73,9 @@ export class TrackTokenConfirmationDialog extends
isAddingTokenToTracked: true, isAddingTokenToTracked: true,
}); });
for (const token of this.props.tokens) { for (const token of this.props.tokens) {
const newTokenEntry = _.assign({}, token); const newTokenEntry = {
...token,
};
newTokenEntry.isTracked = true; newTokenEntry.isTracked = true;
trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry);

View File

@@ -1,7 +1,7 @@
import Dialog from 'material-ui/Dialog'; import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
interface U2fNotSupportedDialogProps { interface U2fNotSupportedDialogProps {
@@ -39,7 +39,7 @@ export function U2fNotSupportedDialog(props: U2fNotSupportedDialogProps) {
<li> <li>
Firefox with{' '} Firefox with{' '}
<a <a
href={constants.FIREFOX_U2F_ADDON} href={constants.URL_FIREFOX_U2F_ADDON}
target="_blank" target="_blank"
style={{textDecoration: 'underline'}} style={{textDecoration: 'underline'}}
> >

View File

@@ -0,0 +1,38 @@
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import {colors} from 'material-ui/styles';
import * as React from 'react';
interface WrappedEthSectionNoticeDialogProps {
isOpen: boolean;
onToggleDialog: () => void;
}
export function WrappedEthSectionNoticeDialog(props: WrappedEthSectionNoticeDialogProps) {
return (
<Dialog
title="Dedicated Wrapped Ether Section"
titleStyle={{fontWeight: 100}}
actions={[
<FlatButton
key="acknowledgeWrapEthSection"
label="Sounds good"
onTouchTap={props.onToggleDialog}
/>,
]}
open={props.isOpen}
onRequestClose={props.onToggleDialog}
autoScrollBodyContent={true}
modal={true}
>
<div className="pt2" style={{color: colors.grey700}}>
<div>
We have recently updated the Wrapped Ether token (WETH) used by 0x Portal.
Don't worry, unwrapping Ether tied to the old Wrapped Ether token can
be done at any time by clicking on the "Wrap ETH" section in the menu
to the left.
</div>
</div>
</Dialog>
);
}

View File

@@ -45,7 +45,7 @@ export class EthWethConversionButton extends
const labelStyle = this.state.isEthConversionHappening ? {fontSize: 10} : {}; const labelStyle = this.state.isEthConversionHappening ? {fontSize: 10} : {};
let callToActionLabel; let callToActionLabel;
let inProgressLabel; let inProgressLabel;
if (this.props.direction === Side.deposit) { if (this.props.direction === Side.Deposit) {
callToActionLabel = 'Wrap'; callToActionLabel = 'Wrap';
inProgressLabel = 'Wrapping...'; inProgressLabel = 'Wrapping...';
} else { } else {
@@ -87,9 +87,9 @@ export class EthWethConversionButton extends
const tokenState = this.props.ethTokenState; const tokenState = this.props.ethTokenState;
let balance = tokenState.balance; let balance = tokenState.balance;
try { try {
if (direction === Side.deposit) { if (direction === Side.Deposit) {
await this.props.blockchain.convertEthToWrappedEthTokensAsync(token.address, value); await this.props.blockchain.convertEthToWrappedEthTokensAsync(token.address, value);
const ethAmount = ZeroEx.toUnitAmount(value, constants.ETH_DECIMAL_PLACES); const ethAmount = ZeroEx.toUnitAmount(value, constants.DECIMAL_PLACES_ETH);
this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount.toString()} ETH to WETH`); this.props.dispatcher.showFlashMessage(`Successfully wrapped ${ethAmount.toString()} ETH to WETH`);
balance = balance.plus(value); balance = balance.plus(value);
} else { } else {
@@ -104,13 +104,13 @@ export class EthWethConversionButton extends
this.props.onConversionSuccessful(); this.props.onConversionSuccessful();
} catch (err) { } catch (err) {
const errMsg = '' + err; const errMsg = '' + err;
if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) { if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
} else if (!_.includes(errMsg, 'User denied transaction')) { } else if (!_.includes(errMsg, 'User denied transaction')) {
utils.consoleLog(`Unexpected error encountered: ${err}`); utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack); utils.consoleLog(err.stack);
await errorReporter.reportAsync(err); await errorReporter.reportAsync(err);
const errorMsg = direction === Side.deposit ? const errorMsg = direction === Side.Deposit ?
'Failed to wrap your ETH. Please try again.' : 'Failed to wrap your ETH. Please try again.' :
'Failed to unwrap your WETH. Please try again.'; 'Failed to unwrap your WETH. Please try again.';
this.props.dispatcher.showFlashMessage(errorMsg); this.props.dispatcher.showFlashMessage(errorMsg);

View File

@@ -2,7 +2,6 @@ import {ZeroEx} from '0x.js';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import Divider from 'material-ui/Divider'; import Divider from 'material-ui/Divider';
import {colors} from 'material-ui/styles';
import { import {
Table, Table,
TableBody, TableBody,
@@ -13,10 +12,12 @@ import {
} from 'material-ui/Table'; } from 'material-ui/Table';
import * as moment from 'moment'; import * as moment from 'moment';
import * as React from 'react'; import * as React from 'react';
import ReactTooltip = require('react-tooltip');
import {Blockchain} from 'ts/blockchain'; import {Blockchain} from 'ts/blockchain';
import {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button'; import {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button';
import {Dispatcher} from 'ts/redux/dispatcher'; import {Dispatcher} from 'ts/redux/dispatcher';
import { import {
EtherscanLinkSuffixes,
OutdatedWrappedEtherByNetworkId, OutdatedWrappedEtherByNetworkId,
Side, Side,
Token, Token,
@@ -24,12 +25,13 @@ import {
TokenState, TokenState,
TokenStateByAddress, TokenStateByAddress,
} from 'ts/types'; } from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs'; import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils';
const PRECISION = 5; const PRECISION = 5;
const DATE_FORMAT = 'D/M/YY'; const DATE_FORMAT = 'D/M/YY';
const LIGHT_GRAY = '#A5A5A5';
const ICON_DIMENSION = 40; const ICON_DIMENSION = 40;
const ETHER_ICON_PATH = '/images/ether.png'; const ETHER_ICON_PATH = '/images/ether.png';
const OUTDATED_WETH_ICON_PATH = '/images/wrapped_eth_gray.png'; const OUTDATED_WETH_ICON_PATH = '/images/wrapped_eth_gray.png';
@@ -83,8 +85,12 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
const tokens = _.values(this.props.tokenByAddress); const tokens = _.values(this.props.tokenByAddress);
const etherToken = _.find(tokens, {symbol: 'WETH'}); const etherToken = _.find(tokens, {symbol: 'WETH'});
const etherTokenState = this.props.tokenStateByAddress[etherToken.address]; const etherTokenState = this.props.tokenStateByAddress[etherToken.address];
const wethBalance = ZeroEx.toUnitAmount(etherTokenState.balance, 18); const wethBalance = ZeroEx.toUnitAmount(etherTokenState.balance, constants.DECIMAL_PLACES_ETH);
const isBidirectional = true; const isBidirectional = true;
const etherscanUrl = utils.getEtherScanLinkIfExists(
etherToken.address, this.props.networkId, EtherscanLinkSuffixes.Address,
);
const tokenLabel = this.renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH);
return ( return (
<div className="clearfix lg-px4 md-px4 sm-px2" style={{minHeight: 600}}> <div className="clearfix lg-px4 md-px4 sm-px2" style={{minHeight: 600}}>
<div className="relative"> <div className="relative">
@@ -92,8 +98,8 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<div className="absolute" style={{top: 0, right: 0}}> <div className="absolute" style={{top: 0, right: 0}}>
<a <a
target="_blank" target="_blank"
href="https://weth.io/" href={constants.URL_WETH_IO}
style={{color: LIGHT_GRAY}} style={{color: colors.grey}}
> >
<div className="flex"> <div className="flex">
<div>About Wrapped ETH</div> <div>About Wrapped ETH</div>
@@ -131,8 +137,11 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
style={{width: ICON_DIMENSION, height: ICON_DIMENSION}} style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
src={ETHER_ICON_PATH} src={ETHER_ICON_PATH}
/> />
<div className="mt2 ml2 sm-hide xs-hide"> <div
Ether className="ml2 sm-hide xs-hide"
style={{marginTop: 12}}
>
ETH
</div> </div>
</div> </div>
</TableRowColumn> </TableRowColumn>
@@ -142,7 +151,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<TableRowColumn> <TableRowColumn>
<EthWethConversionButton <EthWethConversionButton
isOutdatedWrappedEther={false} isOutdatedWrappedEther={false}
direction={Side.deposit} direction={Side.Deposit}
ethToken={etherToken} ethToken={etherToken}
ethTokenState={etherTokenState} ethTokenState={etherTokenState}
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
@@ -153,15 +162,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</TableRow> </TableRow>
<TableRow key="WETH"> <TableRow key="WETH">
<TableRowColumn className="py1"> <TableRowColumn className="py1">
<div className="flex"> {this.renderTokenLink(tokenLabel, etherscanUrl)}
<img
style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
src={constants.iconUrlBySymbol.WETH}
/>
<div className="mt2 ml2 sm-hide xs-hide">
Wrapped Ether
</div>
</div>
</TableRowColumn> </TableRowColumn>
<TableRowColumn> <TableRowColumn>
{wethBalance.toFixed(PRECISION)} WETH {wethBalance.toFixed(PRECISION)} WETH
@@ -169,7 +170,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<TableRowColumn> <TableRowColumn>
<EthWethConversionButton <EthWethConversionButton
isOutdatedWrappedEther={false} isOutdatedWrappedEther={false}
direction={Side.receive} direction={Side.Receive}
ethToken={etherToken} ethToken={etherToken}
ethTokenState={etherTokenState} ethTokenState={etherTokenState}
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
@@ -242,10 +243,13 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
); );
} }
private renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) { private renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) {
const rows = _.map(configs.outdatedWrappedEthers, const rows = _.map(configs.OUTDATED_WRAPPED_ETHERS,
(outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => { (outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => {
const outdatedWETH = outdatedWETHByNetworkId[this.props.networkId]; const outdatedWETHIfExists = outdatedWETHByNetworkId[this.props.networkId];
const timestampMsRange = outdatedWETH.timestampMsRange; if (_.isUndefined(outdatedWETHIfExists)) {
return null; // noop
}
const timestampMsRange = outdatedWETHIfExists.timestampMsRange;
let dateRange: string; let dateRange: string;
if (!_.isUndefined(timestampMsRange)) { if (!_.isUndefined(timestampMsRange)) {
const startMoment = moment(timestampMsRange.startTimestampMs); const startMoment = moment(timestampMsRange.startTimestampMs);
@@ -256,26 +260,26 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
} }
const outdatedEtherToken = { const outdatedEtherToken = {
...etherToken, ...etherToken,
address: outdatedWETH.address, address: outdatedWETHIfExists.address,
}; };
const isStateLoaded = this.state.outdatedWETHAddressToIsStateLoaded[outdatedWETH.address]; const isStateLoaded = this.state.outdatedWETHAddressToIsStateLoaded[outdatedWETHIfExists.address];
const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETH.address]; const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETHIfExists.address];
const balanceInEthIfExists = isStateLoaded ? const balanceInEthIfExists = isStateLoaded ?
ZeroEx.toUnitAmount(outdatedEtherTokenState.balance, 18).toFixed(PRECISION) : ZeroEx.toUnitAmount(
outdatedEtherTokenState.balance, constants.DECIMAL_PLACES_ETH,
).toFixed(PRECISION) :
undefined; undefined;
const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind(this, outdatedWETH.address); const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind(
this, outdatedWETHIfExists.address,
);
const etherscanUrl = utils.getEtherScanLinkIfExists(
outdatedWETHIfExists.address, this.props.networkId, EtherscanLinkSuffixes.Address,
);
const tokenLabel = this.renderToken(dateRange, outdatedEtherToken.address, OUTDATED_WETH_ICON_PATH);
return ( return (
<TableRow key={`weth-${outdatedWETH.address}`}> <TableRow key={`weth-${outdatedWETHIfExists.address}`}>
<TableRowColumn className="py1"> <TableRowColumn className="py1">
<div className="flex"> {this.renderTokenLink(tokenLabel, etherscanUrl)}
<img
style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
src={OUTDATED_WETH_ICON_PATH}
/>
<div className="mt2 ml2 sm-hide xs-hide">
{dateRange}
</div>
</div>
</TableRowColumn> </TableRowColumn>
<TableRowColumn> <TableRowColumn>
{isStateLoaded ? {isStateLoaded ?
@@ -287,7 +291,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<EthWethConversionButton <EthWethConversionButton
isDisabled={!isStateLoaded} isDisabled={!isStateLoaded}
isOutdatedWrappedEther={true} isOutdatedWrappedEther={true}
direction={Side.receive} direction={Side.Receive}
ethToken={outdatedEtherToken} ethToken={outdatedEtherToken}
ethTokenState={outdatedEtherTokenState} ethTokenState={outdatedEtherTokenState}
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
@@ -301,6 +305,41 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
}); });
return rows; return rows;
} }
private renderTokenLink(tokenLabel: React.ReactNode, etherscanUrl: string) {
return (
<span>
{_.isUndefined(etherscanUrl) ?
tokenLabel :
<a href={etherscanUrl} target="_blank" style={{textDecoration: 'none'}}>
{tokenLabel}
</a>
}
</span>
);
}
private renderToken(name: string, address: string, imgPath: string) {
const tooltipId = `tooltip-${address}`;
return (
<div className="flex">
<img
style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
src={imgPath}
/>
<div
className="ml2 sm-hide xs-hide"
style={{marginTop: 12}}
>
<span
data-tip={true}
data-for={tooltipId}
>
{name}
</span>
<ReactTooltip id={tooltipId}>{address}</ReactTooltip>
</div>
</div>
);
}
private async onOutdatedConversionSuccessfulAsync(outdatedWETHAddress: string) { private async onOutdatedConversionSuccessfulAsync(outdatedWETHAddress: string) {
this.setState({ this.setState({
outdatedWETHAddressToIsStateLoaded: { outdatedWETHAddressToIsStateLoaded: {
@@ -345,9 +384,15 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
}); });
} }
private getOutdatedWETHAddresses(): string[] { private getOutdatedWETHAddresses(): string[] {
const outdatedWETHAddresses = _.map(configs.outdatedWrappedEthers, outdatedWrappedEther => { const outdatedWETHAddresses = _.compact(_.map(configs.OUTDATED_WRAPPED_ETHERS,
return outdatedWrappedEther[this.props.networkId].address; outdatedWrappedEtherByNetwork => {
}); const outdatedWrappedEtherIfExists = outdatedWrappedEtherByNetwork[this.props.networkId];
if (_.isUndefined(outdatedWrappedEtherIfExists)) {
return undefined;
}
const address = outdatedWrappedEtherIfExists.address;
return address;
}));
return outdatedWETHAddresses; return outdatedWETHAddresses;
} }
} // tslint:disable:max-file-line-count } // tslint:disable:max-file-line-count

View File

@@ -28,12 +28,11 @@ import {
TokenStateByAddress, TokenStateByAddress,
WebsitePaths, WebsitePaths,
} from 'ts/types'; } from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {errorReporter} from 'ts/utils/error_reporter'; import {errorReporter} from 'ts/utils/error_reporter';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
const CUSTOM_LIGHT_GRAY = '#BBBBBB';
interface FillOrderProps { interface FillOrderProps {
blockchain: Blockchain; blockchain: Blockchain;
blockchainErr: BlockchainErrs; blockchainErr: BlockchainErrs;
@@ -222,7 +221,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
<div className="clearfix pb2" style={{width: '100%'}}> <div className="clearfix pb2" style={{width: '100%'}}>
<div className="inline left">Order details</div> <div className="inline left">Order details</div>
<div className="inline right" style={{minWidth: 208}}> <div className="inline right" style={{minWidth: 208}}>
<div className="col col-4 pl2" style={{color: '#BEBEBE'}}> <div className="col col-4 pl2" style={{color: colors.grey}}>
Maker: Maker:
</div> </div>
<div className="col col-2 pr1"> <div className="col col-2 pr1">
@@ -259,22 +258,20 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
</div> </div>
</div> </div>
{!isUserMaker && {!isUserMaker &&
<div className="clearfix mx-auto" style={{width: 315, height: 108}}> <div className="clearfix mx-auto relative" style={{width: 235, height: 108}}>
<div className="col col-7" style={{maxWidth: 235}}> <TokenAmountInput
<TokenAmountInput label="Fill amount"
label="Fill amount" onChange={this.onFillAmountChange.bind(this)}
onChange={this.onFillAmountChange.bind(this)} shouldShowIncompleteErrs={false}
shouldShowIncompleteErrs={false} token={fillToken}
token={fillToken} tokenState={fillTokenState}
tokenState={fillTokenState} amount={fillAssetToken.amount}
amount={fillAssetToken.amount} shouldCheckBalance={true}
shouldCheckBalance={true} shouldCheckAllowance={true}
shouldCheckAllowance={true} />
/>
</div>
<div <div
className="col col-5 pl1" className="absolute sm-hide xs-hide"
style={{color: CUSTOM_LIGHT_GRAY, paddingTop: 39}} style={{color: colors.grey400, right: -247, top: 39, width: 242}}
> >
= {accounting.formatNumber(orderReceiveAmount, 6)} {makerToken.symbol} = {accounting.formatNumber(orderReceiveAmount, 6)} {makerToken.symbol}
</div> </div>
@@ -324,7 +321,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
Order successfully filled. See the trade details in your{' '} Order successfully filled. See the trade details in your{' '}
<Link <Link
to={`${WebsitePaths.Portal}/trades`} to={`${WebsitePaths.Portal}/trades`}
style={{color: 'white'}} style={{color: colors.white}}
> >
trade history trade history
</Link> </Link>
@@ -381,22 +378,24 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
const isUnseenMakerToken = _.isUndefined(makerTokenIfExists); const isUnseenMakerToken = _.isUndefined(makerTokenIfExists);
const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && makerTokenIfExists.isTracked; const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && makerTokenIfExists.isTracked;
if (isUnseenMakerToken) { if (isUnseenMakerToken) {
tokensToTrack.push(_.assign({}, this.state.parsedOrder.maker.token, { tokensToTrack.push({
...this.state.parsedOrder.maker.token,
iconUrl: undefined, iconUrl: undefined,
isTracked: false, isTracked: false,
isRegistered: false, isRegistered: false,
})); });
} else if (!isMakerTokenTracked) { } else if (!isMakerTokenTracked) {
tokensToTrack.push(makerTokenIfExists); tokensToTrack.push(makerTokenIfExists);
} }
const isUnseenTakerToken = _.isUndefined(takerTokenIfExists); const isUnseenTakerToken = _.isUndefined(takerTokenIfExists);
const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && takerTokenIfExists.isTracked; const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && takerTokenIfExists.isTracked;
if (isUnseenTakerToken) { if (isUnseenTakerToken) {
tokensToTrack.push(_.assign({}, this.state.parsedOrder.taker.token, { tokensToTrack.push({
...this.state.parsedOrder.taker.token,
iconUrl: undefined, iconUrl: undefined,
isTracked: false, isTracked: false,
isRegistered: false, isRegistered: false,
})); });
} else if (!isTakerTokenTracked) { } else if (!isTakerTokenTracked) {
tokensToTrack.push(takerTokenIfExists); tokensToTrack.push(takerTokenIfExists);
} }

View File

@@ -24,11 +24,11 @@ export class FillOrderJSON extends React.Component<FillOrderJSONProps, FillOrder
const tokenAddresses = _.keys(this.props.tokenByAddress); const tokenAddresses = _.keys(this.props.tokenByAddress);
const exchangeContract = this.props.blockchain.getExchangeContractAddressIfExists(); const exchangeContract = this.props.blockchain.getExchangeContractAddressIfExists();
const hintSideToAssetToken = { const hintSideToAssetToken = {
[Side.deposit]: { [Side.Deposit]: {
amount: new BigNumber(35), amount: new BigNumber(35),
address: tokenAddresses[0], address: tokenAddresses[0],
}, },
[Side.receive]: { [Side.Receive]: {
amount: new BigNumber(89), amount: new BigNumber(89),
address: tokenAddresses[1], address: tokenAddresses[1],
}, },
@@ -41,9 +41,10 @@ export class FillOrderJSON extends React.Component<FillOrderJSONProps, FillOrder
v: 27, v: 27,
}; };
const hintSalt = ZeroEx.generatePseudoRandomSalt(); const hintSalt = ZeroEx.generatePseudoRandomSalt();
const feeRecipient = constants.NULL_ADDRESS;
const hintOrder = utils.generateOrder(this.props.networkId, exchangeContract, hintSideToAssetToken, const hintOrder = utils.generateOrder(this.props.networkId, exchangeContract, hintSideToAssetToken,
hintOrderExpiryTimestamp, '', '', constants.MAKER_FEE, hintOrderExpiryTimestamp, '', '', constants.MAKER_FEE,
constants.TAKER_FEE, constants.FEE_RECIPIENT_ADDRESS, constants.TAKER_FEE, feeRecipient,
hintSignatureData, this.props.tokenByAddress, hintSalt); hintSignatureData, this.props.tokenByAddress, hintSalt);
const hintOrderJSON = `${JSON.stringify(hintOrder, null, '\t').substring(0, 500)}...`; const hintOrderJSON = `${JSON.stringify(hintOrder, null, '\t').substring(0, 500)}...`;
return ( return (

View File

@@ -1,7 +1,7 @@
import Dialog from 'material-ui/Dialog'; import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
interface FillWarningDialogProps { interface FillWarningDialogProps {
isOpen: boolean; isOpen: boolean;

View File

@@ -3,6 +3,7 @@ import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as React from 'react'; import * as React from 'react';
import {Token} from 'ts/types'; import {Token} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
interface TokenSendCompletedProps { interface TokenSendCompletedProps {
@@ -19,7 +20,7 @@ export class TokenSendCompleted extends React.Component<TokenSendCompletedProps,
const etherScanLink = !_.isUndefined(this.props.etherScanLinkIfExists) && const etherScanLink = !_.isUndefined(this.props.etherScanLinkIfExists) &&
( (
<a <a
style={{color: 'white'}} style={{color: colors.white}}
href={`${this.props.etherScanLinkIfExists}`} href={`${this.props.etherScanLinkIfExists}`}
target="_blank" target="_blank"
> >

View File

@@ -1,5 +1,6 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
interface TransactionSubmittedProps { interface TransactionSubmittedProps {
etherScanLinkIfExists?: string; etherScanLinkIfExists?: string;
@@ -16,7 +17,7 @@ export class TransactionSubmitted extends React.Component<TransactionSubmittedPr
<div> <div>
Transaction submitted to the network:{' '} Transaction submitted to the network:{' '}
<a <a
style={{color: 'white'}} style={{color: colors.white}}
href={`${this.props.etherScanLinkIfExists}`} href={`${this.props.etherScanLinkIfExists}`}
target="_blank" target="_blank"
> >

View File

@@ -4,6 +4,7 @@ import {
Link, Link,
} from 'react-router-dom'; } from 'react-router-dom';
import {WebsitePaths} from 'ts/types'; import {WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
interface MenuItemsBySection { interface MenuItemsBySection {
@@ -24,9 +25,6 @@ enum Sections {
} }
const ICON_DIMENSION = 16; const ICON_DIMENSION = 16;
const CUSTOM_DARK_GRAY = '#393939';
const CUSTOM_LIGHT_GRAY = '#CACACA';
const CUSTOM_LIGHTEST_GRAY = '#9E9E9E';
const menuItemsBySection: MenuItemsBySection = { const menuItemsBySection: MenuItemsBySection = {
Documentation: [ Documentation: [
{ {
@@ -59,25 +57,25 @@ const menuItemsBySection: MenuItemsBySection = {
{ {
title: 'Rocket.chat', title: 'Rocket.chat',
isExternal: true, isExternal: true,
path: constants.ZEROEX_CHAT_URL, path: constants.URL_ZEROEX_CHAT,
fileName: 'rocketchat.png', fileName: 'rocketchat.png',
}, },
{ {
title: 'Blog', title: 'Blog',
isExternal: true, isExternal: true,
path: constants.BLOG_URL, path: constants.URL_BLOG,
fileName: 'medium.png', fileName: 'medium.png',
}, },
{ {
title: 'Twitter', title: 'Twitter',
isExternal: true, isExternal: true,
path: constants.TWITTER_URL, path: constants.URL_TWITTER,
fileName: 'twitter.png', fileName: 'twitter.png',
}, },
{ {
title: 'Reddit', title: 'Reddit',
isExternal: true, isExternal: true,
path: constants.REDDIT_URL, path: constants.URL_REDDIT,
fileName: 'reddit.png', fileName: 'reddit.png',
}, },
], ],
@@ -90,7 +88,7 @@ const menuItemsBySection: MenuItemsBySection = {
{ {
title: 'Careers', title: 'Careers',
isExternal: true, isExternal: true,
path: constants.ANGELLIST_URL, path: constants.URL_ANGELLIST,
}, },
{ {
title: 'Contact', title: 'Contact',
@@ -100,7 +98,7 @@ const menuItemsBySection: MenuItemsBySection = {
], ],
}; };
const linkStyle = { const linkStyle = {
color: 'white', color: colors.white,
cursor: 'pointer', cursor: 'pointer',
}; };
@@ -111,23 +109,23 @@ const titleToIcon: {[title: string]: string} = {
'Reddit': 'reddit.png', 'Reddit': 'reddit.png',
}; };
export interface FooterProps { export interface FooterProps {}
location: Location;
}
interface FooterState {} interface FooterState {}
export class Footer extends React.Component<FooterProps, FooterState> { export class Footer extends React.Component<FooterProps, FooterState> {
public render() { public render() {
return ( return (
<div className="relative pb4 pt2" style={{backgroundColor: CUSTOM_DARK_GRAY}}> <div className="relative pb4 pt2" style={{backgroundColor: colors.darkerGrey}}>
<div className="mx-auto max-width-4 md-px2 lg-px0 py4 clearfix" style={{color: 'white'}}> <div className="mx-auto max-width-4 md-px2 lg-px0 py4 clearfix" style={{color: colors.white}}>
<div className="col lg-col-4 md-col-4 col-12 left"> <div className="col lg-col-4 md-col-4 col-12 left">
<div className="sm-mx-auto" style={{width: 148}}> <div className="sm-mx-auto" style={{width: 148}}>
<div> <div>
<img src="/images/protocol_logo_white.png" height="30" /> <img src="/images/protocol_logo_white.png" height="30" />
</div> </div>
<div style={{fontSize: 11, color: CUSTOM_LIGHTEST_GRAY, paddingLeft: 37, paddingTop: 2}}> <div
style={{fontSize: 11, color: colors.grey, paddingLeft: 37, paddingTop: 2}}
>
© ZeroEx, Intl. © ZeroEx, Intl.
</div> </div>
</div> </div>
@@ -211,7 +209,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
private renderHeader(title: string) { private renderHeader(title: string) {
const headerStyle = { const headerStyle = {
textTransform: 'uppercase', textTransform: 'uppercase',
color: CUSTOM_LIGHT_GRAY, color: colors.grey400,
letterSpacing: 2, letterSpacing: 2,
fontFamily: 'Roboto Mono', fontFamily: 'Roboto Mono',
fontSize: 13, fontSize: 13,

View File

@@ -244,7 +244,9 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
}); });
const tokenAddress = this.state.chosenTrackTokenAddress; const tokenAddress = this.state.chosenTrackTokenAddress;
const token = this.props.tokenByAddress[tokenAddress]; const token = this.props.tokenByAddress[tokenAddress];
const newTokenEntry = _.assign({}, token); const newTokenEntry = {
...token,
};
newTokenEntry.isTracked = true; newTokenEntry.isTracked = true;
trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry);

View File

@@ -3,7 +3,6 @@ import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog'; import Dialog from 'material-ui/Dialog';
import Divider from 'material-ui/Divider'; import Divider from 'material-ui/Divider';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Blockchain} from 'ts/blockchain'; import {Blockchain} from 'ts/blockchain';
import {ExpirationInput} from 'ts/components/inputs/expiration_input'; import {ExpirationInput} from 'ts/components/inputs/expiration_input';
@@ -30,6 +29,7 @@ import {
TokenByAddress, TokenByAddress,
TokenStateByAddress, TokenStateByAddress,
} from 'ts/types'; } from 'ts/types';
import {colors} from 'ts/utils/colors';
import {errorReporter} from 'ts/utils/error_reporter'; import {errorReporter} from 'ts/utils/error_reporter';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
@@ -78,10 +78,10 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
} }
public render() { public render() {
const dispatcher = this.props.dispatcher; const dispatcher = this.props.dispatcher;
const depositTokenAddress = this.props.sideToAssetToken[Side.deposit].address; const depositTokenAddress = this.props.sideToAssetToken[Side.Deposit].address;
const depositToken = this.props.tokenByAddress[depositTokenAddress]; const depositToken = this.props.tokenByAddress[depositTokenAddress];
const depositTokenState = this.props.tokenStateByAddress[depositTokenAddress]; const depositTokenState = this.props.tokenStateByAddress[depositTokenAddress];
const receiveTokenAddress = this.props.sideToAssetToken[Side.receive].address; const receiveTokenAddress = this.props.sideToAssetToken[Side.Receive].address;
const receiveToken = this.props.tokenByAddress[receiveTokenAddress]; const receiveToken = this.props.tokenByAddress[receiveTokenAddress];
const receiveTokenState = this.props.tokenStateByAddress[receiveTokenAddress]; const receiveTokenState = this.props.tokenStateByAddress[receiveTokenAddress];
const takerExplanation = 'If a taker is specified, only they are<br> \ const takerExplanation = 'If a taker is specified, only they are<br> \
@@ -102,9 +102,9 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
blockchainErr={this.props.blockchainErr} blockchainErr={this.props.blockchainErr}
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
label="Selling" label="Selling"
side={Side.deposit} side={Side.Deposit}
networkId={this.props.networkId} networkId={this.props.networkId}
assetToken={this.props.sideToAssetToken[Side.deposit]} assetToken={this.props.sideToAssetToken[Side.Deposit]}
updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)} updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)}
tokenByAddress={this.props.tokenByAddress} tokenByAddress={this.props.tokenByAddress}
/> />
@@ -112,8 +112,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
label="Sell amount" label="Sell amount"
token={depositToken} token={depositToken}
tokenState={depositTokenState} tokenState={depositTokenState}
amount={this.props.sideToAssetToken[Side.deposit].amount} amount={this.props.sideToAssetToken[Side.Deposit].amount}
onChange={this.onTokenAmountChange.bind(this, depositToken, Side.deposit)} onChange={this.onTokenAmountChange.bind(this, depositToken, Side.Deposit)}
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs} shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={true} shouldCheckBalance={true}
shouldCheckAllowance={true} shouldCheckAllowance={true}
@@ -133,9 +133,9 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
blockchainErr={this.props.blockchainErr} blockchainErr={this.props.blockchainErr}
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
label="Buying" label="Buying"
side={Side.receive} side={Side.Receive}
networkId={this.props.networkId} networkId={this.props.networkId}
assetToken={this.props.sideToAssetToken[Side.receive]} assetToken={this.props.sideToAssetToken[Side.Receive]}
updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)} updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)}
tokenByAddress={this.props.tokenByAddress} tokenByAddress={this.props.tokenByAddress}
/> />
@@ -143,8 +143,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
label="Receive amount" label="Receive amount"
token={receiveToken} token={receiveToken}
tokenState={receiveTokenState} tokenState={receiveTokenState}
amount={this.props.sideToAssetToken[Side.receive].amount} amount={this.props.sideToAssetToken[Side.Receive].amount}
onChange={this.onTokenAmountChange.bind(this, receiveToken, Side.receive)} onChange={this.onTokenAmountChange.bind(this, receiveToken, Side.Receive)}
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs} shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={false} shouldCheckBalance={false}
shouldCheckAllowance={false} shouldCheckAllowance={false}
@@ -154,7 +154,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
</div> </div>
<div className="pt1 sm-pb2 lg-px4 md-px4"> <div className="pt1 sm-pb2 lg-px4 md-px4">
<div className="lg-px3 md-px3"> <div className="lg-px3 md-px3">
<div style={{fontSize: 12, color: colors.grey500}}>Expiration</div> <div style={{fontSize: 12, color: colors.grey}}>Expiration</div>
<ExpirationInput <ExpirationInput
orderExpiryTimestamp={this.props.orderExpiryTimestamp} orderExpiryTimestamp={this.props.orderExpiryTimestamp}
updateOrderExpiry={dispatcher.updateOrderExpiry.bind(dispatcher)} updateOrderExpiry={dispatcher.updateOrderExpiry.bind(dispatcher)}
@@ -235,16 +235,16 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
}); });
} }
private async onSignClickedAsync(): Promise<boolean> { private async onSignClickedAsync(): Promise<boolean> {
if (this.props.blockchainErr !== '') { if (this.props.blockchainErr !== BlockchainErrs.NoError) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return false; return false;
} }
// Check if all required inputs were supplied // Check if all required inputs were supplied
const debitToken = this.props.sideToAssetToken[Side.deposit]; const debitToken = this.props.sideToAssetToken[Side.Deposit];
const debitBalance = this.props.tokenStateByAddress[debitToken.address].balance; const debitBalance = this.props.tokenStateByAddress[debitToken.address].balance;
const debitAllowance = this.props.tokenStateByAddress[debitToken.address].allowance; const debitAllowance = this.props.tokenStateByAddress[debitToken.address].allowance;
const receiveAmount = this.props.sideToAssetToken[Side.receive].amount; const receiveAmount = this.props.sideToAssetToken[Side.Receive].amount;
if (!_.isUndefined(debitToken.amount) && !_.isUndefined(receiveAmount) && if (!_.isUndefined(debitToken.amount) && !_.isUndefined(receiveAmount) &&
debitToken.amount.gt(0) && receiveAmount.gt(0) && debitToken.amount.gt(0) && receiveAmount.gt(0) &&
this.props.userAddress !== '' && this.props.userAddress !== '' &&

View File

@@ -1,6 +1,5 @@
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import TextField from 'material-ui/TextField'; import TextField from 'material-ui/TextField';
import * as React from 'react'; import * as React from 'react';
import {Blockchain} from 'ts/blockchain'; import {Blockchain} from 'ts/blockchain';
@@ -9,6 +8,7 @@ import {Alert} from 'ts/components/ui/alert';
import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button'; import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button';
import {RequiredLabel} from 'ts/components/ui/required_label'; import {RequiredLabel} from 'ts/components/ui/required_label';
import {AlertTypes, Token, TokenByAddress, TokenState} from 'ts/types'; import {AlertTypes, Token, TokenByAddress, TokenState} from 'ts/types';
import {colors} from 'ts/utils/colors';
interface NewTokenFormProps { interface NewTokenFormProps {
blockchain: Blockchain; blockchain: Blockchain;
@@ -49,7 +49,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
<div> <div>
<TextField <TextField
floatingLabelFixed={true} floatingLabelFixed={true}
floatingLabelStyle={{color: colors.grey500}} floatingLabelStyle={{color: colors.grey}}
floatingLabelText={<RequiredLabel label="Name" />} floatingLabelText={<RequiredLabel label="Name" />}
value={this.state.name} value={this.state.name}
errorText={this.state.nameErrText} errorText={this.state.nameErrText}
@@ -59,7 +59,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
<div> <div>
<TextField <TextField
floatingLabelFixed={true} floatingLabelFixed={true}
floatingLabelStyle={{color: colors.grey500}} floatingLabelStyle={{color: colors.grey}}
floatingLabelText={<RequiredLabel label="Symbol" />} floatingLabelText={<RequiredLabel label="Symbol" />}
value={this.state.symbol} value={this.state.symbol}
errorText={this.state.symbolErrText} errorText={this.state.symbolErrText}
@@ -78,7 +78,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
<div> <div>
<TextField <TextField
floatingLabelFixed={true} floatingLabelFixed={true}
floatingLabelStyle={{color: colors.grey500}} floatingLabelStyle={{color: colors.grey}}
floatingLabelText={<RequiredLabel label="Decimals" />} floatingLabelText={<RequiredLabel label="Decimals" />}
value={this.state.decimals} value={this.state.decimals}
errorText={this.state.decimalsErrText} errorText={this.state.decimalsErrText}

View File

@@ -1,9 +1,9 @@
import {addressUtils} from '@0xproject/utils'; import {addressUtils} from '@0xproject/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import TextField from 'material-ui/TextField'; import TextField from 'material-ui/TextField';
import * as React from 'react'; import * as React from 'react';
import {RequiredLabel} from 'ts/components/ui/required_label'; import {RequiredLabel} from 'ts/components/ui/required_label';
import {colors} from 'ts/utils/colors';
interface AddressInputProps { interface AddressInputProps {
disabled?: boolean; disabled?: boolean;
@@ -50,7 +50,7 @@ export class AddressInput extends React.Component<AddressInputProps, AddressInpu
fullWidth={true} fullWidth={true}
hintText={hintText} hintText={hintText}
floatingLabelFixed={true} floatingLabelFixed={true}
floatingLabelStyle={{color: colors.grey500, display: labelDisplay}} floatingLabelStyle={{color: colors.grey, display: labelDisplay}}
floatingLabelText={label} floatingLabelText={label}
errorText={this.state.errMsg} errorText={this.state.errMsg}
value={this.state.address} value={this.state.address}

View File

@@ -1,11 +1,11 @@
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import TextField from 'material-ui/TextField'; import TextField from 'material-ui/TextField';
import * as React from 'react'; import * as React from 'react';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import {RequiredLabel} from 'ts/components/ui/required_label'; import {RequiredLabel} from 'ts/components/ui/required_label';
import {InputErrMsg, ValidatedBigNumberCallback, WebsitePaths} from 'ts/types'; import {InputErrMsg, ValidatedBigNumberCallback, WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
interface BalanceBoundedInputProps { interface BalanceBoundedInputProps {
@@ -83,7 +83,7 @@ export class BalanceBoundedInput extends
fullWidth={true} fullWidth={true}
floatingLabelText={label} floatingLabelText={label}
floatingLabelFixed={true} floatingLabelFixed={true}
floatingLabelStyle={{color: colors.grey500, width: 206}} floatingLabelStyle={{color: colors.grey, width: 206}}
errorText={errorText} errorText={errorText}
value={this.state.amountString} value={this.state.amountString}
hintText={<span style={{textTransform: 'capitalize'}}>amount</span>} hintText={<span style={{textTransform: 'capitalize'}}>amount</span>}
@@ -133,7 +133,7 @@ export class BalanceBoundedInput extends
const increaseBalanceText = 'Increase balance'; const increaseBalanceText = 'Increase balance';
const linkStyle = { const linkStyle = {
cursor: 'pointer', cursor: 'pointer',
color: colors.grey900, color: colors.darkestGrey,
textDecoration: 'underline', textDecoration: 'underline',
display: 'inline', display: 'inline',
}; };

View File

@@ -22,7 +22,7 @@ interface EthAmountInputState {}
export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmountInputState> { export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmountInputState> {
public render() { public render() {
const amount = this.props.amount ? const amount = this.props.amount ?
ZeroEx.toUnitAmount(this.props.amount, constants.ETH_DECIMAL_PLACES) : ZeroEx.toUnitAmount(this.props.amount, constants.DECIMAL_PLACES_ETH) :
undefined; undefined;
return ( return (
<div className="flex overflow-hidden" style={{height: 63}}> <div className="flex overflow-hidden" style={{height: 63}}>
@@ -45,7 +45,7 @@ export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmou
private onChange(isValid: boolean, amount?: BigNumber) { private onChange(isValid: boolean, amount?: BigNumber) {
const baseUnitAmountIfExists = _.isUndefined(amount) ? const baseUnitAmountIfExists = _.isUndefined(amount) ?
undefined : undefined :
ZeroEx.toBaseUnitAmount(amount, constants.ETH_DECIMAL_PLACES); ZeroEx.toBaseUnitAmount(amount, constants.DECIMAL_PLACES_ETH);
this.props.onChange(isValid, baseUnitAmountIfExists); this.props.onChange(isValid, baseUnitAmountIfExists);
} }
} }

View File

@@ -1,11 +1,11 @@
import {ZeroEx} from '0x.js'; import {ZeroEx} from '0x.js';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import {BalanceBoundedInput} from 'ts/components/inputs/balance_bounded_input'; import {BalanceBoundedInput} from 'ts/components/inputs/balance_bounded_input';
import {InputErrMsg, Token, TokenState, ValidatedBigNumberCallback, WebsitePaths} from 'ts/types'; import {InputErrMsg, Token, TokenState, ValidatedBigNumberCallback, WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
interface TokenAmountInputProps { interface TokenAmountInputProps {
token: Token; token: Token;
@@ -59,7 +59,7 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok
Insufficient allowance.{' '} Insufficient allowance.{' '}
<Link <Link
to={`${WebsitePaths.Portal}/balances`} to={`${WebsitePaths.Portal}/balances`}
style={{cursor: 'pointer', color: colors.grey900}} style={{cursor: 'pointer', color: colors.darkestGrey}}
> >
Set allowance Set allowance
</Link> </Link>

View File

@@ -1,6 +1,5 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import Paper from 'material-ui/Paper'; import Paper from 'material-ui/Paper';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Blockchain} from 'ts/blockchain'; import {Blockchain} from 'ts/blockchain';
import {AssetPicker} from 'ts/components/generate_order/asset_picker'; import {AssetPicker} from 'ts/components/generate_order/asset_picker';
@@ -8,6 +7,7 @@ import {InputLabel} from 'ts/components/ui/input_label';
import {TokenIcon} from 'ts/components/ui/token_icon'; import {TokenIcon} from 'ts/components/ui/token_icon';
import {Dispatcher} from 'ts/redux/dispatcher'; import {Dispatcher} from 'ts/redux/dispatcher';
import {AssetToken, BlockchainErrs, Side, Token, TokenByAddress} from 'ts/types'; import {AssetToken, BlockchainErrs, Side, Token, TokenByAddress} from 'ts/types';
import {colors} from 'ts/utils/colors';
const TOKEN_ICON_DIMENSION = 80; const TOKEN_ICON_DIMENSION = 80;
@@ -62,7 +62,7 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState
> >
<TokenIcon token={token} diameter={TOKEN_ICON_DIMENSION} /> <TokenIcon token={token} diameter={TOKEN_ICON_DIMENSION} />
</div> </div>
<div className="py1 center" style={{color: colors.grey500}}> <div className="py1 center" style={{color: colors.grey}}>
{token.name} {token.name}
</div> </div>
</Paper> </Paper>
@@ -95,7 +95,7 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState
}); });
} }
private onAssetClicked() { private onAssetClicked() {
if (this.props.blockchainErr !== '') { if (this.props.blockchainErr !== BlockchainErrs.NoError) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return; return;
} }

View File

@@ -1,6 +1,6 @@
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import {Paper} from 'material-ui/Paper'; import Paper from 'material-ui/Paper';
import TextField from 'material-ui/TextField'; import TextField from 'material-ui/TextField';
import * as React from 'react'; import * as React from 'react';
import {CopyIcon} from 'ts/components/ui/copy_icon'; import {CopyIcon} from 'ts/components/ui/copy_icon';
@@ -137,9 +137,8 @@ You can see and fill it here: ${this.state.shareLink}`);
} }
private async generateShareLinkAsync(): Promise<string> { private async generateShareLinkAsync(): Promise<string> {
const longUrl = encodeURIComponent(this.getOrderUrl()); const longUrl = encodeURIComponent(this.getOrderUrl());
const bitlyRequestUrl = constants.BITLY_ENDPOINT + '/v3/shorten?' + const bitlyRequestUrl =
'access_token=' + constants.BITLY_ACCESS_TOKEN + `${constants.URL_BITLY_API}/v3/shorten?access_token=${configs.BITLY_ACCESS_TOKEN}&longUrl=${longUrl}`;
'&longUrl=' + longUrl;
const response = await fetch(bitlyRequestUrl); const response = await fetch(bitlyRequestUrl);
const responseBody = await response.text(); const responseBody = await response.text();
const bodyObj = JSON.parse(responseBody); const bodyObj = JSON.parse(responseBody);

View File

@@ -1,13 +1,13 @@
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import Paper from 'material-ui/Paper'; import Paper from 'material-ui/Paper';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import * as DocumentTitle from 'react-document-title'; import * as DocumentTitle from 'react-document-title';
import {Route, Switch} from 'react-router-dom'; import {Route, Switch} from 'react-router-dom';
import {Blockchain} from 'ts/blockchain'; import {Blockchain} from 'ts/blockchain';
import {BlockchainErrDialog} from 'ts/components/dialogs/blockchain_err_dialog'; import {BlockchainErrDialog} from 'ts/components/dialogs/blockchain_err_dialog';
import {PortalDisclaimerDialog} from 'ts/components/dialogs/portal_disclaimer_dialog'; import {PortalDisclaimerDialog} from 'ts/components/dialogs/portal_disclaimer_dialog';
import {WrappedEthSectionNoticeDialog} from 'ts/components/dialogs/wrapped_eth_section_notice_dialog';
import {EthWrappers} from 'ts/components/eth_wrappers'; import {EthWrappers} from 'ts/components/eth_wrappers';
import {FillOrder} from 'ts/components/fill_order'; import {FillOrder} from 'ts/components/fill_order';
import {Footer} from 'ts/components/footer'; import {Footer} from 'ts/components/footer';
@@ -32,6 +32,7 @@ import {
TokenStateByAddress, TokenStateByAddress,
WebsitePaths, WebsitePaths,
} from 'ts/types'; } from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs'; import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
@@ -63,22 +64,39 @@ interface PortalAllState {
prevNetworkId: number; prevNetworkId: number;
prevNodeVersion: string; prevNodeVersion: string;
prevUserAddress: string; prevUserAddress: string;
hasAcceptedDisclaimer: boolean; prevPathname: string;
isDisclaimerDialogOpen: boolean;
isWethNoticeDialogOpen: boolean;
} }
export class Portal extends React.Component<PortalAllProps, PortalAllState> { export class Portal extends React.Component<PortalAllProps, PortalAllState> {
private blockchain: Blockchain; private blockchain: Blockchain;
private sharedOrderIfExists: Order; private sharedOrderIfExists: Order;
private throttledScreenWidthUpdate: () => void; private throttledScreenWidthUpdate: () => void;
public static hasAlreadyDismissedWethNotice() {
const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE);
const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) &&
!_.isEmpty(didDismissWethNotice);
return hasAlreadyDismissedWethNotice;
}
constructor(props: PortalAllProps) { constructor(props: PortalAllProps) {
super(props); super(props);
this.sharedOrderIfExists = this.getSharedOrderIfExists(); this.sharedOrderIfExists = this.getSharedOrderIfExists();
this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT); this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`);
const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER);
const hasAcceptedDisclaimer = !_.isUndefined(didAcceptPortalDisclaimer) &&
!_.isEmpty(didAcceptPortalDisclaimer);
this.state = { this.state = {
prevNetworkId: this.props.networkId, prevNetworkId: this.props.networkId,
prevNodeVersion: this.props.nodeVersion, prevNodeVersion: this.props.nodeVersion,
prevUserAddress: this.props.userAddress, prevUserAddress: this.props.userAddress,
hasAcceptedDisclaimer: false, prevPathname: this.props.location.pathname,
isDisclaimerDialogOpen: !hasAcceptedDisclaimer,
isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances,
}; };
} }
public componentDidMount() { public componentDidMount() {
@@ -87,12 +105,6 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
} }
public componentWillMount() { public componentWillMount() {
this.blockchain = new Blockchain(this.props.dispatcher); this.blockchain = new Blockchain(this.props.dispatcher);
const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY);
const hasAcceptedDisclaimer = !_.isUndefined(didAcceptPortalDisclaimer) &&
!_.isEmpty(didAcceptPortalDisclaimer);
this.setState({
hasAcceptedDisclaimer,
});
} }
public componentWillUnmount() { public componentWillUnmount() {
this.blockchain.destroy(); this.blockchain.destroy();
@@ -128,6 +140,14 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
// tslint:disable-next-line:no-floating-promises // tslint:disable-next-line:no-floating-promises
this.blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion); this.blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion);
} }
if (nextProps.location.pathname !== this.state.prevPathname) {
const isViewingBalances = _.includes(nextProps.location.pathname, `${WebsitePaths.Portal}/balances`);
const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
this.setState({
prevPathname: nextProps.location.pathname,
isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances,
});
}
} }
public render() { public render() {
const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher
@@ -138,6 +158,11 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
flexDirection: 'column', flexDirection: 'column',
justifyContent: 'space-between', justifyContent: 'space-between',
}; };
const portalMenuContainerStyle: React.CSSProperties = {
overflow: 'hidden',
backgroundColor: colors.darkestGrey,
color: colors.white,
};
return ( return (
<div style={portalStyle}> <div style={portalStyle}>
<DocumentTitle title="0x Portal DApp"/> <DocumentTitle title="0x Portal DApp"/>
@@ -146,9 +171,9 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
blockchainIsLoaded={this.props.blockchainIsLoaded} blockchainIsLoaded={this.props.blockchainIsLoaded}
location={this.props.location} location={this.props.location}
/> />
<div id="portal" className="mx-auto max-width-4 pt4" style={{width: '100%'}}> <div id="portal" className="mx-auto max-width-4" style={{width: '100%'}}>
<Paper className="mb3 mt2"> <Paper className="mb3 mt2">
{!configs.isMainnetEnabled && this.props.networkId === constants.MAINNET_NETWORK_ID ? {!configs.IS_MAINNET_ENABLED && this.props.networkId === constants.NETWORK_ID_MAINNET ?
<div className="p3 center"> <div className="p3 center">
<div className="h2 py2">Mainnet unavailable</div> <div className="h2 py2">Mainnet unavailable</div>
<div className="mx-auto pb2 pt2"> <div className="mx-auto pb2 pt2">
@@ -171,9 +196,9 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
<div className="mx-auto flex"> <div className="mx-auto flex">
<div <div
className="col col-2 pr2 pt1 sm-hide xs-hide" className="col col-2 pr2 pt1 sm-hide xs-hide"
style={{overflow: 'hidden', backgroundColor: 'rgb(39, 39, 39)', color: 'white'}} style={portalMenuContainerStyle}
> >
<PortalMenu menuItemStyle={{color: 'white'}} /> <PortalMenu menuItemStyle={{color: colors.white}} />
</div> </div>
<div className="col col-12 lg-col-10 md-col-10 sm-col sm-col-12"> <div className="col col-12 lg-col-10 md-col-10 sm-col sm-col-12">
<div className="py2" style={{backgroundColor: colors.grey50}}> <div className="py2" style={{backgroundColor: colors.grey50}}>
@@ -215,8 +240,12 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
toggleDialogFn={updateShouldBlockchainErrDialogBeOpen} toggleDialogFn={updateShouldBlockchainErrDialogBeOpen}
networkId={this.props.networkId} networkId={this.props.networkId}
/> />
<WrappedEthSectionNoticeDialog
isOpen={this.state.isWethNoticeDialogOpen}
onToggleDialog={this.onWethNoticeAccepted.bind(this)}
/>
<PortalDisclaimerDialog <PortalDisclaimerDialog
isOpen={!this.state.hasAcceptedDisclaimer} isOpen={this.state.isDisclaimerDialogOpen}
onToggleDialog={this.onPortalDisclaimerAccepted.bind(this)} onToggleDialog={this.onPortalDisclaimerAccepted.bind(this)}
/> />
<FlashMessage <FlashMessage
@@ -224,7 +253,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
flashMessage={this.props.flashMessage} flashMessage={this.props.flashMessage}
/> />
</div> </div>
<Footer location={this.props.location} /> <Footer />
</div> </div>
); );
} }
@@ -295,9 +324,15 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
); );
} }
private onPortalDisclaimerAccepted() { private onPortalDisclaimerAccepted() {
localStorage.setItem(constants.ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY, 'set'); localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set');
this.setState({ this.setState({
hasAcceptedDisclaimer: true, isDisclaimerDialogOpen: false,
});
}
private onWethNoticeAccepted() {
localStorage.setItem(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE, 'set');
this.setState({
isWethNoticeDialogOpen: false,
}); });
} }
private getSharedOrderIfExists(): Order { private getSharedOrderIfExists(): Order {

View File

@@ -70,14 +70,14 @@ export class SendButton extends React.Component<SendButtonProps, SendButtonState
this.props.dispatcher.replaceTokenBalanceByAddress(token.address, balance); this.props.dispatcher.replaceTokenBalanceByAddress(token.address, balance);
} catch (err) { } catch (err) {
const errMsg = `${err}`; const errMsg = `${err}`;
if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) { if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return; return;
} else if (!_.includes(errMsg, 'User denied transaction')) { } else if (!_.includes(errMsg, 'User denied transaction')) {
utils.consoleLog(`Unexpected error encountered: ${err}`); utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack); utils.consoleLog(err.stack);
await errorReporter.reportAsync(err);
this.props.onError(); this.props.onError();
await errorReporter.reportAsync(err);
} }
} }
this.setState({ this.setState({

View File

@@ -7,7 +7,6 @@ import Divider from 'material-ui/Divider';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import FloatingActionButton from 'material-ui/FloatingActionButton'; import FloatingActionButton from 'material-ui/FloatingActionButton';
import RaisedButton from 'material-ui/RaisedButton'; import RaisedButton from 'material-ui/RaisedButton';
import {colors} from 'material-ui/styles';
import ContentAdd from 'material-ui/svg-icons/content/add'; import ContentAdd from 'material-ui/svg-icons/content/add';
import ContentRemove from 'material-ui/svg-icons/content/remove'; import ContentRemove from 'material-ui/svg-icons/content/remove';
import { import {
@@ -42,6 +41,7 @@ import {
TokenStateByAddress, TokenStateByAddress,
TokenVisibility, TokenVisibility,
} from 'ts/types'; } from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs'; import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {errorReporter} from 'ts/utils/error_reporter'; import {errorReporter} from 'ts/utils/error_reporter';
@@ -115,7 +115,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
if (!_.isUndefined(this.state.currentZrxBalance) && !nextZrxTokenBalance.eq(this.state.currentZrxBalance)) { if (!_.isUndefined(this.state.currentZrxBalance) && !nextZrxTokenBalance.eq(this.state.currentZrxBalance)) {
if (this.state.isZRXSpinnerVisible) { if (this.state.isZRXSpinnerVisible) {
const receivedAmount = nextZrxTokenBalance.minus(this.state.currentZrxBalance); const receivedAmount = nextZrxTokenBalance.minus(this.state.currentZrxBalance);
const receiveAmountInUnits = ZeroEx.toUnitAmount(receivedAmount, 18); const receiveAmountInUnits = ZeroEx.toUnitAmount(receivedAmount, constants.DECIMAL_PLACES_ZRX);
this.props.dispatcher.showFlashMessage(`Received ${receiveAmountInUnits.toString(10)} Kovan ZRX`); this.props.dispatcher.showFlashMessage(`Received ${receiveAmountInUnits.toString(10)} Kovan ZRX`);
} }
this.setState({ this.setState({
@@ -144,7 +144,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
onTouchTap={this.onDharmaDialogToggle.bind(this, false)} onTouchTap={this.onDharmaDialogToggle.bind(this, false)}
/>, />,
]; ];
const isTestNetwork = this.props.networkId === constants.TESTNET_NETWORK_ID; const isTestNetwork = this.props.networkId === constants.NETWORK_ID_TESTNET;
const dharmaButtonColumnStyle = { const dharmaButtonColumnStyle = {
paddingLeft: 3, paddingLeft: 3,
display: isTestNetwork ? 'table-cell' : 'none', display: isTestNetwork ? 'table-cell' : 'none',
@@ -156,7 +156,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
const tokenTableHeight = allTokenRowHeight < MAX_TOKEN_TABLE_HEIGHT ? const tokenTableHeight = allTokenRowHeight < MAX_TOKEN_TABLE_HEIGHT ?
allTokenRowHeight : allTokenRowHeight :
MAX_TOKEN_TABLE_HEIGHT; MAX_TOKEN_TABLE_HEIGHT;
const isSmallScreen = this.props.screenWidth === ScreenWidths.SM; const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
const tokenColSpan = isSmallScreen ? TOKEN_COL_SPAN_SM : TOKEN_COL_SPAN_LG; const tokenColSpan = isSmallScreen ? TOKEN_COL_SPAN_SM : TOKEN_COL_SPAN_LG;
const dharmaLoanExplanation = 'If you need access to larger amounts of ether,<br> \ const dharmaLoanExplanation = 'If you need access to larger amounts of ether,<br> \
you can request a loan from the Dharma Loan<br> \ you can request a loan from the Dharma Loan<br> \
@@ -164,7 +164,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
minutes or less.'; minutes or less.';
const allowanceExplanation = '0x smart contracts require access to your<br> \ const allowanceExplanation = '0x smart contracts require access to your<br> \
token balances in order to execute trades.<br> \ token balances in order to execute trades.<br> \
Toggling permissions sets an allowance for the<br> \ Toggling sets an allowance for the<br> \
smart contract so you can start trading that token.'; smart contract so you can start trading that token.';
return ( return (
<div className="lg-px4 md-px4 sm-px1 pb2"> <div className="lg-px4 md-px4 sm-px1 pb2">
@@ -302,7 +302,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
</TableHeaderColumn> </TableHeaderColumn>
<TableHeaderColumn style={{paddingLeft: 3}}>Balance</TableHeaderColumn> <TableHeaderColumn style={{paddingLeft: 3}}>Balance</TableHeaderColumn>
<TableHeaderColumn> <TableHeaderColumn>
<div className="inline-block">{!isSmallScreen && 'Trade '}Permissions</div> <div className="inline-block">Allowance</div>
<HelpTooltip <HelpTooltip
style={{paddingLeft: 4}} style={{paddingLeft: 4}}
explanation={allowanceExplanation} explanation={allowanceExplanation}
@@ -311,7 +311,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
<TableHeaderColumn> <TableHeaderColumn>
Action Action
</TableHeaderColumn> </TableHeaderColumn>
{this.props.screenWidth !== ScreenWidths.SM && {this.props.screenWidth !== ScreenWidths.Sm &&
<TableHeaderColumn> <TableHeaderColumn>
Send Send
</TableHeaderColumn> </TableHeaderColumn>
@@ -333,9 +333,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
</Dialog> </Dialog>
<Dialog <Dialog
title="Request Dharma Loan" title="Request Dharma Loan"
titleStyle={{fontWeight: 100, backgroundColor: 'rgb(250, 250, 250)'}} titleStyle={{fontWeight: 100, backgroundColor: colors.white}}
bodyStyle={{backgroundColor: 'rgb(37, 37, 37)'}} bodyStyle={{backgroundColor: colors.dharmaDarkGrey}}
actionsContainerStyle={{backgroundColor: 'rgb(250, 250, 250)'}} actionsContainerStyle={{backgroundColor: colors.white}}
autoScrollBodyContent={true} autoScrollBodyContent={true}
actions={dharmaDialogActions} actions={dharmaDialogActions}
open={this.state.isDharmaDialogVisible} open={this.state.isDharmaDialogVisible}
@@ -357,10 +357,10 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
); );
} }
private renderTokenTableRows() { private renderTokenTableRows() {
if (!this.props.blockchainIsLoaded || this.props.blockchainErr !== '') { if (!this.props.blockchainIsLoaded || this.props.blockchainErr !== BlockchainErrs.NoError) {
return ''; return '';
} }
const isSmallScreen = this.props.screenWidth === ScreenWidths.SM; const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
const tokenColSpan = isSmallScreen ? TOKEN_COL_SPAN_SM : TOKEN_COL_SPAN_LG; const tokenColSpan = isSmallScreen ? TOKEN_COL_SPAN_SM : TOKEN_COL_SPAN_LG;
const actionPaddingX = isSmallScreen ? 2 : 24; const actionPaddingX = isSmallScreen ? 2 : 24;
const allTokens = _.values(this.props.tokenByAddress); const allTokens = _.values(this.props.tokenByAddress);
@@ -379,9 +379,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
private renderTokenRow(tokenColSpan: number, actionPaddingX: number, token: Token) { private renderTokenRow(tokenColSpan: number, actionPaddingX: number, token: Token) {
const tokenState = this.props.tokenStateByAddress[token.address]; const tokenState = this.props.tokenStateByAddress[token.address];
const tokenLink = utils.getEtherScanLinkIfExists(token.address, this.props.networkId, const tokenLink = utils.getEtherScanLinkIfExists(token.address, this.props.networkId,
EtherscanLinkSuffixes.address); EtherscanLinkSuffixes.Address);
const isMintable = _.includes(configs.symbolsOfMintableTokens, token.symbol) && const isMintable = _.includes(configs.SYMBOLS_OF_MINTABLE_TOKENS, token.symbol) &&
this.props.networkId !== constants.MAINNET_NETWORK_ID; this.props.networkId !== constants.NETWORK_ID_MAINNET;
return ( return (
<TableRow key={token.address} style={{height: TOKEN_TABLE_ROW_HEIGHT}}> <TableRow key={token.address} style={{height: TOKEN_TABLE_ROW_HEIGHT}}>
<TableRowColumn <TableRowColumn
@@ -423,7 +423,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
onClickAsyncFn={this.onMintTestTokensAsync.bind(this, token)} onClickAsyncFn={this.onMintTestTokensAsync.bind(this, token)}
/> />
} }
{token.symbol === ZRX_TOKEN_SYMBOL && this.props.networkId === constants.TESTNET_NETWORK_ID && {token.symbol === ZRX_TOKEN_SYMBOL && this.props.networkId === constants.NETWORK_ID_TESTNET &&
<LifeCycleRaisedButton <LifeCycleRaisedButton
labelReady="Request" labelReady="Request"
labelLoading="Sending..." labelLoading="Sending..."
@@ -432,7 +432,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
/> />
} }
</TableRowColumn> </TableRowColumn>
{this.props.screenWidth !== ScreenWidths.SM && {this.props.screenWidth !== ScreenWidths.Sm &&
<TableRowColumn <TableRowColumn
style={{paddingLeft: actionPaddingX, paddingRight: actionPaddingX}} style={{paddingLeft: actionPaddingX, paddingRight: actionPaddingX}}
> >
@@ -456,13 +456,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
return; return;
} }
const token = this.props.tokenByAddress[tokenAddress]; const token = this.props.tokenByAddress[tokenAddress];
const isDefaultTrackedToken = _.includes(configs.defaultTrackedTokenSymbols, token.symbol); const isDefaultTrackedToken = _.includes(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, token.symbol);
if (!this.state.isAddingToken && !isDefaultTrackedToken) { if (!this.state.isAddingToken && !isDefaultTrackedToken) {
if (token.isRegistered) { if (token.isRegistered) {
// Remove the token from tracked tokens // Remove the token from tracked tokens
const newToken = _.assign({}, token, { const newToken = {
...token,
isTracked: false, isTracked: false,
}); };
this.props.dispatcher.updateTokenByAddress([newToken]); this.props.dispatcher.updateTokenByAddress([newToken]);
} else { } else {
this.props.dispatcher.removeTokenToTokenByAddress(token); this.props.dispatcher.removeTokenToTokenByAddress(token);
@@ -507,7 +508,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
return ( return (
<div> <div>
Our faucet can only send test Ether to addresses on the {constants.TESTNET_NAME} Our faucet can only send test Ether to addresses on the {constants.TESTNET_NAME}
{' '}testnet (networkId {constants.TESTNET_NETWORK_ID}). Please make sure you are {' '}testnet (networkId {constants.NETWORK_ID_TESTNET}). Please make sure you are
{' '}connected to the {constants.TESTNET_NAME} testnet and try requesting ether again. {' '}connected to the {constants.TESTNET_NAME} testnet and try requesting ether again.
</div> </div>
); );
@@ -580,7 +581,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
return true; return true;
} catch (err) { } catch (err) {
const errMsg = '' + err; const errMsg = '' + err;
if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) { if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return false; return false;
} }
@@ -604,7 +605,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
// If on another network other then the testnet our faucet serves test ether // If on another network other then the testnet our faucet serves test ether
// from, we must show user an error message // from, we must show user an error message
if (this.props.blockchain.networkId !== constants.TESTNET_NETWORK_ID) { if (this.props.blockchain.networkId !== constants.NETWORK_ID_TESTNET) {
this.setState({ this.setState({
errorType: BalanceErrs.incorrectNetworkForFaucet, errorType: BalanceErrs.incorrectNetworkForFaucet,
}); });
@@ -614,7 +615,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
await utils.sleepAsync(ARTIFICIAL_FAUCET_REQUEST_DELAY); await utils.sleepAsync(ARTIFICIAL_FAUCET_REQUEST_DELAY);
const segment = isEtherRequest ? 'ether' : 'zrx'; const segment = isEtherRequest ? 'ether' : 'zrx';
const response = await fetch(`${constants.ETHER_FAUCET_ENDPOINT}/${segment}/${this.props.userAddress}`); const response = await fetch(`${constants.URL_ETHER_FAUCET}/${segment}/${this.props.userAddress}`);
const responseBody = await response.text(); const responseBody = await response.text();
if (response.status !== constants.SUCCESS_STATUS) { if (response.status !== constants.SUCCESS_STATUS) {
utils.consoleLog(`Unexpected status code: ${response.status} -> ${responseBody}`); utils.consoleLog(`Unexpected status code: ${response.status} -> ${responseBody}`);

View File

@@ -1,7 +1,6 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import Drawer from 'material-ui/Drawer'; import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem'; import MenuItem from 'material-ui/MenuItem';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import ReactTooltip = require('react-tooltip'); import ReactTooltip = require('react-tooltip');
@@ -12,11 +11,9 @@ import {Identicon} from 'ts/components/ui/identicon';
import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {DocsInfo} from 'ts/pages/documentation/docs_info';
import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu'; import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu';
import {DocsMenu, MenuSubsectionsBySection, Styles, WebsitePaths} from 'ts/types'; import {DocsMenu, MenuSubsectionsBySection, Styles, WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
const CUSTOM_DARK_GRAY = '#231F20';
const SECTION_HEADER_COLOR = 'rgb(234, 234, 234)';
interface TopBarProps { interface TopBarProps {
userAddress?: string; userAddress?: string;
blockchainIsLoaded: boolean; blockchainIsLoaded: boolean;
@@ -44,16 +41,11 @@ const styles: Styles = {
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
width: 70, width: 70,
}, },
addressPopover: {
backgroundColor: colors.blueGrey500,
color: 'white',
padding: 3,
},
topBar: { topBar: {
backgroundColor: 'white', backgroundcolor: colors.white,
height: 59, height: 59,
width: '100%', width: '100%',
position: 'fixed', position: 'relative',
top: 0, top: 0,
zIndex: 1100, zIndex: 1100,
paddingBottom: 1, paddingBottom: 1,
@@ -63,7 +55,7 @@ const styles: Styles = {
}, },
menuItem: { menuItem: {
fontSize: 14, fontSize: 14,
color: CUSTOM_DARK_GRAY, color: colors.darkestGrey,
paddingTop: 6, paddingTop: 6,
paddingBottom: 6, paddingBottom: 6,
marginTop: 17, marginTop: 17,
@@ -114,7 +106,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
key="subMenuItem-standard-relayer-api" key="subMenuItem-standard-relayer-api"
target="_blank" target="_blank"
className="text-decoration-none" className="text-decoration-none"
href={constants.STANDARD_RELAYER_API_GITHUB} href={constants.URL_STANDARD_RELAYER_API_GITHUB}
> >
<MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Standard Relayer API" /> <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Standard Relayer API" />
</a>, </a>,
@@ -122,7 +114,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
key="subMenuItem-github" key="subMenuItem-github"
target="_blank" target="_blank"
className="text-decoration-none" className="text-decoration-none"
href={constants.GITHUB_URL} href={constants.URL_GITHUB_ORG}
> >
<MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="GitHub" /> <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="GitHub" />
</a>, </a>,
@@ -222,7 +214,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
{this.renderPortalMenu()} {this.renderPortalMenu()}
{this.renderDocsMenu()} {this.renderDocsMenu()}
{this.renderWiki()} {this.renderWiki()}
<div className="pl1 py1 mt3" style={{backgroundColor: SECTION_HEADER_COLOR}}>Website</div> <div className="pl1 py1 mt3" style={{backgroundColor: colors.lightGrey}}>Website</div>
<Link to={WebsitePaths.Home} className="text-decoration-none"> <Link to={WebsitePaths.Home} className="text-decoration-none">
<MenuItem className="py2">Home</MenuItem> <MenuItem className="py2">Home</MenuItem>
</Link> </Link>
@@ -262,7 +254,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
<a <a
className="text-decoration-none" className="text-decoration-none"
target="_blank" target="_blank"
href={constants.BLOG_URL} href={constants.URL_BLOG}
> >
<MenuItem className="py2">Blog</MenuItem> <MenuItem className="py2">Blog</MenuItem>
</a> </a>
@@ -286,7 +278,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
const sectionTitle = `${this.props.docsInfo.displayName} Docs`; const sectionTitle = `${this.props.docsInfo.displayName} Docs`;
return ( return (
<div className="lg-hide md-hide"> <div className="lg-hide md-hide">
<div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>{sectionTitle}</div> <div className="pl1 py1" style={{backgroundColor: colors.lightGrey}}>{sectionTitle}</div>
<NestedSidebarMenu <NestedSidebarMenu
topLevelMenu={this.props.menu} topLevelMenu={this.props.menu}
menuSubsectionsBySection={this.props.menuSubsectionsBySection} menuSubsectionsBySection={this.props.menuSubsectionsBySection}
@@ -306,7 +298,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
return ( return (
<div className="lg-hide md-hide"> <div className="lg-hide md-hide">
<div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>0x Protocol Wiki</div> <div className="pl1 py1" style={{backgroundColor: colors.lightGrey}}>0x Protocol Wiki</div>
<NestedSidebarMenu <NestedSidebarMenu
topLevelMenu={this.props.menuSubsectionsBySection} topLevelMenu={this.props.menuSubsectionsBySection}
menuSubsectionsBySection={this.props.menuSubsectionsBySection} menuSubsectionsBySection={this.props.menuSubsectionsBySection}
@@ -323,7 +315,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
return ( return (
<div className="lg-hide md-hide"> <div className="lg-hide md-hide">
<div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>Portal DApp</div> <div className="pl1 py1" style={{backgroundColor: colors.lightGrey}}>Portal DApp</div>
<PortalMenu <PortalMenu
menuItemStyle={{color: 'black'}} menuItemStyle={{color: 'black'}}
onClick={this.onMenuButtonClick.bind(this)} onClick={this.onMenuButtonClick.bind(this)}

View File

@@ -1,10 +1,10 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as React from 'react'; import * as React from 'react';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import {colors} from 'ts/utils/colors';
const CUSTOM_DARK_GRAY = '#231F20';
const DEFAULT_STYLE = { const DEFAULT_STYLE = {
color: CUSTOM_DARK_GRAY, color: colors.darkestGrey,
}; };
interface TopBarMenuItemProps { interface TopBarMenuItemProps {
@@ -28,7 +28,7 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM
public render() { public render() {
const primaryStyles = this.props.isPrimary ? { const primaryStyles = this.props.isPrimary ? {
borderRadius: 4, borderRadius: 4,
border: `1px solid ${this.props.isNightVersion ? '#979797' : 'rgb(230, 229, 229)'}`, border: `1px solid ${this.props.isNightVersion ? colors.grey : colors.greyishPink}`,
marginTop: 15, marginTop: 15,
paddingLeft: 9, paddingLeft: 9,
paddingRight: 9, paddingRight: 9,
@@ -36,7 +36,7 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM
} : {}; } : {};
const menuItemColor = this.props.isNightVersion ? 'white' : this.props.style.color; const menuItemColor = this.props.isNightVersion ? 'white' : this.props.style.color;
const linkColor = _.isUndefined(menuItemColor) ? const linkColor = _.isUndefined(menuItemColor) ?
CUSTOM_DARK_GRAY : colors.darkestGrey :
menuItemColor; menuItemColor;
return ( return (
<div <div

View File

@@ -1,8 +1,8 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Party} from 'ts/components/ui/party'; import {Party} from 'ts/components/ui/party';
import {Token, TokenByAddress} from 'ts/types'; import {Token, TokenByAddress} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
interface TrackTokenConfirmationProps { interface TrackTokenConfirmationProps {

View File

@@ -2,13 +2,13 @@ import {ZeroEx} from '0x.js';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
import Paper from 'material-ui/Paper'; import Paper from 'material-ui/Paper';
import {colors} from 'material-ui/styles';
import * as moment from 'moment'; import * as moment from 'moment';
import * as React from 'react'; import * as React from 'react';
import * as ReactTooltip from 'react-tooltip'; import * as ReactTooltip from 'react-tooltip';
import {EtherScanIcon} from 'ts/components/ui/etherscan_icon'; import {EtherScanIcon} from 'ts/components/ui/etherscan_icon';
import {Party} from 'ts/components/ui/party'; import {Party} from 'ts/components/ui/party';
import {EtherscanLinkSuffixes, Fill, Token, TokenByAddress} from 'ts/types'; import {EtherscanLinkSuffixes, Fill, Token, TokenByAddress} from 'ts/types';
import {colors} from 'ts/utils/colors';
const PRECISION = 5; const PRECISION = 5;
const IDENTICON_DIAMETER = 40; const IDENTICON_DIAMETER = 40;
@@ -87,7 +87,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
<EtherScanIcon <EtherScanIcon
addressOrTxHash={fill.transactionHash} addressOrTxHash={fill.transactionHash}
networkId={this.props.networkId} networkId={this.props.networkId}
etherscanLinkSuffixes={EtherscanLinkSuffixes.tx} etherscanLinkSuffixes={EtherscanLinkSuffixes.Tx}
/> />
</div> </div>
</div> </div>

View File

@@ -1,8 +1,6 @@
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {AlertTypes} from 'ts/types'; import {AlertTypes} from 'ts/types';
import {colors} from 'ts/utils/colors';
const CUSTOM_GREEN = 'rgb(137, 199, 116)';
interface AlertProps { interface AlertProps {
type: AlertTypes; type: AlertTypes;
@@ -12,8 +10,8 @@ interface AlertProps {
export function Alert(props: AlertProps) { export function Alert(props: AlertProps) {
const isAlert = props.type === AlertTypes.ERROR; const isAlert = props.type === AlertTypes.ERROR;
const errMsgStyles = { const errMsgStyles = {
background: isAlert ? colors.red200 : CUSTOM_GREEN, background: isAlert ? colors.red200 : colors.lightestGreen,
color: 'white', color: colors.white,
marginTop: 10, marginTop: 10,
padding: 4, padding: 4,
paddingLeft: 8, paddingLeft: 8,

View File

@@ -1,9 +1,9 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import * as CopyToClipboard from 'react-copy-to-clipboard'; import * as CopyToClipboard from 'react-copy-to-clipboard';
import * as ReactDOM from 'react-dom'; import * as ReactDOM from 'react-dom';
import ReactTooltip = require('react-tooltip'); import ReactTooltip = require('react-tooltip');
import {colors} from 'ts/utils/colors';
interface CopyIconProps { interface CopyIconProps {
data: string; data: string;

View File

@@ -2,9 +2,9 @@ import * as _ from 'lodash';
import Menu from 'material-ui/Menu'; import Menu from 'material-ui/Menu';
import Popover from 'material-ui/Popover'; import Popover from 'material-ui/Popover';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
const CHECK_CLOSE_POPOVER_INTERVAL_MS = 300; const CHECK_CLOSE_POPOVER_INTERVAL_MS = 300;
const CUSTOM_LIGHT_GRAY = '#848484';
const DEFAULT_STYLE = { const DEFAULT_STYLE = {
fontSize: 14, fontSize: 14,
}; };
@@ -72,7 +72,7 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro
onMouseEnter={this.onHover.bind(this)} onMouseEnter={this.onHover.bind(this)}
onMouseLeave={this.onHoverOff.bind(this)} onMouseLeave={this.onHoverOff.bind(this)}
> >
<Menu style={{color: CUSTOM_LIGHT_GRAY}}> <Menu style={{color: colors.grey}}>
{this.props.subMenuItems} {this.props.subMenuItems}
</Menu> </Menu>
</div> </div>

View File

@@ -26,7 +26,7 @@ export const EthereumAddress = (props: EthereumAddressProps) => {
<EtherScanIcon <EtherScanIcon
addressOrTxHash={props.address} addressOrTxHash={props.address}
networkId={props.networkId} networkId={props.networkId}
etherscanLinkSuffixes={EtherscanLinkSuffixes.address} etherscanLinkSuffixes={EtherscanLinkSuffixes.Address}
/> />
</div> </div>
<ReactTooltip id={tooltipId}>{props.address}</ReactTooltip> <ReactTooltip id={tooltipId}>{props.address}</ReactTooltip>

View File

@@ -1,8 +1,8 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import ReactTooltip = require('react-tooltip'); import ReactTooltip = require('react-tooltip');
import {EtherscanLinkSuffixes} from 'ts/types'; import {EtherscanLinkSuffixes} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
interface EtherScanIconProps { interface EtherScanIconProps {
@@ -13,7 +13,7 @@ interface EtherScanIconProps {
export const EtherScanIcon = (props: EtherScanIconProps) => { export const EtherScanIcon = (props: EtherScanIconProps) => {
const etherscanLinkIfExists = utils.getEtherScanLinkIfExists( const etherscanLinkIfExists = utils.getEtherScanLinkIfExists(
props.addressOrTxHash, props.networkId, EtherscanLinkSuffixes.address, props.addressOrTxHash, props.networkId, EtherscanLinkSuffixes.Address,
); );
const transactionTooltipId = `${props.addressOrTxHash}-etherscan-icon-tooltip`; const transactionTooltipId = `${props.addressOrTxHash}-etherscan-icon-tooltip`;
return ( return (

View File

@@ -1,5 +1,5 @@
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
export interface InputLabelProps { export interface InputLabelProps {
text: string | Element | React.ReactNode; text: string | Element | React.ReactNode;
@@ -7,7 +7,7 @@ export interface InputLabelProps {
const styles = { const styles = {
label: { label: {
color: colors.grey500, color: colors.grey,
fontSize: 12, fontSize: 12,
pointerEvents: 'none', pointerEvents: 'none',
textAlign: 'left', textAlign: 'left',

View File

@@ -1,73 +0,0 @@
import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react';
const CUSTOM_BLUE = '#63A6F1';
interface LabeledSwitcherProps {
labelLeft: string;
labelRight: string;
isLeftInitiallySelected: boolean;
onLeftLabelClickAsync: () => Promise<boolean>;
onRightLabelClickAsync: () => Promise<boolean>;
}
interface LabeledSwitcherState {
isLeftSelected: boolean;
}
export class LabeledSwitcher extends React.Component<LabeledSwitcherProps, LabeledSwitcherState> {
constructor(props: LabeledSwitcherProps) {
super(props);
this.state = {
isLeftSelected: props.isLeftInitiallySelected,
};
}
public render() {
const isLeft = true;
return (
<div
className="rounded clearfix"
>
{this.renderLabel(this.props.labelLeft, isLeft, this.state.isLeftSelected)}
{this.renderLabel(this.props.labelRight, !isLeft, !this.state.isLeftSelected)}
</div>
);
}
private renderLabel(title: string, isLeft: boolean, isSelected: boolean) {
const borderStyle = `2px solid ${isSelected ? '#4F8BCF' : '#DADADA'}`;
const style = {
cursor: 'pointer',
backgroundColor: isSelected ? CUSTOM_BLUE : colors.grey200,
color: isSelected ? 'white' : '#A5A5A5',
boxShadow: isSelected ? `inset 0px 0px 4px #4083CE` : 'inset 0px 0px 4px #F7F6F6',
borderTop: borderStyle,
borderBottom: borderStyle,
[isLeft ? 'borderLeft' : 'borderRight']: borderStyle,
paddingTop: 12,
paddingBottom: 12,
};
return (
<div
className={`col col-6 center p1 ${isLeft ? 'rounded-left' : 'rounded-right'}`}
style={style}
onClick={this.onLabelClickAsync.bind(this, isLeft)}
>
{title}
</div>
);
}
private async onLabelClickAsync(isLeft: boolean): Promise<void> {
this.setState({
isLeftSelected: isLeft,
});
const didSucceed = isLeft ?
await this.props.onLeftLabelClickAsync() :
await this.props.onRightLabelClickAsync();
if (!didSucceed) {
this.setState({
isLeftSelected: !isLeft,
});
}
}
}

View File

@@ -1,6 +1,7 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import RaisedButton from 'material-ui/RaisedButton'; import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
const COMPLETE_STATE_SHOW_LENGTH_MS = 2000; const COMPLETE_STATE_SHOW_LENGTH_MS = 2000;
@@ -31,8 +32,8 @@ export class LifeCycleRaisedButton extends
React.Component<LifeCycleRaisedButtonProps, LifeCycleRaisedButtonState> { React.Component<LifeCycleRaisedButtonProps, LifeCycleRaisedButtonState> {
public static defaultProps: Partial<LifeCycleRaisedButtonProps> = { public static defaultProps: Partial<LifeCycleRaisedButtonProps> = {
isDisabled: false, isDisabled: false,
backgroundColor: 'white', backgroundColor: colors.white,
labelColor: 'rgb(97, 97, 97)', labelColor: colors.darkGrey,
}; };
private buttonTimeoutId: number; private buttonTimeoutId: number;
private didUnmount: boolean; private didUnmount: boolean;

View File

@@ -1,15 +1,14 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import ReactTooltip = require('react-tooltip'); import ReactTooltip = require('react-tooltip');
import {EthereumAddress} from 'ts/components/ui/ethereum_address'; import {EthereumAddress} from 'ts/components/ui/ethereum_address';
import {Identicon} from 'ts/components/ui/identicon'; import {Identicon} from 'ts/components/ui/identicon';
import {EtherscanLinkSuffixes} from 'ts/types'; import {EtherscanLinkSuffixes} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
const IMAGE_DIMENSION = 100; const IMAGE_DIMENSION = 100;
const IDENTICON_DIAMETER = 95; const IDENTICON_DIAMETER = 95;
const CHECK_MARK_GREEN = 'rgb(0, 195, 62)';
interface PartyProps { interface PartyProps {
label: string; label: string;
@@ -45,7 +44,7 @@ export class Party extends React.Component<PartyProps, PartyState> {
height: IMAGE_DIMENSION, height: IMAGE_DIMENSION,
}; };
const etherscanLinkIfExists = utils.getEtherScanLinkIfExists( const etherscanLinkIfExists = utils.getEtherScanLinkIfExists(
this.props.address, this.props.networkId, EtherscanLinkSuffixes.address, this.props.address, this.props.networkId, EtherscanLinkSuffixes.Address,
); );
const isRegistered = this.props.isInTokenRegistry; const isRegistered = this.props.isInTokenRegistry;
const registeredTooltipId = `${this.props.address}-${isRegistered}-registeredTooltip`; const registeredTooltipId = `${this.props.address}-${isRegistered}-registeredTooltip`;
@@ -94,7 +93,7 @@ export class Party extends React.Component<PartyProps, PartyState> {
className="mx-auto" className="mx-auto"
style={{fontSize: 13, width: 127}} style={{fontSize: 13, width: 127}}
> >
<span style={{color: isRegistered ? CHECK_MARK_GREEN : colors.red500}}> <span style={{color: isRegistered ? colors.brightGreen : colors.red500}}>
<i <i
className={`zmdi ${isRegistered ? 'zmdi-check-circle' : 'zmdi-alert-triangle'}`} className={`zmdi ${isRegistered ? 'zmdi-check-circle' : 'zmdi-alert-triangle'}`}
/> />

View File

@@ -1,5 +1,5 @@
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
export interface RequiredLabelProps { export interface RequiredLabelProps {
label: string|React.ReactNode; label: string|React.ReactNode;

View File

@@ -1,6 +1,6 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
interface SwapIconProps { interface SwapIconProps {
swapTokensFn: () => void; swapTokensFn: () => void;

View File

@@ -43,8 +43,8 @@ interface ConnectedDispatch {
} }
const mapStateToProps = (state: State, ownProps: PortalComponentAllProps): ConnectedState => { const mapStateToProps = (state: State, ownProps: PortalComponentAllProps): ConnectedState => {
const receiveAssetToken = state.sideToAssetToken[Side.receive]; const receiveAssetToken = state.sideToAssetToken[Side.Receive];
const depositAssetToken = state.sideToAssetToken[Side.deposit]; const depositAssetToken = state.sideToAssetToken[Side.Deposit];
const receiveAddress = !_.isUndefined(receiveAssetToken.address) ? const receiveAddress = !_.isUndefined(receiveAssetToken.address) ?
receiveAssetToken.address : constants.NULL_ADDRESS; receiveAssetToken.address : constants.NULL_ADDRESS;
const depositAddress = !_.isUndefined(depositAssetToken.address) ? const depositAddress = !_.isUndefined(depositAssetToken.address) ?
@@ -56,7 +56,7 @@ const mapStateToProps = (state: State, ownProps: PortalComponentAllProps): Conne
const hashData = { const hashData = {
depositAmount, depositAmount,
depositTokenContractAddr: depositAddress, depositTokenContractAddr: depositAddress,
feeRecipientAddress: constants.FEE_RECIPIENT_ADDRESS, feeRecipientAddress: constants.NULL_ADDRESS,
makerFee: constants.MAKER_FEE, makerFee: constants.MAKER_FEE,
orderExpiryTimestamp: state.orderExpiryTimestamp, orderExpiryTimestamp: state.orderExpiryTimestamp,
orderMakerAddress: state.userAddress, orderMakerAddress: state.userAddress,

View File

@@ -9,16 +9,13 @@ import {
} from 'ts/pages/documentation/documentation'; } from 'ts/pages/documentation/documentation';
import {Dispatcher} from 'ts/redux/dispatcher'; import {Dispatcher} from 'ts/redux/dispatcher';
import {State} from 'ts/redux/reducer'; import {State} from 'ts/redux/reducer';
import {DocsInfoConfig, WebsitePaths} from 'ts/types'; import {DocsInfoConfig, SmartContractDocSections as Sections, WebsitePaths} from 'ts/types';
import {constants} from 'ts/utils/constants';
import {doxityUtils} from 'ts/utils/doxity_utils'; import {doxityUtils} from 'ts/utils/doxity_utils';
/* tslint:disable:no-var-requires */ /* tslint:disable:no-var-requires */
const IntroMarkdown = require('md/docs/smart_contracts/introduction'); const IntroMarkdown = require('md/docs/smart_contracts/introduction');
/* tslint:enable:no-var-requires */ /* tslint:enable:no-var-requires */
const sections = constants.smartContractDocSections;
const docsInfoConfig: DocsInfoConfig = { const docsInfoConfig: DocsInfoConfig = {
displayName: '0x Smart Contracts', displayName: '0x Smart Contracts',
packageUrl: 'https://github.com/0xProject/contracts', packageUrl: 'https://github.com/0xProject/contracts',
@@ -26,26 +23,30 @@ const docsInfoConfig: DocsInfoConfig = {
docsJsonRoot: 'https://s3.amazonaws.com/smart-contracts-docs-json', docsJsonRoot: 'https://s3.amazonaws.com/smart-contracts-docs-json',
menu: { menu: {
introduction: [ introduction: [
sections.Introduction, Sections.Introduction,
], ],
contracts: [ contracts: [
sections.Exchange, Sections.Exchange,
sections.TokenRegistry, Sections.TokenRegistry,
sections.ZRXToken, Sections.ZRXToken,
sections.EtherToken, Sections.TokenTransferProxy,
sections.TokenTransferProxy,
], ],
}, },
sectionNameToMarkdown: { sectionNameToMarkdown: {
[sections.Introduction]: IntroMarkdown, [Sections.Introduction]: IntroMarkdown,
},
sections: {
Introduction: Sections.Introduction,
Exchange: Sections.Exchange,
TokenTransferProxy: Sections.TokenTransferProxy,
TokenRegistry: Sections.TokenRegistry,
ZRXToken: Sections.ZRXToken,
}, },
sections,
visibleConstructors: [ visibleConstructors: [
sections.Exchange, Sections.Exchange,
sections.TokenRegistry, Sections.TokenRegistry,
sections.ZRXToken, Sections.ZRXToken,
sections.EtherToken, Sections.TokenTransferProxy,
sections.TokenTransferProxy,
], ],
convertToDocAgnosticFormatFn: doxityUtils.convertToDocAgnosticFormat.bind(doxityUtils), convertToDocAgnosticFormatFn: doxityUtils.convertToDocAgnosticFormat.bind(doxityUtils),
}; };

View File

@@ -1,8 +1,8 @@
// Polyfills // Polyfills
import 'whatwg-fetch'; import 'whatwg-fetch';
import BigNumber from 'bignumber.js'; import {bigNumberConfigs} from '@0xproject/utils';
import {colors, getMuiTheme, MuiThemeProvider} from 'material-ui/styles'; import {MuiThemeProvider} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {render} from 'react-dom'; import {render} from 'react-dom';
import {Provider} from 'react-redux'; import {Provider} from 'react-redux';
@@ -19,59 +19,18 @@ import {NotFound} from 'ts/pages/not_found';
import {Wiki} from 'ts/pages/wiki/wiki'; import {Wiki} from 'ts/pages/wiki/wiki';
import {reducer, State} from 'ts/redux/reducer'; import {reducer, State} from 'ts/redux/reducer';
import {WebsitePaths} from 'ts/types'; import {WebsitePaths} from 'ts/types';
import {constants} from 'ts/utils/constants'; import {muiTheme} from 'ts/utils/mui_theme';
injectTapEventPlugin(); injectTapEventPlugin();
// By default BigNumber's `toString` method converts to exponential notation if the value has bigNumberConfigs.configure();
// more then 20 digits. We want to avoid this behavior, so we set EXPONENTIAL_AT to a high number
BigNumber.config({
EXPONENTIAL_AT: 1000,
});
// Check if we've introduced an update that requires us to clear the tradeHistory local storage entries // Check if we've introduced an update that requires us to clear the tradeHistory local storage entries
tradeHistoryStorage.clearIfRequired(); tradeHistoryStorage.clearIfRequired();
trackedTokenStorage.clearIfRequired(); trackedTokenStorage.clearIfRequired();
const CUSTOM_GREY = 'rgb(39, 39, 39)';
const CUSTOM_GREEN = 'rgb(102, 222, 117)';
const CUSTOM_DARKER_GREEN = 'rgb(77, 197, 92)';
import 'basscss/css/basscss.css'; import 'basscss/css/basscss.css';
import 'less/all.less'; import 'less/all.less';
const muiTheme = getMuiTheme({
appBar: {
height: 45,
color: 'white',
textColor: 'black',
},
palette: {
pickerHeaderColor: constants.CUSTOM_BLUE,
primary1Color: constants.CUSTOM_BLUE,
primary2Color: constants.CUSTOM_BLUE,
textColor: colors.grey700,
},
datePicker: {
color: colors.grey700,
textColor: 'white',
calendarTextColor: 'white',
selectColor: CUSTOM_GREY,
selectTextColor: 'white',
},
timePicker: {
color: colors.grey700,
textColor: 'white',
accentColor: 'white',
headerColor: CUSTOM_GREY,
selectColor: CUSTOM_GREY,
selectTextColor: CUSTOM_GREY,
},
toggle: {
thumbOnColor: CUSTOM_GREEN,
trackOnColor: CUSTOM_DARKER_GREEN,
},
});
// We pass modulePromise returning lambda instead of module promise, // We pass modulePromise returning lambda instead of module promise,
// cause we only want to import the module when the user navigates to the page. // cause we only want to import the module when the user navigates to the page.
// At the same time webpack statically parses for System.import() to determine bundle chunk split points // At the same time webpack statically parses for System.import() to determine bundle chunk split points

View File

@@ -11,10 +11,10 @@ export const trackedTokenStorage = {
// that introduced a backward incompatible change requiring the tracked tokens to be re-set // that introduced a backward incompatible change requiring the tracked tokens to be re-set
clearIfRequired() { clearIfRequired() {
const lastClearFillDate = localStorage.getItemIfExists(TRACKED_TOKENS_CLEAR_KEY); const lastClearFillDate = localStorage.getItemIfExists(TRACKED_TOKENS_CLEAR_KEY);
if (lastClearFillDate !== configs.lastLocalStorageTrackedTokenClearanceDate) { if (lastClearFillDate !== configs.LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE) {
localStorage.removeItem(TRACKED_TOKENS_KEY); localStorage.removeItem(TRACKED_TOKENS_KEY);
} }
localStorage.setItem(TRACKED_TOKENS_CLEAR_KEY, configs.lastLocalStorageTrackedTokenClearanceDate); localStorage.setItem(TRACKED_TOKENS_CLEAR_KEY, configs.LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE);
}, },
addTrackedTokenToUser(userAddress: string, networkId: number, token: Token) { addTrackedTokenToUser(userAddress: string, networkId: number, token: Token) {
const trackedTokensByUserAddress = this.getTrackedTokensByUserAddress(); const trackedTokensByUserAddress = this.getTrackedTokensByUserAddress();

View File

@@ -16,7 +16,7 @@ export const tradeHistoryStorage = {
// the blockchain // the blockchain
clearIfRequired() { clearIfRequired() {
const lastClearFillDate = localStorage.getItemIfExists(FILL_CLEAR_KEY); const lastClearFillDate = localStorage.getItemIfExists(FILL_CLEAR_KEY);
if (lastClearFillDate !== configs.lastLocalStorageFillClearanceDate) { if (lastClearFillDate !== configs.LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE) {
const localStorageKeys = localStorage.getAllKeys(); const localStorageKeys = localStorage.getAllKeys();
_.each(localStorageKeys, key => { _.each(localStorageKeys, key => {
if (_.startsWith(key, `${FILLS_KEY}-`) || _.startsWith(key, `${FILLS_LATEST_BLOCK}-`)) { if (_.startsWith(key, `${FILLS_KEY}-`) || _.startsWith(key, `${FILLS_LATEST_BLOCK}-`)) {
@@ -24,7 +24,7 @@ export const tradeHistoryStorage = {
} }
}); });
} }
localStorage.setItem(FILL_CLEAR_KEY, configs.lastLocalStorageFillClearanceDate); localStorage.setItem(FILL_CLEAR_KEY, configs.LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE);
}, },
addFillToUser(userAddress: string, networkId: number, fill: Fill) { addFillToUser(userAddress: string, networkId: number, fill: Fill) {
const fillsByHash = this.getUserFillsByHash(userAddress, networkId); const fillsByHash = this.getUserFillsByHash(userAddress, networkId);

View File

@@ -1,18 +1,14 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import * as DocumentTitle from 'react-document-title'; import * as DocumentTitle from 'react-document-title';
import {Footer} from 'ts/components/footer'; import {Footer} from 'ts/components/footer';
import {TopBar} from 'ts/components/top_bar'; import {TopBar} from 'ts/components/top_bar';
import {Profile} from 'ts/pages/about/profile'; import {Profile} from 'ts/pages/about/profile';
import {ProfileInfo, Styles} from 'ts/types'; import {ProfileInfo, Styles} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
const CUSTOM_BACKGROUND_COLOR = '#F0F0F0';
const CUSTOM_GRAY = '#4C4C4C';
const CUSTOM_LIGHT_GRAY = '#A2A2A2';
const teamRow1: ProfileInfo[] = [ const teamRow1: ProfileInfo[] = [
{ {
name: 'Will Warren', name: 'Will Warren',
@@ -145,6 +141,12 @@ const styles: Styles = {
color: 'black', color: 'black',
paddingTop: 110, paddingTop: 110,
}, },
weAreHiring: {
fontSize: 30,
color: colors.darkestGrey,
fontFamily: 'Roboto Mono',
letterSpacing: 7.5,
},
}; };
export class About extends React.Component<AboutProps, AboutState> { export class About extends React.Component<AboutProps, AboutState> {
@@ -153,12 +155,12 @@ export class About extends React.Component<AboutProps, AboutState> {
} }
public render() { public render() {
return ( return (
<div style={{backgroundColor: CUSTOM_BACKGROUND_COLOR}}> <div style={{backgroundColor: colors.lightestGrey}}>
<DocumentTitle title="0x About Us"/> <DocumentTitle title="0x About Us"/>
<TopBar <TopBar
blockchainIsLoaded={false} blockchainIsLoaded={false}
location={this.props.location} location={this.props.location}
style={{backgroundColor: CUSTOM_BACKGROUND_COLOR}} style={{backgroundColor: colors.lightestGrey}}
/> />
<div <div
id="about" id="about"
@@ -176,7 +178,7 @@ export class About extends React.Component<AboutProps, AboutState> {
</div> </div>
<div <div
className="pt3" className="pt3"
style={{fontSize: 17, color: CUSTOM_GRAY, lineHeight: 1.5}} style={{fontSize: 17, color: colors.darkestGrey, lineHeight: 1.5}}
> >
Our team is a diverse and globally distributed group with backgrounds Our team is a diverse and globally distributed group with backgrounds
in engineering, research, business and design. We are passionate about in engineering, research, business and design. We are passionate about
@@ -195,7 +197,7 @@ export class About extends React.Component<AboutProps, AboutState> {
<div className="pt3 pb2"> <div className="pt3 pb2">
<div <div
className="pt2 pb3 sm-center md-pl4 lg-pl0 md-ml3" className="pt2 pb3 sm-center md-pl4 lg-pl0 md-ml3"
style={{color: CUSTOM_LIGHT_GRAY, fontSize: 24, fontFamily: 'Roboto Mono'}} style={{color: colors.grey, fontSize: 24, fontFamily: 'Roboto Mono'}}
> >
Advisors: Advisors:
</div> </div>
@@ -206,17 +208,17 @@ export class About extends React.Component<AboutProps, AboutState> {
<div className="mx-auto py4 sm-px3" style={{maxWidth: 308}}> <div className="mx-auto py4 sm-px3" style={{maxWidth: 308}}>
<div <div
className="pb2" className="pb2"
style={{fontSize: 30, color: CUSTOM_GRAY, fontFamily: 'Roboto Mono', letterSpacing: 7.5}} style={styles.weAreHiring}
> >
WE'RE HIRING WE'RE HIRING
</div> </div>
<div <div
className="pb4 mb4" className="pb4 mb4"
style={{fontSize: 16, color: CUSTOM_GRAY, lineHeight: 1.5, letterSpacing: '0.5px'}} style={{fontSize: 16, color: colors.darkestGrey, lineHeight: 1.5, letterSpacing: '0.5px'}}
> >
We are seeking outstanding candidates to{' '} We are seeking outstanding candidates to{' '}
<a <a
href={constants.ANGELLIST_URL} href={constants.URL_ANGELLIST}
target="_blank" target="_blank"
style={{color: 'black'}} style={{color: 'black'}}
> >
@@ -226,7 +228,7 @@ export class About extends React.Component<AboutProps, AboutState> {
</div> </div>
</div> </div>
</div> </div>
<Footer location={this.props.location} /> <Footer />
</div> </div>
); );
} }

View File

@@ -1,6 +1,7 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as React from 'react'; import * as React from 'react';
import {ProfileInfo, Styles} from 'ts/types'; import {ProfileInfo, Styles} from 'ts/types';
import {colors} from 'ts/utils/colors';
const IMAGE_DIMENSION = 149; const IMAGE_DIMENSION = 149;
const styles: Styles = { const styles: Styles = {
@@ -48,7 +49,7 @@ export function Profile(props: ProfileProps) {
{!_.isUndefined(props.profileInfo.title) && {!_.isUndefined(props.profileInfo.title) &&
<div <div
className="pt1 center" className="pt1 center"
style={{fontSize: 14, fontFamily: 'Roboto Mono', color: '#818181'}} style={{fontSize: 14, fontFamily: 'Roboto Mono', color: colors.darkGrey}}
> >
{props.profileInfo.title.toUpperCase()} {props.profileInfo.title.toUpperCase()}
</div> </div>

View File

@@ -1,7 +1,6 @@
import findVersions = require('find-versions'); import findVersions = require('find-versions');
import * as _ from 'lodash'; import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress'; import CircularProgress from 'material-ui/CircularProgress';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import DocumentTitle = require('react-document-title'); import DocumentTitle = require('react-document-title');
import { import {
@@ -34,19 +33,18 @@ import {
TypeDefinitionByName, TypeDefinitionByName,
TypescriptMethod, TypescriptMethod,
} from 'ts/types'; } from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {docUtils} from 'ts/utils/doc_utils'; import {docUtils} from 'ts/utils/doc_utils';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
const SCROLL_TOP_ID = 'docsScrollTop'; const SCROLL_TOP_ID = 'docsScrollTop';
const CUSTOM_PURPLE = '#690596';
const CUSTOM_RED = '#e91751';
const CUSTOM_TURQUOIS = '#058789';
const networkNameToColor: {[network: string]: string} = { const networkNameToColor: {[network: string]: string} = {
[Networks.kovan]: CUSTOM_PURPLE, [Networks.kovan]: colors.purple,
[Networks.ropsten]: CUSTOM_RED, [Networks.ropsten]: colors.red,
[Networks.mainnet]: CUSTOM_TURQUOIS, [Networks.mainnet]: colors.turquois,
}; };
export interface DocumentationAllProps { export interface DocumentationAllProps {
@@ -273,7 +271,7 @@ export class Documentation extends
); );
} }
private renderNetworkBadgesIfExists(sectionName: string) { private renderNetworkBadgesIfExists(sectionName: string) {
const networkToAddressByContractName = constants.contractAddresses[this.props.docsVersion]; const networkToAddressByContractName = configs.CONTRACT_ADDRESS[this.props.docsVersion];
const badges = _.map(networkToAddressByContractName, const badges = _.map(networkToAddressByContractName,
(addressByContractName: AddressByContractName, networkName: string) => { (addressByContractName: AddressByContractName, networkName: string) => {
const contractAddress = addressByContractName[sectionName]; const contractAddress = addressByContractName[sectionName];
@@ -281,14 +279,14 @@ export class Documentation extends
return null; return null;
} }
const linkIfExists = utils.getEtherScanLinkIfExists( const linkIfExists = utils.getEtherScanLinkIfExists(
contractAddress, constants.networkIdByName[networkName], EtherscanLinkSuffixes.address, contractAddress, constants.NETWORK_ID_BY_NAME[networkName], EtherscanLinkSuffixes.Address,
); );
return ( return (
<a <a
key={`badge-${networkName}-${sectionName}`} key={`badge-${networkName}-${sectionName}`}
href={linkIfExists} href={linkIfExists}
target="_blank" target="_blank"
style={{color: 'white', textDecoration: 'none'}} style={{color: colors.white, textDecoration: 'none'}}
> >
<Badge <Badge
title={networkName} title={networkName}

View File

@@ -4,8 +4,7 @@ import {DocsInfo} from 'ts/pages/documentation/docs_info';
import {Type} from 'ts/pages/documentation/type'; import {Type} from 'ts/pages/documentation/type';
import {AnchorTitle} from 'ts/pages/shared/anchor_title'; import {AnchorTitle} from 'ts/pages/shared/anchor_title';
import {Event, EventArg, HeaderSizes} from 'ts/types'; import {Event, EventArg, HeaderSizes} from 'ts/types';
import {colors} from 'ts/utils/colors';
const CUSTOM_GREEN = 'rgb(77, 162, 75)';
interface EventDefinitionProps { interface EventDefinitionProps {
event: Event; event: Event;
@@ -50,7 +49,7 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event
); );
} }
private renderEventCode() { private renderEventCode() {
const indexed = <span style={{color: CUSTOM_GREEN}}> indexed</span>; const indexed = <span style={{color: colors.green}}> indexed</span>;
const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => { const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => {
const type = ( const type = (
<Type <Type

View File

@@ -1,5 +1,4 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Comment} from 'ts/pages/documentation/comment'; import {Comment} from 'ts/pages/documentation/comment';
import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {DocsInfo} from 'ts/pages/documentation/docs_info';
@@ -14,6 +13,7 @@ import {
TypeDefinitionByName, TypeDefinitionByName,
TypescriptMethod, TypescriptMethod,
} from 'ts/types'; } from 'ts/types';
import {colors} from 'ts/utils/colors';
import {typeDocUtils} from 'ts/utils/typedoc_utils'; import {typeDocUtils} from 'ts/utils/typedoc_utils';
interface MethodBlockProps { interface MethodBlockProps {
@@ -31,7 +31,7 @@ const styles: Styles = {
chip: { chip: {
fontSize: 13, fontSize: 13,
backgroundColor: colors.lightBlueA700, backgroundColor: colors.lightBlueA700,
color: 'white', color: colors.white,
height: 11, height: 11,
borderRadius: 14, borderRadius: 14,
marginTop: 19, marginTop: 19,
@@ -150,7 +150,7 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
<div className="bold"> <div className="bold">
{parameter.name} {parameter.name}
</div> </div>
<div className="pt1" style={{color: colors.grey500, fontSize: 14}}> <div className="pt1" style={{color: colors.grey, fontSize: 14}}>
{isOptional && 'optional'} {isOptional && 'optional'}
</div> </div>
</div> </div>

View File

@@ -1,7 +1,7 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Source} from 'ts/types'; import {Source} from 'ts/types';
import {colors} from 'ts/utils/colors';
interface SourceLinkProps { interface SourceLinkProps {
source: Source; source: Source;
@@ -29,7 +29,7 @@ export function SourceLink(props: SourceLinkProps) {
href={sourceCodeUrl} href={sourceCodeUrl}
target="_blank" target="_blank"
className="underline" className="underline"
style={{color: colors.grey500}} style={{color: colors.grey}}
> >
Source Source
</a> </a>

View File

@@ -1,24 +1,21 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Link as ScrollLink} from 'react-scroll'; import {Link as ScrollLink} from 'react-scroll';
import * as ReactTooltip from 'react-tooltip'; import * as ReactTooltip from 'react-tooltip';
import {DocsInfo} from 'ts/pages/documentation/docs_info'; import {DocsInfo} from 'ts/pages/documentation/docs_info';
import {TypeDefinition} from 'ts/pages/documentation/type_definition'; import {TypeDefinition} from 'ts/pages/documentation/type_definition';
import {Type as TypeDef, TypeDefinitionByName, TypeDocTypes} from 'ts/types'; import {Type as TypeDef, TypeDefinitionByName, TypeDocTypes} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
const BUILT_IN_TYPE_COLOR = '#e69d00';
const STRING_LITERAL_COLOR = '#4da24b';
// Some types reference other libraries. For these types, we want to link the user to the relevant documentation. // Some types reference other libraries. For these types, we want to link the user to the relevant documentation.
const typeToUrl: {[typeName: string]: string} = { const typeToUrl: {[typeName: string]: string} = {
Web3: constants.WEB3_DOCS_URL, Web3: constants.URL_WEB3_DOCS,
Provider: constants.WEB3_PROVIDER_DOCS_URL, Provider: constants.URL_WEB3_PROVIDER_DOCS,
BigNumber: constants.BIGNUMBERJS_GITHUB_URL, BigNumber: constants.URL_BIGNUMBERJS_GITHUB,
DecodedLogEntryEvent: constants.WEB3_DECODED_LOG_ENTRY_EVENT_URL, DecodedLogEntryEvent: constants.URL_WEB3_DECODED_LOG_ENTRY_EVENT,
LogEntryEvent: constants.WEB3_LOG_ENTRY_EVENT_URL, LogEntryEvent: constants.URL_WEB3_LOG_ENTRY_EVENT,
}; };
const typePrefix: {[typeName: string]: string} = { const typePrefix: {[typeName: string]: string} = {
@@ -56,7 +53,7 @@ export function Type(props: TypeProps): any {
case TypeDocTypes.Intrinsic: case TypeDocTypes.Intrinsic:
case TypeDocTypes.Unknown: case TypeDocTypes.Unknown:
typeName = type.name; typeName = type.name;
typeNameColor = BUILT_IN_TYPE_COLOR; typeNameColor = colors.orange;
break; break;
case TypeDocTypes.Reference: case TypeDocTypes.Reference:
@@ -90,7 +87,7 @@ export function Type(props: TypeProps): any {
case TypeDocTypes.StringLiteral: case TypeDocTypes.StringLiteral:
typeName = `'${type.value}'`; typeName = `'${type.value}'`;
typeNameColor = STRING_LITERAL_COLOR; typeNameColor = colors.green;
break; break;
case TypeDocTypes.Array: case TypeDocTypes.Array:

View File

@@ -9,10 +9,9 @@ import {MethodSignature} from 'ts/pages/documentation/method_signature';
import {Type} from 'ts/pages/documentation/type'; import {Type} from 'ts/pages/documentation/type';
import {AnchorTitle} from 'ts/pages/shared/anchor_title'; import {AnchorTitle} from 'ts/pages/shared/anchor_title';
import {CustomType, CustomTypeChild, HeaderSizes, KindString, TypeDocTypes} from 'ts/types'; import {CustomType, CustomTypeChild, HeaderSizes, KindString, TypeDocTypes} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
const KEYWORD_COLOR = '#a81ca6';
interface TypeDefinitionProps { interface TypeDefinitionProps {
customType: CustomType; customType: CustomType;
shouldAddId?: boolean; shouldAddId?: boolean;
@@ -76,11 +75,15 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
); );
break; break;
case KindString['Type alias']: case KindString.TypeAlias:
typePrefix = 'Type Alias'; typePrefix = 'Type Alias';
codeSnippet = ( codeSnippet = (
<span> <span>
<span style={{color: KEYWORD_COLOR}}>type</span> {customType.name} ={' '} <span
style={{color: colors.lightPurple}}
>
type
</span> {customType.name} ={' '}
{customType.type.typeDocType !== TypeDocTypes.Reflection ? {customType.type.typeDocType !== TypeDocTypes.Reflection ?
<Type type={customType.type} docsInfo={this.props.docsInfo} /> : <Type type={customType.type} docsInfo={this.props.docsInfo} /> :
<MethodSignature <MethodSignature

View File

@@ -1,11 +1,11 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import * as DocumentTitle from 'react-document-title'; import * as DocumentTitle from 'react-document-title';
import {Footer} from 'ts/components/footer'; import {Footer} from 'ts/components/footer';
import {TopBar} from 'ts/components/top_bar'; import {TopBar} from 'ts/components/top_bar';
import {Question} from 'ts/pages/faq/question'; import {Question} from 'ts/pages/faq/question';
import {FAQQuestion, FAQSection, Styles, WebsitePaths} from 'ts/types'; import {FAQQuestion, FAQSection, Styles, WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs'; import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
@@ -411,7 +411,7 @@ const sections: FAQSection[] = [
prompt: 'How can I get involved?', prompt: 'How can I get involved?',
answer: ( answer: (
<div> <div>
Join our <a href={constants.ZEROEX_CHAT_URL} target="_blank">Rocket.chat</a>! Join our <a href={constants.URL_ZEROEX_CHAT} target="_blank">Rocket.chat</a>!
As an open source project, 0x will rely on a worldwide community of passionate As an open source project, 0x will rely on a worldwide community of passionate
developers to contribute proposals, ideas and code. developers to contribute proposals, ideas and code.
</div> </div>
@@ -462,7 +462,7 @@ export class FAQ extends React.Component<FAQProps, FAQState> {
{this.renderSections()} {this.renderSections()}
</div> </div>
</div> </div>
<Footer location={this.props.location} /> <Footer />
</div> </div>
); );
} }

View File

@@ -1,6 +1,7 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import {Card, CardHeader, CardText} from 'material-ui/Card'; import {Card, CardHeader, CardText} from 'material-ui/Card';
import * as React from 'react'; import * as React from 'react';
import {colors} from 'ts/utils/colors';
export interface QuestionProps { export interface QuestionProps {
prompt: string; prompt: string;
@@ -31,7 +32,7 @@ export class Question extends React.Component<QuestionProps, QuestionState> {
<CardHeader <CardHeader
title={this.props.prompt} title={this.props.prompt}
style={{borderBottom: this.state.isExpanded ? '1px solid rgba(0, 0, 0, 0.19)' : 'none'}} style={{borderBottom: this.state.isExpanded ? '1px solid rgba(0, 0, 0, 0.19)' : 'none'}}
titleStyle={{color: 'rgb(66, 66, 66)'}} titleStyle={{color: colors.darkerGrey}}
actAsExpander={true} actAsExpander={true}
showExpandableButton={true} showExpandableButton={true}
/> />

View File

@@ -1,12 +1,12 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import RaisedButton from 'material-ui/RaisedButton'; import RaisedButton from 'material-ui/RaisedButton';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import DocumentTitle = require('react-document-title'); import DocumentTitle = require('react-document-title');
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import {Footer} from 'ts/components/footer'; import {Footer} from 'ts/components/footer';
import {TopBar} from 'ts/components/top_bar'; import {TopBar} from 'ts/components/top_bar';
import {ScreenWidths, WebsitePaths} from 'ts/types'; import {ScreenWidths, WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
@@ -35,11 +35,6 @@ interface Project {
} }
const THROTTLE_TIMEOUT = 100; const THROTTLE_TIMEOUT = 100;
const CUSTOM_HERO_BACKGROUND_COLOR = '#404040';
const CUSTOM_PROJECTS_BACKGROUND_COLOR = '#343333';
const CUSTOM_WHITE_BACKGROUND = 'rgb(245, 245, 245)';
const CUSTOM_WHITE_TEXT = '#E4E4E4';
const CUSTOM_GRAY_TEXT = '#919191';
const boxContents: BoxContent[] = [ const boxContents: BoxContent[] = [
{ {
@@ -70,67 +65,67 @@ const boxContents: BoxContent[] = [
const projects: Project[] = [ const projects: Project[] = [
{ {
logoFileName: 'ethfinex-top.png', logoFileName: 'ethfinex-top.png',
projectUrl: constants.ETHFINEX_URL, projectUrl: constants.PROJECT_URL_ETHFINEX,
}, },
{ {
logoFileName: 'radar_relay_top.png', logoFileName: 'radar_relay_top.png',
projectUrl: constants.RADAR_RELAY_URL, projectUrl: constants.PROJECT_URL_RADAR_RELAY,
}, },
{ {
logoFileName: 'paradex_top.png', logoFileName: 'paradex_top.png',
projectUrl: constants.PARADEX_URL, projectUrl: constants.PROJECT_URL_PARADEX,
}, },
{ {
logoFileName: 'the_ocean.png', logoFileName: 'the_ocean.png',
projectUrl: constants.OCEAN_URL, projectUrl: constants.PROJECT_URL_0CEAN,
}, },
{ {
logoFileName: 'dydx.png', logoFileName: 'dydx.png',
projectUrl: constants.DYDX_URL, projectUrl: constants.PROJECT_URL_DYDX,
}, },
{ {
logoFileName: 'melonport.png', logoFileName: 'melonport.png',
projectUrl: constants.MELONPORT_URL, projectUrl: constants.PROJECT_URL_MELONPORT,
}, },
{ {
logoFileName: 'maker.png', logoFileName: 'maker.png',
projectUrl: constants.MAKER_URL, projectUrl: constants.PROJECT_URL_MAKER,
}, },
{ {
logoFileName: 'dharma.png', logoFileName: 'dharma.png',
projectUrl: constants.DHARMA_URL, projectUrl: constants.PROJECT_URL_DHARMA,
}, },
{ {
logoFileName: 'lendroid.png', logoFileName: 'lendroid.png',
projectUrl: constants.LENDROID_URL, projectUrl: constants.PROJECT_URL_LENDROID,
}, },
{ {
logoFileName: 'district0x.png', logoFileName: 'district0x.png',
projectUrl: constants.DISTRICT_0X_URL, projectUrl: constants.PROJECT_URL_DISTRICT_0X,
}, },
{ {
logoFileName: 'aragon.png', logoFileName: 'aragon.png',
projectUrl: constants.ARAGON_URL, projectUrl: constants.PROJECT_URL_ARAGON,
}, },
{ {
logoFileName: 'blocknet.png', logoFileName: 'blocknet.png',
projectUrl: constants.BLOCKNET_URL, projectUrl: constants.PROJECT_URL_BLOCKNET,
}, },
{ {
logoFileName: 'status.png', logoFileName: 'status.png',
projectUrl: constants.STATUS_URL, projectUrl: constants.PROJECT_URL_STATUS,
}, },
{ {
logoFileName: 'augur.png', logoFileName: 'augur.png',
projectUrl: constants.AUGUR_URL, projectUrl: constants.PROJECT_URL_AUGUR,
}, },
{ {
logoFileName: 'anx.png', logoFileName: 'anx.png',
projectUrl: constants.OPEN_ANX_URL, projectUrl: constants.PROJECT_URL_OPEN_ANX,
}, },
{ {
logoFileName: 'auctus.png', logoFileName: 'auctus.png',
projectUrl: constants.AUCTUS_URL, projectUrl: constants.PROJECT_URL_AUCTUS,
}, },
]; ];
@@ -160,13 +155,13 @@ export class Landing extends React.Component<LandingProps, LandingState> {
} }
public render() { public render() {
return ( return (
<div id="landing" className="clearfix" style={{color: colors.grey800}}> <div id="landing" className="clearfix" style={{color: colors.grey500}}>
<DocumentTitle title="0x Protocol"/> <DocumentTitle title="0x Protocol"/>
<TopBar <TopBar
blockchainIsLoaded={false} blockchainIsLoaded={false}
location={this.props.location} location={this.props.location}
isNightVersion={true} isNightVersion={true}
style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR, position: 'relative'}} style={{backgroundColor: colors.heroGrey, position: 'relative'}}
/> />
{this.renderHero()} {this.renderHero()}
{this.renderProjects()} {this.renderProjects()}
@@ -176,12 +171,12 @@ export class Landing extends React.Component<LandingProps, LandingState> {
{this.renderBuildingBlocksSection()} {this.renderBuildingBlocksSection()}
{this.renderUseCases()} {this.renderUseCases()}
{this.renderCallToAction()} {this.renderCallToAction()}
<Footer location={this.props.location} /> <Footer />
</div> </div>
); );
} }
private renderHero() { private renderHero() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const buttonLabelStyle: React.CSSProperties = { const buttonLabelStyle: React.CSSProperties = {
textTransform: 'none', textTransform: 'none',
fontSize: isSmallScreen ? 12 : 14, fontSize: isSmallScreen ? 12 : 14,
@@ -197,7 +192,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
return ( return (
<div <div
className="clearfix py4" className="clearfix py4"
style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}} style={{backgroundColor: colors.heroGrey}}
> >
<div <div
className="mx-auto max-width-4 clearfix" className="mx-auto max-width-4 clearfix"
@@ -211,7 +206,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
<div <div
className={left} className={left}
style={{color: 'white'}} style={{color: colors.white}}
> >
<div style={{paddingLeft: isSmallScreen ? 0 : 12}}> <div style={{paddingLeft: isSmallScreen ? 0 : 12}}>
<div <div
@@ -241,7 +236,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
<div className="col col-6 sm-center"> <div className="col col-6 sm-center">
<a <a
href={constants.ZEROEX_CHAT_URL} href={constants.URL_ZEROEX_CHAT}
target="_blank" target="_blank"
className="text-decoration-none" className="text-decoration-none"
> >
@@ -249,7 +244,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
style={{borderRadius: 6, minWidth: 150}} style={{borderRadius: 6, minWidth: 150}}
buttonStyle={lightButtonStyle} buttonStyle={lightButtonStyle}
labelColor="white" labelColor="white"
backgroundColor={CUSTOM_HERO_BACKGROUND_COLOR} backgroundColor={colors.heroGrey}
labelStyle={buttonLabelStyle} labelStyle={buttonLabelStyle}
label="Join the community" label="Join the community"
onClick={_.noop} onClick={_.noop}
@@ -265,8 +260,8 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderProjects() { private renderProjects() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const isMediumScreen = this.state.screenWidth === ScreenWidths.MD; const isMediumScreen = this.state.screenWidth === ScreenWidths.Md;
const projectList = _.map(projects, (project: Project, i: number) => { const projectList = _.map(projects, (project: Project, i: number) => {
const colWidth = isSmallScreen ? 3 : (isMediumScreen ? 4 : 2 - (i % 2)); const colWidth = isSmallScreen ? 3 : (isMediumScreen ? 4 : 2 - (i % 2));
return ( return (
@@ -291,7 +286,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
}); });
const titleStyle: React.CSSProperties = { const titleStyle: React.CSSProperties = {
fontFamily: 'Roboto Mono', fontFamily: 'Roboto Mono',
color: '#A4A4A4', color: colors.grey,
textTransform: 'uppercase', textTransform: 'uppercase',
fontWeight: 300, fontWeight: 300,
letterSpacing: 3, letterSpacing: 3,
@@ -299,7 +294,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
return ( return (
<div <div
className="clearfix py4" className="clearfix py4"
style={{backgroundColor: CUSTOM_PROJECTS_BACKGROUND_COLOR}} style={{backgroundColor: colors.projectsGrey}}
> >
<div className="mx-auto max-width-4 clearfix sm-px3"> <div className="mx-auto max-width-4 clearfix sm-px3">
<div <div
@@ -313,13 +308,13 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
<div <div
className="pt3 mx-auto center" className="pt3 mx-auto center"
style={{color: CUSTOM_GRAY_TEXT, fontFamily: 'Roboto Mono', maxWidth: 300, fontSize: 14}} style={{color: colors.landingLinkGrey, fontFamily: 'Roboto Mono', maxWidth: 300, fontSize: 14}}
> >
view the{' '} view the{' '}
<Link <Link
to={`${WebsitePaths.Wiki}#List-of-Projects-Using-0x-Protocol`} to={`${WebsitePaths.Wiki}#List-of-Projects-Using-0x-Protocol`}
className="text-decoration-none underline" className="text-decoration-none underline"
style={{color: CUSTOM_GRAY_TEXT}} style={{color: colors.landingLinkGrey}}
> >
full list full list
</Link> </Link>
@@ -329,11 +324,11 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderTokenizationSection() { private renderTokenizationSection() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return ( return (
<div <div
className="clearfix lg-py4 md-py4 sm-pb4 sm-pt2" className="clearfix lg-py4 md-py4 sm-pb4 sm-pt2"
style={{backgroundColor: CUSTOM_WHITE_BACKGROUND}} style={{backgroundColor: colors.grey100}}
> >
<div className="mx-auto max-width-4 py4 clearfix"> <div className="mx-auto max-width-4 py4 clearfix">
{isSmallScreen && {isSmallScreen &&
@@ -382,11 +377,11 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderProtocolSection() { private renderProtocolSection() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return ( return (
<div <div
className="clearfix lg-py4 md-py4 sm-pt4" className="clearfix lg-py4 md-py4 sm-pt4"
style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}} style={{backgroundColor: colors.heroGrey}}
> >
<div className="mx-auto max-width-4 lg-py4 md-py4 sm-pt4 clearfix"> <div className="mx-auto max-width-4 lg-py4 md-py4 sm-pt4 clearfix">
<div className="col lg-col-6 md-col-6 col-12 sm-center"> <div className="col lg-col-6 md-col-6 col-12 sm-center">
@@ -397,7 +392,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
<div <div
className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-mx-auto" className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-mx-auto"
style={{color: CUSTOM_WHITE_TEXT, paddingTop: 8, maxWidth: isSmallScreen ? 'none' : 445}} style={{color: colors.beigeWhite, paddingTop: 8, maxWidth: isSmallScreen ? 'none' : 445}}
> >
<div <div
className="lg-h1 md-h1 sm-h2 pb1 sm-pt3 sm-center" className="lg-h1 md-h1 sm-h2 pb1 sm-pt3 sm-center"
@@ -420,7 +415,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
<div <div
className="pt3 sm-mx-auto sm-px3" className="pt3 sm-mx-auto sm-px3"
style={{color: CUSTOM_GRAY_TEXT, maxWidth: isSmallScreen ? 412 : 'none'}} style={{color: colors.landingLinkGrey, maxWidth: isSmallScreen ? 412 : 'none'}}
> >
<div className="flex" style={{fontSize: 18}}> <div className="flex" style={{fontSize: 18}}>
<div <div
@@ -433,7 +428,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
<Link <Link
to={`${WebsitePaths.Wiki}#List-of-Projects-Using-0x-Protocol`} to={`${WebsitePaths.Wiki}#List-of-Projects-Using-0x-Protocol`}
className="text-decoration-none underline" className="text-decoration-none underline"
style={{color: CUSTOM_GRAY_TEXT, fontFamily: 'Roboto Mono'}} style={{color: colors.landingLinkGrey, fontFamily: 'Roboto Mono'}}
> >
view all view all
</Link> </Link>
@@ -468,7 +463,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderBuildingBlocksSection() { private renderBuildingBlocksSection() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const descriptionStyle: React.CSSProperties = { const descriptionStyle: React.CSSProperties = {
fontFamily: 'Roboto Mono', fontFamily: 'Roboto Mono',
lineHeight: isSmallScreen ? 1.5 : 2, lineHeight: isSmallScreen ? 1.5 : 2,
@@ -485,7 +480,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
return ( return (
<div <div
className="clearfix lg-pt4 md-pt4" className="clearfix lg-pt4 md-pt4"
style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}} style={{backgroundColor: colors.heroGrey}}
> >
<div className="mx-auto max-width-4 lg-pt4 md-pt4 lg-mb4 md-mb4 sm-mb2 clearfix"> <div className="mx-auto max-width-4 lg-pt4 md-pt4 lg-mb4 md-mb4 sm-mb2 clearfix">
{isSmallScreen && {isSmallScreen &&
@@ -493,7 +488,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
} }
<div <div
className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-px3" className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-px3"
style={{color: CUSTOM_WHITE_TEXT}} style={{color: colors.beigeWhite}}
> >
<div <div
className="pb1 lg-pt4 md-pt4 sm-pt3 lg-h1 md-h1 sm-h2 sm-px3 sm-center" className="pb1 lg-pt4 md-pt4 sm-pt3 lg-h1 md-h1 sm-h2 sm-px3 sm-center"
@@ -517,7 +512,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
<Link <Link
to={WebsitePaths.ZeroExJs} to={WebsitePaths.ZeroExJs}
className="text-decoration-none underline" className="text-decoration-none underline"
style={{color: CUSTOM_WHITE_TEXT, fontFamily: 'Roboto Mono'}} style={{color: colors.beigeWhite, fontFamily: 'Roboto Mono'}}
> >
0x.js 0x.js
</Link> </Link>
@@ -525,7 +520,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
<Link <Link
to={WebsitePaths.SmartContracts} to={WebsitePaths.SmartContracts}
className="text-decoration-none underline" className="text-decoration-none underline"
style={{color: CUSTOM_WHITE_TEXT, fontFamily: 'Roboto Mono'}} style={{color: colors.beigeWhite, fontFamily: 'Roboto Mono'}}
> >
smart contract smart contract
</Link> </Link>
@@ -540,7 +535,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderBlockChipImage() { private renderBlockChipImage() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return ( return (
<div className="col lg-col-6 md-col-6 col-12 sm-center"> <div className="col lg-col-6 md-col-6 col-12 sm-center">
<img <img
@@ -551,7 +546,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderTokenCloud() { private renderTokenCloud() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return ( return (
<div className="col lg-col-6 md-col-6 col-12 center"> <div className="col lg-col-6 md-col-6 col-12 center">
<img <img
@@ -562,7 +557,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderAssetTypes() { private renderAssetTypes() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const assetTypes: AssetType[] = [ const assetTypes: AssetType[] = [
{ {
title: 'Currency', title: 'Currency',
@@ -601,11 +596,11 @@ export class Landing extends React.Component<LandingProps, LandingState> {
return assets; return assets;
} }
private renderInfoBoxes() { private renderInfoBoxes() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const boxStyle: React.CSSProperties = { const boxStyle: React.CSSProperties = {
maxWidth: 252, maxWidth: 252,
height: 386, height: 386,
backgroundColor: '#F9F9F9', backgroundColor: colors.grey50,
borderRadius: 5, borderRadius: 5,
padding: '10px 24px 24px', padding: '10px 24px 24px',
}; };
@@ -642,7 +637,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
return ( return (
<div <div
className="clearfix" className="clearfix"
style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}} style={{backgroundColor: colors.heroGrey}}
> >
<div <div
className="mx-auto py4 sm-mt2 clearfix" className="mx-auto py4 sm-mt2 clearfix"
@@ -654,7 +649,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderUseCases() { private renderUseCases() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const useCases: UseCase[] = [ const useCases: UseCase[] = [
{ {
@@ -709,14 +704,14 @@ export class Landing extends React.Component<LandingProps, LandingState> {
const cases = _.map(useCases, (useCase: UseCase) => { const cases = _.map(useCases, (useCase: UseCase) => {
const style = _.isUndefined(useCase.style) || isSmallScreen ? {} : useCase.style; const style = _.isUndefined(useCase.style) || isSmallScreen ? {} : useCase.style;
const useCaseBoxStyle = { const useCaseBoxStyle = {
color: '#A2A2A2', color: colors.grey,
border: '1px solid #565656', border: '1px solid #565656',
borderRadius: 4, borderRadius: 4,
maxWidth: isSmallScreen ? 375 : 'none', maxWidth: isSmallScreen ? 375 : 'none',
...style, ...style,
}; };
const typeStyle: React.CSSProperties = { const typeStyle: React.CSSProperties = {
color: '#EBEBEB', color: colors.lightGrey,
fontSize: 13, fontSize: 13,
textTransform: 'uppercase', textTransform: 'uppercase',
fontFamily: 'Roboto Mono', fontFamily: 'Roboto Mono',
@@ -753,7 +748,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
return ( return (
<div <div
className="clearfix pb4 lg-pt2 md-pt2 sm-pt4" className="clearfix pb4 lg-pt2 md-pt2 sm-pt4"
style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}} style={{backgroundColor: colors.heroGrey}}
> >
<div <div
className="mx-auto pb4 pt3 mt1 sm-mt2 clearfix" className="mx-auto pb4 pt3 mt1 sm-mt2 clearfix"
@@ -765,7 +760,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
); );
} }
private renderCallToAction() { private renderCallToAction() {
const isSmallScreen = this.state.screenWidth === ScreenWidths.SM; const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const buttonLabelStyle: React.CSSProperties = { const buttonLabelStyle: React.CSSProperties = {
textTransform: 'none', textTransform: 'none',
fontSize: 15, fontSize: 15,
@@ -782,14 +777,14 @@ export class Landing extends React.Component<LandingProps, LandingState> {
return ( return (
<div <div
className="clearfix pb4" className="clearfix pb4"
style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}} style={{backgroundColor: colors.heroGrey}}
> >
<div <div
className="mx-auto max-width-4 pb4 mb3 clearfix" className="mx-auto max-width-4 pb4 mb3 clearfix"
> >
<div <div
className={callToActionClassNames} className={callToActionClassNames}
style={{fontFamily: 'Roboto Mono', color: 'white', lineHeight: isSmallScreen ? 1.7 : 3}} style={{fontFamily: 'Roboto Mono', color: colors.white, lineHeight: isSmallScreen ? 1.7 : 3}}
> >
Get started on building the decentralized future Get started on building the decentralized future
</div> </div>
@@ -799,7 +794,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
style={{borderRadius: 6, minWidth: 150}} style={{borderRadius: 6, minWidth: 150}}
buttonStyle={lightButtonStyle} buttonStyle={lightButtonStyle}
labelColor={colors.white} labelColor={colors.white}
backgroundColor={CUSTOM_HERO_BACKGROUND_COLOR} backgroundColor={colors.heroGrey}
labelStyle={buttonLabelStyle} labelStyle={buttonLabelStyle}
label="Build on 0x" label="Build on 0x"
onClick={_.noop} onClick={_.noop}

View File

@@ -38,7 +38,7 @@ export class NotFound extends React.Component<NotFoundProps, NotFoundState> {
</div> </div>
</div> </div>
</div> </div>
<Footer location={this.props.location} /> <Footer />
</div> </div>
); );
} }

View File

@@ -1,10 +1,10 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import MenuItem from 'material-ui/MenuItem'; import MenuItem from 'material-ui/MenuItem';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import {Link as ScrollLink} from 'react-scroll'; import {Link as ScrollLink} from 'react-scroll';
import {VersionDropDown} from 'ts/pages/shared/version_drop_down'; import {VersionDropDown} from 'ts/pages/shared/version_drop_down';
import {MenuSubsectionsBySection, Styles} from 'ts/types'; import {MenuSubsectionsBySection, Styles} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
@@ -55,7 +55,7 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
containerId={constants.DOCS_CONTAINER_ID} containerId={constants.DOCS_CONTAINER_ID}
> >
<div <div
style={{color: colors.grey500, cursor: 'pointer'}} style={{color: colors.grey, cursor: 'pointer'}}
className="pb1" className="pb1"
> >
{finalSectionName.toUpperCase()} {finalSectionName.toUpperCase()}

View File

@@ -1,6 +1,5 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress'; import CircularProgress from 'material-ui/CircularProgress';
import {colors} from 'material-ui/styles';
import * as React from 'react'; import * as React from 'react';
import DocumentTitle = require('react-document-title'); import DocumentTitle = require('react-document-title');
import { import {
@@ -11,6 +10,7 @@ import {MarkdownSection} from 'ts/pages/shared/markdown_section';
import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu'; import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu';
import {SectionHeader} from 'ts/pages/shared/section_header'; import {SectionHeader} from 'ts/pages/shared/section_header';
import {Article, ArticlesBySection, HeaderSizes, Styles, WebsitePaths} from 'ts/types'; import {Article, ArticlesBySection, HeaderSizes, Styles, WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs'; import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils'; import {utils} from 'ts/utils/utils';
@@ -112,7 +112,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
> >
<div id="0xProtocolWiki" /> <div id="0xProtocolWiki" />
<h1 className="md-pl2 sm-pl3"> <h1 className="md-pl2 sm-pl3">
<a href={constants.GITHUB_WIKI_URL} target="_blank"> <a href={constants.URL_GITHUB_WIKI} target="_blank">
0x Protocol Wiki 0x Protocol Wiki
</a> </a>
</h1> </h1>
@@ -134,7 +134,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
private renderSection(sectionName: string) { private renderSection(sectionName: string) {
const articles = this.state.articlesBySection[sectionName]; const articles = this.state.articlesBySection[sectionName];
const renderedArticles = _.map(articles, (article: Article) => { const renderedArticles = _.map(articles, (article: Article) => {
const githubLink = `${constants.GITHUB_WIKI_URL}/edit/master/${sectionName}/${article.fileName}`; const githubLink = `${constants.URL_GITHUB_WIKI}/edit/master/${sectionName}/${article.fileName}`;
return ( return (
<div key={`markdown-section-${article.title}`}> <div key={`markdown-section-${article.title}`}>
<MarkdownSection <MarkdownSection
@@ -143,7 +143,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
headerSize={HeaderSizes.H2} headerSize={HeaderSizes.H2}
githubLink={githubLink} githubLink={githubLink}
/> />
<div className="mb4 mt3 p3 center" style={{backgroundColor: '#f9f5ef'}}> <div className="mb4 mt3 p3 center" style={{backgroundColor: colors.lightestGrey}}>
See a way to make this article better?{' '} See a way to make this article better?{' '}
<a <a
href={githubLink} href={githubLink}

View File

@@ -5,7 +5,6 @@ import {
ActionTypes, ActionTypes,
AssetToken, AssetToken,
BlockchainErrs, BlockchainErrs,
Direction,
Order, Order,
ProviderType, ProviderType,
ScreenWidths, ScreenWidths,
@@ -23,48 +22,42 @@ export class Dispatcher {
// Portal // Portal
public resetState() { public resetState() {
this.dispatch({ this.dispatch({
type: ActionTypes.RESET_STATE, type: ActionTypes.ResetState,
}); });
} }
public updateNodeVersion(nodeVersion: string) { public updateNodeVersion(nodeVersion: string) {
this.dispatch({ this.dispatch({
data: nodeVersion, data: nodeVersion,
type: ActionTypes.UPDATE_NODE_VERSION, type: ActionTypes.UpdateNodeVersion,
}); });
} }
public updateScreenWidth(screenWidth: ScreenWidths) { public updateScreenWidth(screenWidth: ScreenWidths) {
this.dispatch({ this.dispatch({
data: screenWidth, data: screenWidth,
type: ActionTypes.UPDATE_SCREEN_WIDTH, type: ActionTypes.UpdateScreenWidth,
}); });
} }
public swapAssetTokenSymbols() { public swapAssetTokenSymbols() {
this.dispatch({ this.dispatch({
type: ActionTypes.SWAP_ASSET_TOKENS, type: ActionTypes.SwapAssetTokens,
});
}
public updateGenerateOrderStep(direction: Direction) {
this.dispatch({
data: direction,
type: ActionTypes.UPDATE_GENERATE_ORDER_STEP,
}); });
} }
public updateOrderSalt(salt: BigNumber) { public updateOrderSalt(salt: BigNumber) {
this.dispatch({ this.dispatch({
data: salt, data: salt,
type: ActionTypes.UPDATE_ORDER_SALT, type: ActionTypes.UpdateOrderSalt,
}); });
} }
public updateUserSuppliedOrderCache(order: Order) { public updateUserSuppliedOrderCache(order: Order) {
this.dispatch({ this.dispatch({
data: order, data: order,
type: ActionTypes.UPDATE_USER_SUPPLIED_ORDER_CACHE, type: ActionTypes.UpdateUserSuppliedOrderCache,
}); });
} }
public updateShouldBlockchainErrDialogBeOpen(shouldBeOpen: boolean) { public updateShouldBlockchainErrDialogBeOpen(shouldBeOpen: boolean) {
this.dispatch({ this.dispatch({
data: shouldBeOpen, data: shouldBeOpen,
type: ActionTypes.UPDATE_SHOULD_BLOCKCHAIN_ERR_DIALOG_BE_OPEN, type: ActionTypes.UpdateShouldBlockchainErrDialogBeOpen,
}); });
} }
public updateChosenAssetToken(side: Side, token: AssetToken) { public updateChosenAssetToken(side: Side, token: AssetToken) {
@@ -73,7 +66,7 @@ export class Dispatcher {
side, side,
token, token,
}, },
type: ActionTypes.UPDATE_CHOSEN_ASSET_TOKEN, type: ActionTypes.UpdateChosenAssetToken,
}); });
} }
public updateChosenAssetTokenAddress(side: Side, address: string) { public updateChosenAssetTokenAddress(side: Side, address: string) {
@@ -82,72 +75,72 @@ export class Dispatcher {
address, address,
side, side,
}, },
type: ActionTypes.UPDATE_CHOSEN_ASSET_TOKEN_ADDRESS, type: ActionTypes.UpdateChosenAssetTokenAddress,
}); });
} }
public updateOrderTakerAddress(address: string) { public updateOrderTakerAddress(address: string) {
this.dispatch({ this.dispatch({
data: address, data: address,
type: ActionTypes.UPDATE_ORDER_TAKER_ADDRESS, type: ActionTypes.UpdateOrderTakerAddress,
}); });
} }
public updateUserAddress(address: string) { public updateUserAddress(address: string) {
this.dispatch({ this.dispatch({
data: address, data: address,
type: ActionTypes.UPDATE_USER_ADDRESS, type: ActionTypes.UpdateUserAddress,
}); });
} }
public updateOrderExpiry(unixTimestampSec: BigNumber) { public updateOrderExpiry(unixTimestampSec: BigNumber) {
this.dispatch({ this.dispatch({
data: unixTimestampSec, data: unixTimestampSec,
type: ActionTypes.UPDATE_ORDER_EXPIRY, type: ActionTypes.UpdateOrderExpiry,
}); });
} }
public encounteredBlockchainError(err: BlockchainErrs) { public encounteredBlockchainError(err: BlockchainErrs) {
this.dispatch({ this.dispatch({
data: err, data: err,
type: ActionTypes.BLOCKCHAIN_ERR_ENCOUNTERED, type: ActionTypes.BlockchainErrEncountered,
}); });
} }
public updateBlockchainIsLoaded(isLoaded: boolean) { public updateBlockchainIsLoaded(isLoaded: boolean) {
this.dispatch({ this.dispatch({
data: isLoaded, data: isLoaded,
type: ActionTypes.UPDATE_BLOCKCHAIN_IS_LOADED, type: ActionTypes.UpdateBlockchainIsLoaded,
}); });
} }
public addTokenToTokenByAddress(token: Token) { public addTokenToTokenByAddress(token: Token) {
this.dispatch({ this.dispatch({
data: token, data: token,
type: ActionTypes.ADD_TOKEN_TO_TOKEN_BY_ADDRESS, type: ActionTypes.AddTokenToTokenByAddress,
}); });
} }
public removeTokenToTokenByAddress(token: Token) { public removeTokenToTokenByAddress(token: Token) {
this.dispatch({ this.dispatch({
data: token, data: token,
type: ActionTypes.REMOVE_TOKEN_TO_TOKEN_BY_ADDRESS, type: ActionTypes.RemoveTokenFromTokenByAddress,
}); });
} }
public clearTokenByAddress() { public clearTokenByAddress() {
this.dispatch({ this.dispatch({
type: ActionTypes.CLEAR_TOKEN_BY_ADDRESS, type: ActionTypes.ClearTokenByAddress,
}); });
} }
public updateTokenByAddress(tokens: Token[]) { public updateTokenByAddress(tokens: Token[]) {
this.dispatch({ this.dispatch({
data: tokens, data: tokens,
type: ActionTypes.UPDATE_TOKEN_BY_ADDRESS, type: ActionTypes.UpdateTokenByAddress,
}); });
} }
public updateTokenStateByAddress(tokenStateByAddress: TokenStateByAddress) { public updateTokenStateByAddress(tokenStateByAddress: TokenStateByAddress) {
this.dispatch({ this.dispatch({
data: tokenStateByAddress, data: tokenStateByAddress,
type: ActionTypes.UPDATE_TOKEN_STATE_BY_ADDRESS, type: ActionTypes.UpdateTokenStateByAddress,
}); });
} }
public removeFromTokenStateByAddress(tokenAddress: string) { public removeFromTokenStateByAddress(tokenAddress: string) {
this.dispatch({ this.dispatch({
data: tokenAddress, data: tokenAddress,
type: ActionTypes.REMOVE_FROM_TOKEN_STATE_BY_ADDRESS, type: ActionTypes.RemoveFromTokenStateByAddress,
}); });
} }
public replaceTokenAllowanceByAddress(address: string, allowance: BigNumber) { public replaceTokenAllowanceByAddress(address: string, allowance: BigNumber) {
@@ -156,7 +149,7 @@ export class Dispatcher {
address, address,
allowance, allowance,
}, },
type: ActionTypes.REPLACE_TOKEN_ALLOWANCE_BY_ADDRESS, type: ActionTypes.ReplaceTokenAllowanceByAddress,
}); });
} }
public replaceTokenBalanceByAddress(address: string, balance: BigNumber) { public replaceTokenBalanceByAddress(address: string, balance: BigNumber) {
@@ -165,7 +158,7 @@ export class Dispatcher {
address, address,
balance, balance,
}, },
type: ActionTypes.REPLACE_TOKEN_BALANCE_BY_ADDRESS, type: ActionTypes.ReplaceTokenBalanceByAddress,
}); });
} }
public updateTokenBalanceByAddress(address: string, balanceDelta: BigNumber) { public updateTokenBalanceByAddress(address: string, balanceDelta: BigNumber) {
@@ -174,31 +167,31 @@ export class Dispatcher {
address, address,
balanceDelta, balanceDelta,
}, },
type: ActionTypes.UPDATE_TOKEN_BALANCE_BY_ADDRESS, type: ActionTypes.UpdateTokenBalanceByAddress,
}); });
} }
public updateSignatureData(signatureData: SignatureData) { public updateSignatureData(signatureData: SignatureData) {
this.dispatch({ this.dispatch({
data: signatureData, data: signatureData,
type: ActionTypes.UPDATE_ORDER_SIGNATURE_DATA, type: ActionTypes.UpdateOrderSignatureData,
}); });
} }
public updateUserEtherBalance(balance: BigNumber) { public updateUserEtherBalance(balance: BigNumber) {
this.dispatch({ this.dispatch({
data: balance, data: balance,
type: ActionTypes.UPDATE_USER_ETHER_BALANCE, type: ActionTypes.UpdateUserEtherBalance,
}); });
} }
public updateNetworkId(networkId: number) { public updateNetworkId(networkId: number) {
this.dispatch({ this.dispatch({
data: networkId, data: networkId,
type: ActionTypes.UPDATE_NETWORK_ID, type: ActionTypes.UpdateNetworkId,
}); });
} }
public updateOrderFillAmount(amount: BigNumber) { public updateOrderFillAmount(amount: BigNumber) {
this.dispatch({ this.dispatch({
data: amount, data: amount,
type: ActionTypes.UPDATE_ORDER_FILL_AMOUNT, type: ActionTypes.UpdateOrderFillAmount,
}); });
} }
@@ -206,13 +199,13 @@ export class Dispatcher {
public updateCurrentDocsVersion(version: string) { public updateCurrentDocsVersion(version: string) {
this.dispatch({ this.dispatch({
data: version, data: version,
type: ActionTypes.UPDATE_LIBRARY_VERSION, type: ActionTypes.UpdateLibraryVersion,
}); });
} }
public updateAvailableDocVersions(versions: string[]) { public updateAvailableDocVersions(versions: string[]) {
this.dispatch({ this.dispatch({
data: versions, data: versions,
type: ActionTypes.UPDATE_AVAILABLE_LIBRARY_VERSIONS, type: ActionTypes.UpdateAvailableLibraryVersions,
}); });
} }
@@ -220,23 +213,23 @@ export class Dispatcher {
public showFlashMessage(msg: string|React.ReactNode) { public showFlashMessage(msg: string|React.ReactNode) {
this.dispatch({ this.dispatch({
data: msg, data: msg,
type: ActionTypes.SHOW_FLASH_MESSAGE, type: ActionTypes.ShowFlashMessage,
}); });
} }
public hideFlashMessage() { public hideFlashMessage() {
this.dispatch({ this.dispatch({
type: ActionTypes.HIDE_FLASH_MESSAGE, type: ActionTypes.HideFlashMessage,
}); });
} }
public updateProviderType(providerType: ProviderType) { public updateProviderType(providerType: ProviderType) {
this.dispatch({ this.dispatch({
type: ActionTypes.UPDATE_PROVIDER_TYPE, type: ActionTypes.UpdateProviderType,
data: providerType, data: providerType,
}); });
} }
public updateInjectedProviderName(injectedProviderName: string) { public updateInjectedProviderName(injectedProviderName: string) {
this.dispatch({ this.dispatch({
type: ActionTypes.UPDATE_INJECTED_PROVIDER_NAME, type: ActionTypes.UpdateInjectedProviderName,
data: injectedProviderName, data: injectedProviderName,
}); });
} }

View File

@@ -5,8 +5,6 @@ import {
Action, Action,
ActionTypes, ActionTypes,
BlockchainErrs, BlockchainErrs,
Direction,
GenerateOrderSteps,
Order, Order,
ProviderType, ProviderType,
ScreenWidths, ScreenWidths,
@@ -28,7 +26,6 @@ export interface State {
// Portal // Portal
blockchainErr: BlockchainErrs; blockchainErr: BlockchainErrs;
blockchainIsLoaded: boolean; blockchainIsLoaded: boolean;
generateOrderStep: GenerateOrderSteps;
networkId: number; networkId: number;
orderExpiryTimestamp: BigNumber; orderExpiryTimestamp: BigNumber;
orderFillAmount: BigNumber; orderFillAmount: BigNumber;
@@ -58,9 +55,8 @@ export interface State {
const INITIAL_STATE: State = { const INITIAL_STATE: State = {
// Portal // Portal
blockchainErr: '', blockchainErr: BlockchainErrs.NoError,
blockchainIsLoaded: false, blockchainIsLoaded: false,
generateOrderStep: GenerateOrderSteps.ChooseAssets,
networkId: undefined, networkId: undefined,
orderExpiryTimestamp: utils.initialOrderExpiryUnixTimestampSec(), orderExpiryTimestamp: utils.initialOrderExpiryUnixTimestampSec(),
orderFillAmount: undefined, orderFillAmount: undefined,
@@ -76,8 +72,8 @@ const INITIAL_STATE: State = {
screenWidth: utils.getScreenWidth(), screenWidth: utils.getScreenWidth(),
shouldBlockchainErrDialogBeOpen: false, shouldBlockchainErrDialogBeOpen: false,
sideToAssetToken: { sideToAssetToken: {
[Side.deposit]: {}, [Side.Deposit]: {},
[Side.receive]: {}, [Side.Receive]: {},
}, },
tokenByAddress: {}, tokenByAddress: {},
tokenStateByAddress: {}, tokenStateByAddress: {},
@@ -91,270 +87,300 @@ const INITIAL_STATE: State = {
// Shared // Shared
flashMessage: undefined, flashMessage: undefined,
providerType: ProviderType.INJECTED, providerType: ProviderType.Injected,
injectedProviderName: '', injectedProviderName: '',
}; };
export function reducer(state: State = INITIAL_STATE, action: Action) { export function reducer(state: State = INITIAL_STATE, action: Action) {
switch (action.type) { switch (action.type) {
// Portal // Portal
case ActionTypes.RESET_STATE: case ActionTypes.ResetState:
return INITIAL_STATE; return INITIAL_STATE;
case ActionTypes.UPDATE_ORDER_SALT: { case ActionTypes.UpdateOrderSalt: {
return _.assign({}, state, { return {
...state,
orderSalt: action.data, orderSalt: action.data,
}); };
} }
case ActionTypes.UPDATE_NODE_VERSION: { case ActionTypes.UpdateNodeVersion: {
return _.assign({}, state, { return {
...state,
nodeVersion: action.data, nodeVersion: action.data,
}); };
} }
case ActionTypes.UPDATE_ORDER_FILL_AMOUNT: { case ActionTypes.UpdateOrderFillAmount: {
return _.assign({}, state, { return {
...state,
orderFillAmount: action.data, orderFillAmount: action.data,
}); };
} }
case ActionTypes.UPDATE_SHOULD_BLOCKCHAIN_ERR_DIALOG_BE_OPEN: { case ActionTypes.UpdateShouldBlockchainErrDialogBeOpen: {
return _.assign({}, state, { return {
...state,
shouldBlockchainErrDialogBeOpen: action.data, shouldBlockchainErrDialogBeOpen: action.data,
}); };
} }
case ActionTypes.UPDATE_USER_ETHER_BALANCE: { case ActionTypes.UpdateUserEtherBalance: {
return _.assign({}, state, { return {
...state,
userEtherBalance: action.data, userEtherBalance: action.data,
}); };
} }
case ActionTypes.UPDATE_USER_SUPPLIED_ORDER_CACHE: { case ActionTypes.UpdateUserSuppliedOrderCache: {
return _.assign({}, state, { return {
...state,
userSuppliedOrderCache: action.data, userSuppliedOrderCache: action.data,
}); };
} }
case ActionTypes.CLEAR_TOKEN_BY_ADDRESS: { case ActionTypes.ClearTokenByAddress: {
return _.assign({}, state, { return {
...state,
tokenByAddress: {}, tokenByAddress: {},
}); };
} }
case ActionTypes.ADD_TOKEN_TO_TOKEN_BY_ADDRESS: { case ActionTypes.AddTokenToTokenByAddress: {
const newTokenByAddress = state.tokenByAddress; const newTokenByAddress = state.tokenByAddress;
newTokenByAddress[action.data.address] = action.data; newTokenByAddress[action.data.address] = action.data;
return _.assign({}, state, { return {
...state,
tokenByAddress: newTokenByAddress, tokenByAddress: newTokenByAddress,
}); };
} }
case ActionTypes.REMOVE_TOKEN_TO_TOKEN_BY_ADDRESS: { case ActionTypes.RemoveTokenFromTokenByAddress: {
const newTokenByAddress = state.tokenByAddress; const newTokenByAddress = state.tokenByAddress;
delete newTokenByAddress[action.data.address]; delete newTokenByAddress[action.data.address];
return _.assign({}, state, { return {
...state,
tokenByAddress: newTokenByAddress, tokenByAddress: newTokenByAddress,
}); };
} }
case ActionTypes.UPDATE_TOKEN_BY_ADDRESS: { case ActionTypes.UpdateTokenByAddress: {
const tokenByAddress = state.tokenByAddress; const tokenByAddress = state.tokenByAddress;
const tokens = action.data; const tokens = action.data;
_.each(tokens, token => { _.each(tokens, token => {
const updatedToken = _.assign({}, tokenByAddress[token.address], token); const updatedToken = {
...tokenByAddress[token.address],
...token,
};
tokenByAddress[token.address] = updatedToken; tokenByAddress[token.address] = updatedToken;
}); });
return _.assign({}, state, { return {
...state,
tokenByAddress, tokenByAddress,
}); };
} }
case ActionTypes.UPDATE_TOKEN_STATE_BY_ADDRESS: { case ActionTypes.UpdateTokenStateByAddress: {
const tokenStateByAddress = state.tokenStateByAddress; const tokenStateByAddress = state.tokenStateByAddress;
const updatedTokenStateByAddress = action.data; const updatedTokenStateByAddress = action.data;
_.each(updatedTokenStateByAddress, (tokenState: TokenState, address: string) => { _.each(updatedTokenStateByAddress, (tokenState: TokenState, address: string) => {
const updatedTokenState = _.assign({}, tokenStateByAddress[address], tokenState); const updatedTokenState = {
...tokenStateByAddress[address],
...tokenState,
};
tokenStateByAddress[address] = updatedTokenState; tokenStateByAddress[address] = updatedTokenState;
}); });
return _.assign({}, state, { return {
...state,
tokenStateByAddress, tokenStateByAddress,
}); };
} }
case ActionTypes.REMOVE_FROM_TOKEN_STATE_BY_ADDRESS: { case ActionTypes.RemoveFromTokenStateByAddress: {
const tokenStateByAddress = state.tokenStateByAddress; const tokenStateByAddress = state.tokenStateByAddress;
const tokenAddress = action.data; const tokenAddress = action.data;
delete tokenStateByAddress[tokenAddress]; delete tokenStateByAddress[tokenAddress];
return _.assign({}, state, { return {
...state,
tokenStateByAddress, tokenStateByAddress,
}); };
} }
case ActionTypes.REPLACE_TOKEN_ALLOWANCE_BY_ADDRESS: { case ActionTypes.ReplaceTokenAllowanceByAddress: {
const tokenStateByAddress = state.tokenStateByAddress; const tokenStateByAddress = state.tokenStateByAddress;
const allowance = action.data.allowance; const allowance = action.data.allowance;
const tokenAddress = action.data.address; const tokenAddress = action.data.address;
tokenStateByAddress[tokenAddress] = _.assign({}, tokenStateByAddress[tokenAddress], { tokenStateByAddress[tokenAddress] = {
...tokenStateByAddress[tokenAddress],
allowance, allowance,
}); };
return _.assign({}, state, { return {
...state,
tokenStateByAddress, tokenStateByAddress,
}); };
} }
case ActionTypes.REPLACE_TOKEN_BALANCE_BY_ADDRESS: { case ActionTypes.ReplaceTokenBalanceByAddress: {
const tokenStateByAddress = state.tokenStateByAddress; const tokenStateByAddress = state.tokenStateByAddress;
const balance = action.data.balance; const balance = action.data.balance;
const tokenAddress = action.data.address; const tokenAddress = action.data.address;
tokenStateByAddress[tokenAddress] = _.assign({}, tokenStateByAddress[tokenAddress], { tokenStateByAddress[tokenAddress] = {
...tokenStateByAddress[tokenAddress],
balance, balance,
}); };
return _.assign({}, state, { return {
...state,
tokenStateByAddress, tokenStateByAddress,
}); };
} }
case ActionTypes.UPDATE_TOKEN_BALANCE_BY_ADDRESS: { case ActionTypes.UpdateTokenBalanceByAddress: {
const tokenStateByAddress = state.tokenStateByAddress; const tokenStateByAddress = state.tokenStateByAddress;
const balanceDelta = action.data.balanceDelta; const balanceDelta = action.data.balanceDelta;
const tokenAddress = action.data.address; const tokenAddress = action.data.address;
const currBalance = tokenStateByAddress[tokenAddress].balance; const currBalance = tokenStateByAddress[tokenAddress].balance;
tokenStateByAddress[tokenAddress] = _.assign({}, tokenStateByAddress[tokenAddress], { tokenStateByAddress[tokenAddress] = {
...tokenStateByAddress[tokenAddress],
balance: currBalance.plus(balanceDelta), balance: currBalance.plus(balanceDelta),
}); };
return _.assign({}, state, { return {
...state,
tokenStateByAddress, tokenStateByAddress,
}); };
} }
case ActionTypes.UPDATE_ORDER_SIGNATURE_DATA: { case ActionTypes.UpdateOrderSignatureData: {
return _.assign({}, state, { return {
...state,
orderSignatureData: action.data, orderSignatureData: action.data,
}); };
} }
case ActionTypes.UPDATE_SCREEN_WIDTH: { case ActionTypes.UpdateScreenWidth: {
return _.assign({}, state, { return {
...state,
screenWidth: action.data, screenWidth: action.data,
}); };
} }
case ActionTypes.UPDATE_BLOCKCHAIN_IS_LOADED: { case ActionTypes.UpdateBlockchainIsLoaded: {
return _.assign({}, state, { return {
...state,
blockchainIsLoaded: action.data, blockchainIsLoaded: action.data,
}); };
} }
case ActionTypes.BLOCKCHAIN_ERR_ENCOUNTERED: { case ActionTypes.BlockchainErrEncountered: {
return _.assign({}, state, { return {
...state,
blockchainErr: action.data, blockchainErr: action.data,
}); };
} }
case ActionTypes.UPDATE_NETWORK_ID: { case ActionTypes.UpdateNetworkId: {
return _.assign({}, state, { return {
...state,
networkId: action.data, networkId: action.data,
}); };
} }
case ActionTypes.UPDATE_GENERATE_ORDER_STEP: { case ActionTypes.UpdateChosenAssetToken: {
const direction = action.data; const newSideToAssetToken = {
let nextGenerateOrderStep = state.generateOrderStep; ...state.sideToAssetToken,
if (direction === Direction.forward) {
nextGenerateOrderStep += 1;
} else if (state.generateOrderStep !== 0) {
nextGenerateOrderStep -= 1;
}
return _.assign({}, state, {
generateOrderStep: nextGenerateOrderStep,
});
}
case ActionTypes.UPDATE_CHOSEN_ASSET_TOKEN: {
const newSideToAssetToken = _.assign({}, state.sideToAssetToken, {
[action.data.side]: action.data.token, [action.data.side]: action.data.token,
}); };
return _.assign({}, state, { return {
...state,
sideToAssetToken: newSideToAssetToken, sideToAssetToken: newSideToAssetToken,
}); };
} }
case ActionTypes.UPDATE_CHOSEN_ASSET_TOKEN_ADDRESS: { case ActionTypes.UpdateChosenAssetTokenAddress: {
const newAssetToken = state.sideToAssetToken[action.data.side]; const newAssetToken = state.sideToAssetToken[action.data.side];
newAssetToken.address = action.data.address; newAssetToken.address = action.data.address;
const newSideToAssetToken = _.assign({}, state.sideToAssetToken, { const newSideToAssetToken = {
...state.sideToAssetToken,
[action.data.side]: newAssetToken, [action.data.side]: newAssetToken,
}); };
return _.assign({}, state, { return {
...state,
sideToAssetToken: newSideToAssetToken, sideToAssetToken: newSideToAssetToken,
}); };
} }
case ActionTypes.SWAP_ASSET_TOKENS: { case ActionTypes.SwapAssetTokens: {
const newSideToAssetToken = _.assign({}, state.sideToAssetToken, { const newSideToAssetToken = {
[Side.deposit]: state.sideToAssetToken[Side.receive], [Side.Deposit]: state.sideToAssetToken[Side.Receive],
[Side.receive]: state.sideToAssetToken[Side.deposit], [Side.Receive]: state.sideToAssetToken[Side.Deposit],
}); };
return _.assign({}, state, { return {
...state,
sideToAssetToken: newSideToAssetToken, sideToAssetToken: newSideToAssetToken,
}); };
} }
case ActionTypes.UPDATE_ORDER_EXPIRY: { case ActionTypes.UpdateOrderExpiry: {
return _.assign({}, state, { return {
...state,
orderExpiryTimestamp: action.data, orderExpiryTimestamp: action.data,
}); };
} }
case ActionTypes.UPDATE_ORDER_TAKER_ADDRESS: { case ActionTypes.UpdateOrderTakerAddress: {
return _.assign({}, state, { return {
...state,
orderTakerAddress: action.data, orderTakerAddress: action.data,
}); };
} }
case ActionTypes.UPDATE_USER_ADDRESS: { case ActionTypes.UpdateUserAddress: {
return _.assign({}, state, { return {
...state,
userAddress: action.data, userAddress: action.data,
}); };
} }
// Docs // Docs
case ActionTypes.UPDATE_LIBRARY_VERSION: { case ActionTypes.UpdateLibraryVersion: {
return _.assign({}, state, { return {
...state,
docsVersion: action.data, docsVersion: action.data,
}); };
} }
case ActionTypes.UPDATE_AVAILABLE_LIBRARY_VERSIONS: { case ActionTypes.UpdateAvailableLibraryVersions: {
return _.assign({}, state, { return {
...state,
availableDocVersions: action.data, availableDocVersions: action.data,
}); };
} }
// Shared // Shared
case ActionTypes.SHOW_FLASH_MESSAGE: { case ActionTypes.ShowFlashMessage: {
return _.assign({}, state, { return {
...state,
flashMessage: action.data, flashMessage: action.data,
}); };
} }
case ActionTypes.HIDE_FLASH_MESSAGE: { case ActionTypes.HideFlashMessage: {
return _.assign({}, state, { return {
...state,
flashMessage: undefined, flashMessage: undefined,
}); };
} }
case ActionTypes.UPDATE_PROVIDER_TYPE: { case ActionTypes.UpdateProviderType: {
return _.assign({}, state, { return {
...state,
providerType: action.data, providerType: action.data,
}); };
} }
case ActionTypes.UPDATE_INJECTED_PROVIDER_NAME: { case ActionTypes.UpdateInjectedProviderName: {
return _.assign({}, state, { return {
...state,
injectedProviderName: action.data, injectedProviderName: action.data,
}); };
} }
default: default:

View File

@@ -1,42 +1,11 @@
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import * as _ from 'lodash'; import * as _ from 'lodash';
// Utility function to create a K:V from a list of strings export enum Side {
// Adapted from: https://basarat.gitbooks.io/typescript/content/docs/types/literal-types.html Receive = 'RECEIVE',
function strEnum(values: string[]): {[key: string]: string} { Deposit = 'DEPOSIT',
return _.reduce(values, (result, key) => {
result[key] = key;
return result;
}, Object.create(null));
} }
export enum GenerateOrderSteps {
ChooseAssets,
GrantAllowance,
RemainingConfigs,
SignTransaction,
CopyAndShare,
}
export const Side = strEnum([
'receive',
'deposit',
]);
export type Side = keyof typeof Side;
export const BlockchainErrs = strEnum([
'A_CONTRACT_NOT_DEPLOYED_ON_NETWORK',
'DISCONNECTED_FROM_ETHEREUM_NODE',
'UNHANDLED_ERROR',
]);
export type BlockchainErrs = keyof typeof BlockchainErrs;
export const Direction = strEnum([
'forward',
'backward',
]);
export type Direction = keyof typeof Direction;
export interface Token { export interface Token {
iconUrl?: string; iconUrl?: string;
name: string; name: string;
@@ -139,48 +108,46 @@ export enum BalanceErrs {
allowanceSettingFailed, allowanceSettingFailed,
} }
export const ActionTypes = strEnum([ export enum ActionTypes {
// Portal // Portal
'UPDATE_SCREEN_WIDTH', UpdateScreenWidth = 'UPDATE_SCREEN_WIDTH',
'UPDATE_NODE_VERSION', UpdateNodeVersion = 'UPDATE_NODE_VERSION',
'RESET_STATE', ResetState = 'RESET_STATE',
'ADD_TOKEN_TO_TOKEN_BY_ADDRESS', AddTokenToTokenByAddress = 'ADD_TOKEN_TO_TOKEN_BY_ADDRESS',
'BLOCKCHAIN_ERR_ENCOUNTERED', BlockchainErrEncountered = 'BLOCKCHAIN_ERR_ENCOUNTERED',
'CLEAR_TOKEN_BY_ADDRESS', ClearTokenByAddress = 'CLEAR_TOKEN_BY_ADDRESS',
'UPDATE_BLOCKCHAIN_IS_LOADED', UpdateBlockchainIsLoaded = 'UPDATE_BLOCKCHAIN_IS_LOADED',
'UPDATE_NETWORK_ID', UpdateNetworkId = 'UPDATE_NETWORK_ID',
'UPDATE_GENERATE_ORDER_STEP', UpdateChosenAssetToken = 'UPDATE_CHOSEN_ASSET_TOKEN',
'UPDATE_CHOSEN_ASSET_TOKEN', UpdateChosenAssetTokenAddress = 'UPDATE_CHOSEN_ASSET_TOKEN_ADDRESS',
'UPDATE_CHOSEN_ASSET_TOKEN_ADDRESS', UpdateOrderTakerAddress = 'UPDATE_ORDER_TAKER_ADDRESS',
'UPDATE_ORDER_TAKER_ADDRESS', UpdateOrderSalt = 'UPDATE_ORDER_SALT',
'UPDATE_ORDER_SALT', UpdateOrderSignatureData = 'UPDATE_ORDER_SIGNATURE_DATA',
'UPDATE_ORDER_SIGNATURE_DATA', UpdateTokenByAddress = 'UPDATE_TOKEN_BY_ADDRESS',
'UPDATE_TOKEN_BY_ADDRESS', RemoveTokenFromTokenByAddress = 'REMOVE_TOKEN_FROM_TOKEN_BY_ADDRESS',
'REMOVE_TOKEN_TO_TOKEN_BY_ADDRESS', UpdateTokenStateByAddress = 'UPDATE_TOKEN_STATE_BY_ADDRESS',
'UPDATE_TOKEN_STATE_BY_ADDRESS', RemoveFromTokenStateByAddress = 'REMOVE_FROM_TOKEN_STATE_BY_ADDRESS',
'REMOVE_FROM_TOKEN_STATE_BY_ADDRESS', ReplaceTokenAllowanceByAddress = 'REPLACE_TOKEN_ALLOWANCE_BY_ADDRESS',
'REPLACE_TOKEN_ALLOWANCE_BY_ADDRESS', ReplaceTokenBalanceByAddress = 'REPLACE_TOKEN_BALANCE_BY_ADDRESS',
'REPLACE_TOKEN_BALANCE_BY_ADDRESS', UpdateTokenBalanceByAddress = 'UPDATE_TOKEN_BALANCE_BY_ADDRESS',
'UPDATE_TOKEN_BALANCE_BY_ADDRESS', UpdateOrderExpiry = 'UPDATE_ORDER_EXPIRY',
'UPDATE_ORDER_EXPIRY', SwapAssetTokens = 'SWAP_ASSET_TOKENS',
'SWAP_ASSET_TOKENS', UpdateUserAddress = 'UPDATE_USER_ADDRESS',
'UPDATE_USER_ADDRESS', UpdateUserEtherBalance = 'UPDATE_USER_ETHER_BALANCE',
'UPDATE_USER_ETHER_BALANCE', UpdateUserSuppliedOrderCache = 'UPDATE_USER_SUPPLIED_ORDER_CACHE',
'UPDATE_USER_SUPPLIED_ORDER_CACHE', UpdateOrderFillAmount = 'UPDATE_ORDER_FILL_AMOUNT',
'UPDATE_ORDER_FILL_AMOUNT', UpdateShouldBlockchainErrDialogBeOpen = 'UPDATE_SHOULD_BLOCKCHAIN_ERR_DIALOG_BE_OPEN',
'UPDATE_SHOULD_BLOCKCHAIN_ERR_DIALOG_BE_OPEN',
// Docs // Docs
'UPDATE_LIBRARY_VERSION', UpdateLibraryVersion = 'UPDATE_LIBRARY_VERSION',
'UPDATE_AVAILABLE_LIBRARY_VERSIONS', UpdateAvailableLibraryVersions = 'UPDATE_AVAILABLE_LIBRARY_VERSIONS',
// Shared // Shared
'SHOW_FLASH_MESSAGE', ShowFlashMessage = 'SHOW_FLASH_MESSAGE',
'HIDE_FLASH_MESSAGE', HideFlashMessage = 'HIDE_FLASH_MESSAGE',
'UPDATE_PROVIDER_TYPE', UpdateProviderType = 'UPDATE_PROVIDER_TYPE',
'UPDATE_INJECTED_PROVIDER_NAME', UpdateInjectedProviderName = 'UPDATE_INJECTED_PROVIDER_NAME',
]); }
export type ActionTypes = keyof typeof ActionTypes;
export interface Action { export interface Action {
type: ActionTypes; type: ActionTypes;
@@ -253,44 +220,47 @@ export interface ContractEvent {
export type InputErrMsg = React.ReactNode | string | undefined; export type InputErrMsg = React.ReactNode | string | undefined;
export type ValidatedBigNumberCallback = (isValid: boolean, amount?: BigNumber) => void; export type ValidatedBigNumberCallback = (isValid: boolean, amount?: BigNumber) => void;
export const ScreenWidths = strEnum([ export enum ScreenWidths {
'SM', Sm = 'SM',
'MD', Md = 'MD',
'LG', Lg = 'LG',
]); }
export type ScreenWidths = keyof typeof ScreenWidths;
export enum AlertTypes { export enum AlertTypes {
ERROR, ERROR,
SUCCESS, SUCCESS,
} }
export const EtherscanLinkSuffixes = strEnum([ export enum EtherscanLinkSuffixes {
'address', Address = 'address',
'tx', Tx = 'tx',
]); }
export type EtherscanLinkSuffixes = keyof typeof EtherscanLinkSuffixes;
export const BlockchainCallErrs = strEnum([ export enum BlockchainErrs {
'CONTRACT_DOES_NOT_EXIST', AContractNotDeployedOnNetwork = 'A_CONTRACT_NOT_DEPLOYED_ON_NETWORK',
'USER_HAS_NO_ASSOCIATED_ADDRESSES', DisconnectedFromEthereumNode = 'DISCONNECTED_FROM_ETHEREUM_NODE',
'UNHANDLED_ERROR', NoError = 'NO_ERROR',
'TOKEN_ADDRESS_IS_INVALID', }
'INVALID_SIGNATURE',
]);
export type BlockchainCallErrs = keyof typeof BlockchainCallErrs;
export const KindString = strEnum([ export enum BlockchainCallErrs {
'Constructor', ContractDoesNotExist = 'CONTRACT_DOES_NOT_EXIST',
'Property', UserHasNoAssociatedAddresses = 'USER_HAS_NO_ASSOCIATED_ADDRESSES',
'Method', UnhandledError = 'UNHANDLED_ERROR',
'Interface', TokenAddressIsInvalid = 'TOKEN_ADDRESS_IS_INVALID',
'Type alias', }
'Variable',
'Function', // Exception: We don't make the values uppercase because these KindString's need to
'Enumeration', // match up those returned by TypeDoc
]); export enum KindString {
export type KindString = keyof typeof KindString; Constructor = 'Constructor',
Property = 'Property',
Method = 'Method',
Interface = 'Interface',
TypeAlias = 'Type alias',
Variable = 'Variable',
Function = 'Function',
Enumeration = 'Enumeration',
}
export interface EnumValue { export interface EnumValue {
name: string; name: string;
@@ -486,11 +456,10 @@ export interface MenuSubsectionsBySection {
[section: string]: string[]; [section: string]: string[];
} }
export const ProviderType = strEnum([ export enum ProviderType {
'INJECTED', Injected = 'INJECTED',
'LEDGER', Ledger = 'LEDGER',
]); }
export type ProviderType = keyof typeof ProviderType;
export interface Fact { export interface Fact {
title: string; title: string;
@@ -694,4 +663,12 @@ export interface OutdatedWrappedEtherByNetworkId {
}; };
} }
export enum SmartContractDocSections {
Introduction = 'Introduction',
Exchange = 'Exchange',
TokenTransferProxy = 'TokenTransferProxy',
TokenRegistry = 'TokenRegistry',
ZRXToken = 'ZRXToken',
}
// tslint:disable:max-file-line-count // tslint:disable:max-file-line-count

View File

@@ -0,0 +1,43 @@
import {colors as materialUiColors} from 'material-ui/styles';
export const colors = {
...materialUiColors,
grey50: '#FAFAFA',
grey100: '#F5F5F5',
lightestGrey: '#F0F0F0',
greyishPink: '#E6E5E5',
grey300: '#E0E0E0',
beigeWhite: '#E4E4E4',
grey400: '#BDBDBD',
lightGrey: '#BBBBBB',
grey500: '#9E9E9E',
grey: '#A5A5A5',
darkGrey: '#818181',
landingLinkGrey: '#919191',
grey700: '#616161',
grey800: '#424242',
darkerGrey: '#393939',
heroGrey: '#404040',
projectsGrey: '#343333',
darkestGrey: '#272727',
dharmaDarkGrey: '#252525',
lightBlue: '#60A4F4',
lightBlueA700: '#0091EA',
darkBlue: '#4D5481',
turquois: '#058789',
lightPurple: '#A81CA6',
purple: '#690596',
red200: '#EF9A9A',
red: '#E91751',
red500: '#F44336',
red600: '#E53935',
limeGreen: '#66DE75',
lightGreen: '#4DC55C',
lightestGreen: '#89C774',
brightGreen: '#00C33E',
green400: '#66BB6A',
green: '#4DA24B',
amber600: '#FFB300',
orange: '#E69D00',
amber800: '#FF8F00',
};

View File

@@ -1,25 +1,105 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import { import {
ContractAddresses,
Environments, Environments,
Networks,
OutdatedWrappedEtherByNetworkId, OutdatedWrappedEtherByNetworkId,
PublicNodeUrlsByNetworkId,
SmartContractDocSections,
} from 'ts/types'; } from 'ts/types';
const BASE_URL = window.location.origin; const BASE_URL = window.location.origin;
const isDevelopment = _.includes(BASE_URL, 'https://0xproject.dev:3572') || const isDevelopment = _.includes([
_.includes(BASE_URL, 'https://localhost:3572') || 'https://0xproject.localhost:3572',
_.includes(BASE_URL, 'https://127.0.0.1'); 'https://localhost:3572',
'https://127.0.0.1',
], BASE_URL);
const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs';
export const configs = { export const configs = {
BASE_URL,
ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION,
BACKEND_BASE_URL: isDevelopment ? 'https://localhost:3001' : 'https://website-api.0xproject.com', BACKEND_BASE_URL: isDevelopment ? 'https://localhost:3001' : 'https://website-api.0xproject.com',
symbolsOfMintableTokens: ['MKR', 'MLN', 'GNT', 'DGD', 'REP'], BASE_URL,
BITLY_ACCESS_TOKEN: 'ffc4c1a31e5143848fb7c523b39f91b9b213d208',
CONTRACT_ADDRESS: {
'1.0.0': {
[Networks.mainnet]: {
[SmartContractDocSections.Exchange]: '0x12459c951127e0c374ff9105dda097662a027093',
[SmartContractDocSections.TokenTransferProxy]: '0x8da0d80f5007ef1e431dd2127178d224e32c2ef4',
[SmartContractDocSections.ZRXToken]: '0xe41d2489571d322189246dafa5ebde1f4699f498',
[SmartContractDocSections.TokenRegistry]: '0x926a74c5c36adf004c87399e65f75628b0f98d2c',
},
[Networks.ropsten]: {
[SmartContractDocSections.Exchange]: '0x479cc461fecd078f766ecc58533d6f69580cf3ac',
[SmartContractDocSections.TokenTransferProxy]: '0x4e9aad8184de8833365fea970cd9149372fdf1e6',
[SmartContractDocSections.ZRXToken]: '0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d',
[SmartContractDocSections.TokenRegistry]: '0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed',
},
[Networks.kovan]: {
[SmartContractDocSections.Exchange]: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364',
[SmartContractDocSections.TokenTransferProxy]: '0x087Eed4Bc1ee3DE49BeFbd66C662B434B15d49d4',
[SmartContractDocSections.ZRXToken]: '0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570',
[SmartContractDocSections.TokenRegistry]: '0xf18e504561f4347bea557f3d4558f559dddbae7f',
},
},
} as ContractAddresses,
DEFAULT_DERIVATION_PATH: `44'/60'/0'`,
// WARNING: ZRX & WETH MUST always be default trackedTokens // WARNING: ZRX & WETH MUST always be default trackedTokens
defaultTrackedTokenSymbols: ['WETH', 'ZRX'], DEFAULT_TRACKED_TOKEN_SYMBOLS: ['WETH', 'ZRX'],
lastLocalStorageFillClearanceDate: '2017-11-22', DOMAIN_STAGING: 'staging-0xproject.s3-website-us-east-1.amazonaws.com',
lastLocalStorageTrackedTokenClearanceDate: '2017-12-13', DOMAIN_DEVELOPMENT: '0xproject.localhost:3572',
isMainnetEnabled: true, DOMAIN_PRODUCTION: '0xproject.com',
outdatedWrappedEthers: [ ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION,
ICON_URL_BY_SYMBOL: {
'REP': '/images/token_icons/augur.png',
'DGD': '/images/token_icons/digixdao.png',
'WETH': '/images/token_icons/ether_erc20.png',
'MLN': '/images/token_icons/melon.png',
'GNT': '/images/token_icons/golem.png',
'MKR': '/images/token_icons/makerdao.png',
'ZRX': '/images/token_icons/zero_ex.png',
'ANT': '/images/token_icons/aragon.png',
'BNT': '/images/token_icons/bancor.png',
'BAT': '/images/token_icons/basicattentiontoken.png',
'CVC': '/images/token_icons/civic.png',
'EOS': '/images/token_icons/eos.png',
'FUN': '/images/token_icons/funfair.png',
'GNO': '/images/token_icons/gnosis.png',
'ICN': '/images/token_icons/iconomi.png',
'OMG': '/images/token_icons/omisego.png',
'SNT': '/images/token_icons/status.png',
'STORJ': '/images/token_icons/storjcoinx.png',
'PAY': '/images/token_icons/tenx.png',
'QTUM': '/images/token_icons/qtum.png',
'DNT': '/images/token_icons/district0x.png',
'SNGLS': '/images/token_icons/singularity.png',
'EDG': '/images/token_icons/edgeless.png',
'1ST': '/images/token_icons/firstblood.jpg',
'WINGS': '/images/token_icons/wings.png',
'BQX': '/images/token_icons/bitquence.png',
'LUN': '/images/token_icons/lunyr.png',
'RLC': '/images/token_icons/iexec.png',
'MCO': '/images/token_icons/monaco.png',
'ADT': '/images/token_icons/adtoken.png',
'CFI': '/images/token_icons/cofound-it.png',
'ROL': '/images/token_icons/etheroll.png',
'WGNT': '/images/token_icons/golem.png',
'MTL': '/images/token_icons/metal.png',
'NMR': '/images/token_icons/numeraire.png',
'SAN': '/images/token_icons/santiment.png',
'TAAS': '/images/token_icons/taas.png',
'TKN': '/images/token_icons/tokencard.png',
'TRST': '/images/token_icons/trust.png',
} as {[symbol: string]: string},
IS_MAINNET_ENABLED: true,
LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22',
LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2017-12-19',
// NEW_WRAPPED_ETHERS is temporary until we remove the SHOULD_DEPRECATE_OLD_WETH_TOKEN flag
// and add the new WETHs to the tokenRegistry
NEW_WRAPPED_ETHERS: {
1: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
42: '0xd0a1e359811322d97991e03f863a0c30c2cf029c',
} as {[networkId: string]: string},
OUTDATED_WRAPPED_ETHERS: [
{ {
42: { 42: {
address: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c', address: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c',
@@ -37,4 +117,15 @@ export const configs = {
}, },
}, },
] as OutdatedWrappedEtherByNetworkId[], ] as OutdatedWrappedEtherByNetworkId[],
// The order matters. We first try first node and only then fall back to others.
PUBLIC_NODE_URLS_BY_NETWORK_ID: {
[1]: [
`https://mainnet.infura.io/${INFURA_API_KEY}`,
],
[42]: [
`https://kovan.infura.io/${INFURA_API_KEY}`,
],
} as PublicNodeUrlsByNetworkId,
SHOULD_DEPRECATE_OLD_WETH_TOKEN: true,
SYMBOLS_OF_MINTABLE_TOKENS: ['MKR', 'MLN', 'GNT', 'DGD', 'REP'],
}; };

View File

@@ -1,188 +1,87 @@
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { import {
ContractAddresses,
Docs,
Networks, Networks,
PublicNodeUrlsByNetworkId,
WebsitePaths,
} from 'ts/types'; } from 'ts/types';
const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs';
const smartContractDocSections = {
Introduction: 'Introduction',
Exchange: 'Exchange',
TokenTransferProxy: 'TokenTransferProxy',
TokenRegistry: 'TokenRegistry',
ZRXToken: 'ZRXToken',
EtherToken: 'EtherToken',
};
export const constants = { export const constants = {
ANGELLIST_URL: 'https://angel.co/0xproject/jobs', DECIMAL_PLACES_ETH: 18,
STAGING_DOMAIN: 'staging-0xproject.s3-website-us-east-1.amazonaws.com', DECIMAL_PLACES_ZRX: 18,
PRODUCTION_DOMAIN: '0xproject.com', DOCS_SCROLL_DURATION_MS: 0,
DEVELOPMENT_DOMAIN: '0xproject.dev:3572', DOCS_CONTAINER_ID: 'documentation',
BIGNUMBERJS_GITHUB_URL: 'http://mikemcl.github.io/bignumber.js',
BITLY_ACCESS_TOKEN: 'ffc4c1a31e5143848fb7c523b39f91b9b213d208',
BITLY_ENDPOINT: 'https://api-ssl.bitly.com',
BLOG_URL: 'https://blog.0xproject.com/latest',
CUSTOM_BLUE: '#60a4f4',
DEFAULT_DERIVATION_PATH: `44'/60'/0'`,
ETHER_FAUCET_ENDPOINT: 'https://faucet.0xproject.com',
FEE_RECIPIENT_ADDRESS: '0x0000000000000000000000000000000000000000',
FIREFOX_U2F_ADDON: 'https://addons.mozilla.org/en-US/firefox/addon/u2f-support-add-on/',
GITHUB_URL: 'https://github.com/0xProject',
GITHUB_WIKI_URL: 'https://github.com/0xProject/wiki',
HTTP_NO_CONTENT_STATUS_CODE: 204,
ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY: 'didAcceptPortalDisclaimer',
LINKEDIN_0X_URL: 'https://www.linkedin.com/company/0x',
LEDGER_PROVIDER_NAME: 'Ledger',
METAMASK_PROVIDER_NAME: 'Metamask',
GENESIS_ORDER_BLOCK_BY_NETWORK_ID: { GENESIS_ORDER_BLOCK_BY_NETWORK_ID: {
1: 4145578, 1: 4145578,
42: 3117574, 42: 3117574,
50: 0, 50: 0,
} as {[networkId: number]: number}, } as {[networkId: number]: number},
PUBLIC_PROVIDER_NAME: '0x Public', HOME_SCROLL_DURATION_MS: 500,
// The order matters. We first try first node and only then fall back to others. HTTP_NO_CONTENT_STATUS_CODE: 204,
PUBLIC_NODE_URLS_BY_NETWORK_ID: { LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER: 'didAcceptPortalDisclaimer',
[1]: [ LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE: 'hasDismissedWethNotice',
`https://mainnet.infura.io/${INFURA_API_KEY}`,
],
[42]: [
`https://kovan.infura.io/${INFURA_API_KEY}`,
],
} as PublicNodeUrlsByNetworkId,
PARITY_SIGNER_PROVIDER_NAME: 'Parity Signer',
GENERIC_PROVIDER_NAME: 'Injected Web3',
MAKER_FEE: new BigNumber(0), MAKER_FEE: new BigNumber(0),
MAINNET_NAME: 'Main network', MAINNET_NAME: 'Main network',
MAINNET_NETWORK_ID: 1,
METAMASK_CHROME_STORE_URL: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
// tslint:disable-next-line:max-line-length
PARITY_CHROME_STORE_URL: 'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig',
MIST_DOWNLOAD_URL: 'https://github.com/ethereum/mist/releases',
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
ROLLBAR_ACCESS_TOKEN: 'a6619002b51c4464928201e6ea94de65',
DOCS_SCROLL_DURATION_MS: 0,
DOCS_CONTAINER_ID: 'documentation',
HOME_SCROLL_DURATION_MS: 500,
REDDIT_URL: 'https://reddit.com/r/0xproject',
STANDARD_RELAYER_API_GITHUB: 'https://github.com/0xProject/standard-relayer-api/blob/master/README.md',
SUCCESS_STATUS: 200,
UNAVAILABLE_STATUS: 503,
TAKER_FEE: new BigNumber(0),
TESTNET_NAME: 'Kovan',
TESTNET_NETWORK_ID: 42,
TESTRPC_NETWORK_ID: 50,
TWITTER_URL: 'https://twitter.com/0xproject',
ETH_DECIMAL_PLACES: 18,
MINT_AMOUNT: new BigNumber('100000000000000000000'), MINT_AMOUNT: new BigNumber('100000000000000000000'),
WEB3_DOCS_URL: 'https://github.com/ethereum/wiki/wiki/JavaScript-API', NETWORK_ID_MAINNET: 1,
WEB3_PROVIDER_DOCS_URL: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150', NETWORK_ID_TESTNET: 42,
WEB3_DECODED_LOG_ENTRY_EVENT_URL: NETWORK_ID_TESTRPC: 50,
'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L123', NETWORK_NAME_BY_ID: {
WEB3_LOG_ENTRY_EVENT_URL: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L127',
ZEROEX_CHAT_URL: 'https://chat.0xproject.com',
// Projects
ETHFINEX_URL: 'https://www.bitfinex.com/ethfinex',
RADAR_RELAY_URL: 'https://radarrelay.com',
PARADEX_URL: 'https://paradex.io',
DYDX_URL: 'https://dydx.exchange',
MELONPORT_URL: 'https://melonport.com',
DISTRICT_0X_URL: 'https://district0x.io',
DHARMA_URL: 'https://dharma.io',
LENDROID_URL: 'https://lendroid.com',
MAKER_URL: 'https://makerdao.com',
ARAGON_URL: 'https://aragon.one',
BLOCKNET_URL: 'https://blocknet.co',
OCEAN_URL: 'http://the0cean.com',
STATUS_URL: 'https://status.im',
AUGUR_URL: 'https://augur.net',
AUCTUS_URL: 'https://auctus.org',
OPEN_ANX_URL: 'https://www.openanx.org',
iconUrlBySymbol: {
'REP': '/images/token_icons/augur.png',
'DGD': '/images/token_icons/digixdao.png',
'WETH': '/images/token_icons/ether_erc20.png',
'MLN': '/images/token_icons/melon.png',
'GNT': '/images/token_icons/golem.png',
'MKR': '/images/token_icons/makerdao.png',
'ZRX': '/images/token_icons/zero_ex.png',
'ANT': '/images/token_icons/aragon.png',
'BNT': '/images/token_icons/bancor.png',
'BAT': '/images/token_icons/basicattentiontoken.png',
'CVC': '/images/token_icons/civic.png',
'EOS': '/images/token_icons/eos.png',
'FUN': '/images/token_icons/funfair.png',
'GNO': '/images/token_icons/gnosis.png',
'ICN': '/images/token_icons/iconomi.png',
'OMG': '/images/token_icons/omisego.png',
'SNT': '/images/token_icons/status.png',
'STORJ': '/images/token_icons/storjcoinx.png',
'PAY': '/images/token_icons/tenx.png',
'QTUM': '/images/token_icons/qtum.png',
'DNT': '/images/token_icons/district0x.png',
'SNGLS': '/images/token_icons/singularity.png',
'EDG': '/images/token_icons/edgeless.png',
'1ST': '/images/token_icons/firstblood.jpg',
'WINGS': '/images/token_icons/wings.png',
'BQX': '/images/token_icons/bitquence.png',
'LUN': '/images/token_icons/lunyr.png',
'RLC': '/images/token_icons/iexec.png',
'MCO': '/images/token_icons/monaco.png',
'ADT': '/images/token_icons/adtoken.png',
'CFI': '/images/token_icons/cofound-it.png',
'ROL': '/images/token_icons/etheroll.png',
'WGNT': '/images/token_icons/golem.png',
'MTL': '/images/token_icons/metal.png',
'NMR': '/images/token_icons/numeraire.png',
'SAN': '/images/token_icons/santiment.png',
'TAAS': '/images/token_icons/taas.png',
'TKN': '/images/token_icons/tokencard.png',
'TRST': '/images/token_icons/trust.png',
} as {[symbol: string]: string},
networkNameById: {
1: Networks.mainnet, 1: Networks.mainnet,
3: Networks.ropsten, 3: Networks.ropsten,
4: Networks.rinkeby, 4: Networks.rinkeby,
42: Networks.kovan, 42: Networks.kovan,
} as {[symbol: number]: string}, } as {[symbol: number]: string},
networkIdByName: { NETWORK_ID_BY_NAME: {
[Networks.mainnet]: 1, [Networks.mainnet]: 1,
[Networks.ropsten]: 3, [Networks.ropsten]: 3,
[Networks.rinkeby]: 4, [Networks.rinkeby]: 4,
[Networks.kovan]: 42, [Networks.kovan]: 42,
} as {[networkName: string]: number}, } as {[networkName: string]: number},
docToPath: { NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
[Docs.ZeroExJs]: WebsitePaths.ZeroExJs, PROVIDER_NAME_LEDGER: 'Ledger',
[Docs.SmartContracts]: WebsitePaths.SmartContracts, PROVIDER_NAME_METAMASK: 'Metamask',
}, PROVIDER_NAME_PARITY_SIGNER: 'Parity Signer',
smartContractDocSections, PROVIDER_NAME_GENERIC: 'Injected Web3',
contractAddresses: { PROVIDER_NAME_PUBLIC: '0x Public',
'1.0.0': { ROLLBAR_ACCESS_TOKEN: 'a6619002b51c4464928201e6ea94de65',
[Networks.mainnet]: { SUCCESS_STATUS: 200,
[smartContractDocSections.Exchange]: '0x12459c951127e0c374ff9105dda097662a027093', UNAVAILABLE_STATUS: 503,
[smartContractDocSections.TokenTransferProxy]: '0x8da0d80f5007ef1e431dd2127178d224e32c2ef4', TAKER_FEE: new BigNumber(0),
[smartContractDocSections.ZRXToken]: '0xe41d2489571d322189246dafa5ebde1f4699f498', TESTNET_NAME: 'Kovan',
[smartContractDocSections.EtherToken]: '0x2956356cd2a2bf3202f771f50d3d14a367b48070', PROJECT_URL_ETHFINEX: 'https://www.bitfinex.com/ethfinex',
[smartContractDocSections.TokenRegistry]: '0x926a74c5c36adf004c87399e65f75628b0f98d2c', PROJECT_URL_RADAR_RELAY: 'https://radarrelay.com',
}, PROJECT_URL_PARADEX: 'https://paradex.io',
[Networks.ropsten]: { PROJECT_URL_DYDX: 'https://dydx.exchange',
[smartContractDocSections.Exchange]: '0x479cc461fecd078f766ecc58533d6f69580cf3ac', PROJECT_URL_MELONPORT: 'https://melonport.com',
[smartContractDocSections.TokenTransferProxy]: '0x4e9aad8184de8833365fea970cd9149372fdf1e6', PROJECT_URL_DISTRICT_0X: 'https://district0x.io',
[smartContractDocSections.ZRXToken]: '0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d', PROJECT_URL_DHARMA: 'https://dharma.io',
[smartContractDocSections.EtherToken]: '0xc00fd9820cd2898cc4c054b7bf142de637ad129a', PROJECT_URL_LENDROID: 'https://lendroid.com',
[smartContractDocSections.TokenRegistry]: '0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed', PROJECT_URL_MAKER: 'https://makerdao.com',
}, PROJECT_URL_ARAGON: 'https://aragon.one',
[Networks.kovan]: { PROJECT_URL_BLOCKNET: 'https://blocknet.co',
[smartContractDocSections.Exchange]: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364', PROJECT_URL_0CEAN: 'http://the0cean.com',
[smartContractDocSections.TokenTransferProxy]: '0x087Eed4Bc1ee3DE49BeFbd66C662B434B15d49d4', PROJECT_URL_STATUS: 'https://status.im',
[smartContractDocSections.ZRXToken]: '0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570', PROJECT_URL_AUGUR: 'https://augur.net',
[smartContractDocSections.EtherToken]: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c', PROJECT_URL_AUCTUS: 'https://auctus.org',
[smartContractDocSections.TokenRegistry]: '0xf18e504561f4347bea557f3d4558f559dddbae7f', PROJECT_URL_OPEN_ANX: 'https://www.openanx.org',
}, URL_ANGELLIST: 'https://angel.co/0xproject/jobs',
}, URL_BIGNUMBERJS_GITHUB: 'http://mikemcl.github.io/bignumber.js',
} as ContractAddresses, URL_BITLY_API: 'https://api-ssl.bitly.com',
URL_BLOG: 'https://blog.0xproject.com/latest',
URL_FIREFOX_U2F_ADDON: 'https://addons.mozilla.org/en-US/firefox/addon/u2f-support-add-on/',
URL_ETHER_FAUCET: 'https://faucet.0xproject.com',
URL_GITHUB_ORG: 'https://github.com/0xProject',
URL_GITHUB_WIKI: 'https://github.com/0xProject/wiki',
URL_METAMASK_CHROME_STORE: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
URL_MIST_DOWNLOAD: 'https://github.com/ethereum/mist/releases',
URL_PARITY_CHROME_STORE:
'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig',
URL_REDDIT: 'https://reddit.com/r/0xproject',
URL_STANDARD_RELAYER_API_GITHUB: 'https://github.com/0xProject/standard-relayer-api/blob/master/README.md',
URL_TWITTER: 'https://twitter.com/0xproject',
URL_WEB3_DOCS: 'https://github.com/ethereum/wiki/wiki/JavaScript-API',
URL_WEB3_DECODED_LOG_ENTRY_EVENT:
'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L123',
URL_WEB3_LOG_ENTRY_EVENT: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L127',
URL_WEB3_PROVIDER_DOCS: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150',
URL_WETH_IO: 'https://weth.io/',
URL_ZEROEX_CHAT: 'https://chat.0xproject.com',
}; };

View File

@@ -15,7 +15,7 @@ const rollbarConfig = {
environment: configs.ENVIRONMENT, environment: configs.ENVIRONMENT,
}, },
uncaughtErrorLevel: 'error', uncaughtErrorLevel: 'error',
hostWhiteList: [constants.PRODUCTION_DOMAIN, constants.STAGING_DOMAIN], hostWhiteList: [configs.DOMAIN_PRODUCTION, configs.DOMAIN_STAGING],
ignoredMessages: [ ignoredMessages: [
// Errors from the third-party scripts // Errors from the third-party scripts
'Script error', 'Script error',

View File

@@ -0,0 +1,35 @@
import {getMuiTheme} from 'material-ui/styles';
import {colors} from 'ts/utils/colors';
export const muiTheme = getMuiTheme({
appBar: {
height: 45,
color: colors.white,
textColor: colors.black,
},
palette: {
pickerHeaderColor: colors.lightBlue,
primary1Color: colors.lightBlue,
primary2Color: colors.lightBlue,
textColor: colors.grey700,
},
datePicker: {
color: colors.grey700,
textColor: colors.white,
calendarTextColor: colors.white,
selectColor: colors.darkestGrey,
selectTextColor: colors.white,
},
timePicker: {
color: colors.grey700,
textColor: colors.white,
accentColor: colors.white,
headerColor: colors.darkestGrey,
selectColor: colors.darkestGrey,
selectTextColor: colors.darkestGrey,
},
toggle: {
thumbOnColor: colors.limeGreen,
trackOnColor: colors.lightGreen,
},
});

View File

@@ -22,7 +22,7 @@ export const typeDocUtils = {
isType(entity: TypeDocNode): boolean { isType(entity: TypeDocNode): boolean {
return entity.kindString === KindString.Interface || return entity.kindString === KindString.Interface ||
entity.kindString === KindString.Function || entity.kindString === KindString.Function ||
entity.kindString === KindString['Type alias'] || entity.kindString === KindString.TypeAlias ||
entity.kindString === KindString.Variable || entity.kindString === KindString.Variable ||
entity.kindString === KindString.Enumeration; entity.kindString === KindString.Enumeration;
}, },
@@ -126,7 +126,7 @@ export const typeDocUtils = {
case KindString.Function: case KindString.Function:
case KindString.Variable: case KindString.Variable:
case KindString.Enumeration: case KindString.Enumeration:
case KindString['Type alias']: case KindString.TypeAlias:
if (docsInfo.isPublicType(entity.name)) { if (docsInfo.isPublicType(entity.name)) {
const customType = typeDocUtils._convertCustomType( const customType = typeDocUtils._convertCustomType(
entity, docsInfo.sections, sectionName, docsInfo.subPackageName); entity, docsInfo.sections, sectionName, docsInfo.subPackageName);

View File

@@ -15,6 +15,7 @@ import {
Token, Token,
TokenByAddress, TokenByAddress,
} from 'ts/types'; } from 'ts/types';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants'; import {constants} from 'ts/utils/constants';
import * as u2f from 'ts/vendor/u2f_api'; import * as u2f from 'ts/vendor/u2f_api';
@@ -61,8 +62,8 @@ export const utils = {
orderExpiryTimestamp: BigNumber, orderTakerAddress: string, orderMakerAddress: string, orderExpiryTimestamp: BigNumber, orderTakerAddress: string, orderMakerAddress: string,
makerFee: BigNumber, takerFee: BigNumber, feeRecipient: string, makerFee: BigNumber, takerFee: BigNumber, feeRecipient: string,
signatureData: SignatureData, tokenByAddress: TokenByAddress, orderSalt: BigNumber): Order { signatureData: SignatureData, tokenByAddress: TokenByAddress, orderSalt: BigNumber): Order {
const makerToken = tokenByAddress[sideToAssetToken[Side.deposit].address]; const makerToken = tokenByAddress[sideToAssetToken[Side.Deposit].address];
const takerToken = tokenByAddress[sideToAssetToken[Side.receive].address]; const takerToken = tokenByAddress[sideToAssetToken[Side.Receive].address];
const order = { const order = {
maker: { maker: {
address: orderMakerAddress, address: orderMakerAddress,
@@ -72,7 +73,7 @@ export const utils = {
decimals: makerToken.decimals, decimals: makerToken.decimals,
address: makerToken.address, address: makerToken.address,
}, },
amount: sideToAssetToken[Side.deposit].amount.toString(), amount: sideToAssetToken[Side.Deposit].amount.toString(),
feeAmount: makerFee.toString(), feeAmount: makerFee.toString(),
}, },
taker: { taker: {
@@ -83,7 +84,7 @@ export const utils = {
decimals: takerToken.decimals, decimals: takerToken.decimals,
address: takerToken.address, address: takerToken.address,
}, },
amount: sideToAssetToken[Side.receive].amount.toString(), amount: sideToAssetToken[Side.Receive].amount.toString(),
feeAmount: takerFee.toString(), feeAmount: takerFee.toString(),
}, },
expiration: orderExpiryTimestamp.toString(), expiration: orderExpiryTimestamp.toString(),
@@ -124,11 +125,11 @@ export const utils = {
// This logic mirrors the CSS media queries in BassCSS for the `lg-`, `md-` and `sm-` CSS // This logic mirrors the CSS media queries in BassCSS for the `lg-`, `md-` and `sm-` CSS
// class prefixes. Do not edit these. // class prefixes. Do not edit these.
if (widthInEm > LG_MIN_EM) { if (widthInEm > LG_MIN_EM) {
return ScreenWidths.LG; return ScreenWidths.Lg;
} else if (widthInEm > MD_MIN_EM) { } else if (widthInEm > MD_MIN_EM) {
return ScreenWidths.MD; return ScreenWidths.Md;
} else { } else {
return ScreenWidths.SM; return ScreenWidths.Sm;
} }
}, },
isUserOnMobile(): boolean { isUserOnMobile(): boolean {
@@ -136,7 +137,7 @@ export const utils = {
return isUserOnMobile; return isUserOnMobile;
}, },
getEtherScanLinkIfExists(addressOrTxHash: string, networkId: number, suffix: EtherscanLinkSuffixes): string { getEtherScanLinkIfExists(addressOrTxHash: string, networkId: number, suffix: EtherscanLinkSuffixes): string {
const networkName = constants.networkNameById[networkId]; const networkName = constants.NETWORK_NAME_BY_ID[networkId];
if (_.isUndefined(networkName)) { if (_.isUndefined(networkName)) {
return undefined; return undefined;
} }
@@ -182,11 +183,11 @@ export const utils = {
}, },
getCurrentEnvironment() { getCurrentEnvironment() {
switch (location.host) { switch (location.host) {
case constants.DEVELOPMENT_DOMAIN: case configs.DOMAIN_DEVELOPMENT:
return 'development'; return 'development';
case constants.STAGING_DOMAIN: case configs.DOMAIN_STAGING:
return 'staging'; return 'staging';
case constants.PRODUCTION_DOMAIN: case configs.DOMAIN_PRODUCTION:
return 'production'; return 'production';
default: default:
return 'production'; return 'production';