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": {
"0x.js": "~0.27.2",
"@0xproject/subproviders": "^0.1.0",
"@0xproject/utils": "^0.1.0",
"accounting": "^0.4.1",
"basscss": "^8.0.3",
"bignumber.js": "~4.1.0",

View File

@@ -77,21 +77,21 @@ export class Blockchain {
}
private static getNameGivenProvider(provider: Web3.Provider): string {
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
// internal `Web3FrameProvider` class.
const isParitySigner = _.startsWith(provider.constructor.toString(), 'function Web3FrameProvider');
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) {
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);
let provider;
@@ -114,11 +114,11 @@ export class Blockchain {
// injected into their browser.
provider = new ProviderEngine();
provider.addProvider(new FilterSubprovider());
const networkId = configs.isMainnetEnabled ?
constants.MAINNET_NETWORK_ID :
constants.TESTNET_NETWORK_ID;
const networkId = configs.IS_MAINNET_ENABLED ?
constants.NETWORK_ID_MAINNET :
constants.NETWORK_ID_TESTNET;
provider.addProvider(new RedundantRPCSubprovider(
constants.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
));
provider.start();
}
@@ -135,11 +135,11 @@ export class Blockchain {
const isConnected = !_.isUndefined(newNetworkId);
if (!isConnected) {
this.networkId = newNetworkId;
this.dispatcher.encounteredBlockchainError(BlockchainErrs.DISCONNECTED_FROM_ETHEREUM_NODE);
this.dispatcher.encounteredBlockchainError(BlockchainErrs.DisconnectedFromEthereumNode);
this.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
} else if (this.networkId !== newNetworkId) {
this.networkId = newNetworkId;
this.dispatcher.encounteredBlockchainError('');
this.dispatcher.encounteredBlockchainError(BlockchainErrs.NoError);
await this.fetchTokenInformationAsync();
await this.rehydrateStoreWithContractEvents();
}
@@ -158,6 +158,14 @@ export class Blockchain {
}
public async isAddressInTokenRegistryAsync(tokenAddress: string): Promise<boolean> {
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);
return !_.isUndefined(tokenIfExists);
}
@@ -186,7 +194,7 @@ export class Blockchain {
// later on in the logic.
let provider;
switch (providerType) {
case ProviderType.LEDGER: {
case ProviderType.Ledger: {
const isU2FSupported = await utils.isU2FSupportedAsync();
if (!isU2FSupported) {
throw new Error('Cannot update providerType to LEDGER without U2F support');
@@ -205,11 +213,11 @@ export class Blockchain {
this.ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs);
provider.addProvider(this.ledgerSubprovider);
provider.addProvider(new FilterSubprovider());
const networkId = configs.isMainnetEnabled ?
constants.MAINNET_NETWORK_ID :
constants.TESTNET_NETWORK_ID;
const networkId = configs.IS_MAINNET_ENABLED ?
constants.NETWORK_ID_MAINNET :
constants.NETWORK_ID_TESTNET;
provider.addProvider(new RedundantRPCSubprovider(
constants.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
));
provider.start();
this.web3Wrapper.destroy();
@@ -220,7 +228,7 @@ export class Blockchain {
break;
}
case ProviderType.INJECTED: {
case ProviderType.Injected: {
if (_.isUndefined(this.cachedProvider)) {
return; // Going from injected to injected, so we noop
}
@@ -241,8 +249,8 @@ export class Blockchain {
await this.fetchTokenInformationAsync();
}
public async setProxyAllowanceAsync(token: Token, amountInBaseUnits: BigNumber): Promise<void> {
utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TOKEN_ADDRESS_IS_INVALID);
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES);
utils.assert(this.isValidAddress(token.address), BlockchainCallErrs.TokenAddressIsInvalid);
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
const txHash = await this.zeroEx.token.setProxyAllowanceAsync(
@@ -258,7 +266,7 @@ export class Blockchain {
token.address, this.userAddress, toAddress, amountInBaseUnits,
);
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, {
etherScanLinkIfExists,
token,
@@ -294,7 +302,7 @@ export class Blockchain {
}
public async fillOrderAsync(signedOrder: SignedOrder,
fillTakerTokenAmount: BigNumber): Promise<BigNumber> {
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES);
utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const shouldThrowOnInsufficientBalanceOrAllowance = true;
@@ -346,7 +354,7 @@ export class Blockchain {
return this.web3Wrapper.isAddress(lowercaseAddress);
}
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);
@@ -375,7 +383,7 @@ export class Blockchain {
return signatureData;
}
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);
await mintableContract.mint(constants.MINT_AMOUNT, {
@@ -390,14 +398,14 @@ export class Blockchain {
}
public async convertEthToWrappedEthTokensAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> {
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);
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
}
public async convertWrappedEthTokensToEthAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> {
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);
await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
@@ -463,7 +471,7 @@ export class Blockchain {
}
private async showEtherScanLinkAndAwaitTransactionMinedAsync(
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, {
etherScanLinkIfExists,
}));
@@ -491,7 +499,7 @@ export class Blockchain {
}
private async startListeningForExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise<void> {
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
await this.fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues);
@@ -591,19 +599,19 @@ export class Blockchain {
_.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => {
// 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
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
// 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
// new canonical WETH.
// TODO: Remove this hack once we've updated the TokenRegistries
// Airtable task: https://airtable.com/tblFe0Q9JuKJPYbTn/viwsOG2Y97qdIeCIO/recv3VGmIorFzHBVz
let address = t.address;
if (t.symbol === 'WETH') {
if (this.networkId === 1) {
address = '0xe495bcacaf29a0eb00fb67b86e9cd2a994dd55d8';
} else if (this.networkId === 42) {
address = '0x739e78d6bebbdf24105a5145fa04436589d1cbd9';
}
if (configs.SHOULD_DEPRECATE_OLD_WETH_TOKEN && t.symbol === 'WETH') {
const newEtherTokenAddressIfExists = configs.NEW_WRAPPED_ETHERS[this.networkId];
if (!_.isUndefined(newEtherTokenAddressIfExists)) {
address = newEtherTokenAddressIfExists;
}
}
const token: Token = {
iconUrl,
@@ -639,9 +647,9 @@ export class Blockchain {
const provider = await Blockchain.getProviderAsync(injectedWeb3, networkIdIfExists);
const networkId = !_.isUndefined(networkIdIfExists) ? networkIdIfExists :
configs.isMainnetEnabled ?
constants.MAINNET_NETWORK_ID :
constants.TESTNET_NETWORK_ID;
configs.IS_MAINNET_ENABLED ?
constants.NETWORK_ID_MAINNET :
constants.NETWORK_ID_TESTNET;
const zeroExConfigs = {
networkId,
};
@@ -661,7 +669,7 @@ export class Blockchain {
const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3);
const providerName = doesInjectedWeb3Exist ?
Blockchain.getNameGivenProvider(injectedWeb3.currentProvider) :
constants.PUBLIC_PROVIDER_NAME;
constants.PROVIDER_NAME_PUBLIC;
this.dispatcher.updateInjectedProviderName(providerName);
}
private async fetchTokenInformationAsync() {
@@ -686,7 +694,7 @@ export class Blockchain {
let trackedTokensIfExists = trackedTokenStorage.getTrackedTokensIfExists(this.userAddress, this.networkId);
const tokenRegistryTokens = _.values(tokenRegistryTokensByAddress);
if (_.isUndefined(trackedTokensIfExists)) {
trackedTokensIfExists = _.map(configs.defaultTrackedTokenSymbols, symbol => {
trackedTokensIfExists = _.map(configs.DEFAULT_TRACKED_TOKEN_SYMBOLS, symbol => {
const token = _.find(tokenRegistryTokens, t => t.symbol === symbol);
token.isTracked = true;
return token;
@@ -709,11 +717,11 @@ export class Blockchain {
await this.updateTokenBalancesAndAllowancesAsync(trackedTokensIfExists);
const mostPopularTradingPairTokens: Token[] = [
_.find(allTokens, {symbol: configs.defaultTrackedTokenSymbols[0]}),
_.find(allTokens, {symbol: configs.defaultTrackedTokenSymbols[1]}),
_.find(allTokens, {symbol: configs.DEFAULT_TRACKED_TOKEN_SYMBOLS[0]}),
_.find(allTokens, {symbol: configs.DEFAULT_TRACKED_TOKEN_SYMBOLS[1]}),
];
this.dispatcher.updateChosenAssetTokenAddress(Side.deposit, mostPopularTradingPairTokens[0].address);
this.dispatcher.updateChosenAssetTokenAddress(Side.receive, mostPopularTradingPairTokens[1].address);
this.dispatcher.updateChosenAssetTokenAddress(Side.Deposit, mostPopularTradingPairTokens[0].address);
this.dispatcher.updateChosenAssetTokenAddress(Side.Receive, mostPopularTradingPairTokens[1].address);
this.dispatcher.updateBlockchainIsLoaded(true);
}
private async instantiateContractIfExistsAsync(artifact: any, address?: string): Promise<ContractInstance> {
@@ -733,7 +741,7 @@ export class Blockchain {
const doesContractExist = await this.doesContractExistAtAddressAsync(contractAddress);
if (!doesContractExist) {
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}`;
utils.consoleLog(`Notice: Error encountered: ${err} ${err.stack}`);
if (_.includes(errMsg, 'not been deployed to detected network')) {
throw new Error(BlockchainCallErrs.CONTRACT_DOES_NOT_EXIST);
throw new Error(BlockchainCallErrs.ContractDoesNotExist);
} else {
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 Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import {colors} from 'material-ui/styles';
import * as React from 'react';
import {Blockchain} from 'ts/blockchain';
import {BlockchainErrs} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants';
@@ -46,22 +46,22 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
);
}
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';
} else if (!hasWalletAddress) {
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';
} else {
return 'Unexpected error';
}
}
private renderExplanation(hasWalletAddress: boolean) {
if (this.props.blockchainErr === BlockchainErrs.A_CONTRACT_NOT_DEPLOYED_ON_NETWORK) {
if (this.props.blockchainErr === BlockchainErrs.AContractNotDeployedOnNetwork) {
return this.renderContractsNotDeployedExplanation();
} else if (!hasWalletAddress) {
return this.renderNoWalletFoundExplanation();
} else if (this.props.blockchainErr === BlockchainErrs.DISCONNECTED_FROM_ETHEREUM_NODE) {
} else if (this.props.blockchainErr === BlockchainErrs.DisconnectedFromEthereumNode) {
return this.renderDisconnectedFromNode();
} else {
return this.renderUnexpectedErrorExplanation();
@@ -71,9 +71,9 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
return (
<div>
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
</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.
</div>
);
@@ -97,7 +97,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
<h4>1. Metamask chrome extension</h4>
<div>
You can install the{' '}
<a href={constants.METAMASK_CHROME_STORE_URL} target="_blank">
<a href={constants.URL_METAMASK_CHROME_STORE} target="_blank">
Metamask
</a> Chrome extension Ethereum wallet. Once installed and set up, refresh this page.
<div className="pt1">
@@ -107,11 +107,11 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
</div>
<h4>Parity Signer</h4>
<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.
Make sure you have started your local Parity node with{' '}
{configs.isMainnetEnabled && '`parity ui` or'} `parity --chain kovan ui`{' '}
in order to connect to {configs.isMainnetEnabled ? 'mainnet or Kovan respectively.' : 'Kovan.'}
{configs.IS_MAINNET_ENABLED && '`parity ui` or'} `parity --chain kovan ui`{' '}
in order to connect to {configs.IS_MAINNET_ENABLED ? 'mainnet or Kovan respectively.' : 'Kovan.'}
</div>
<div className="pt2">
<span className="bold">Note:</span>
@@ -130,24 +130,24 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
{' '}currently connected to (network Id: {this.props.networkId}).
{' '}In order to use the 0x portal dApp,
{' '}please connect to the
{' '}{constants.TESTNET_NAME} testnet (network Id: {constants.TESTNET_NETWORK_ID})
{configs.isMainnetEnabled ?
` or ${constants.MAINNET_NAME} (network Id: ${constants.MAINNET_NETWORK_ID}).` :
{' '}{constants.TESTNET_NAME} testnet (network Id: {constants.NETWORK_ID_TESTNET})
{configs.IS_MAINNET_ENABLED ?
` or ${constants.MAINNET_NAME} (network Id: ${constants.NETWORK_ID_MAINNET}).` :
`.`
}
</div>
<h4>Metamask</h4>
<div>
If you are using{' '}
<a href={constants.METAMASK_CHROME_STORE_URL} target="_blank">
<a href={constants.URL_METAMASK_CHROME_STORE} target="_blank">
Metamask
</a>, you can switch networks in the top left corner of the extension popover.
</div>
<h4>Parity Signer</h4>
<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{' '}
{configs.isMainnetEnabled ?
{configs.IS_MAINNET_ENABLED ?
'`parity ui` or `parity --chain Kovan ui` in order to connect to mainnet \
or Kovan respectively.' :
'`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 {TokenAmountInput} from 'ts/components/inputs/token_amount_input';
import {Side, Token, TokenState} from 'ts/types';
const DARK_BLUE = '#4D5481';
import {colors} from 'ts/utils/colors';
interface EthWethConversionDialogProps {
direction: Side;
@@ -47,7 +46,7 @@ export class EthWethConversionDialog extends
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 (
<Dialog
title={title}
@@ -61,10 +60,10 @@ export class EthWethConversionDialog extends
);
}
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 Wrapped Ether back into it\'s native form.';
const isWrappedVersion = this.props.direction === Side.receive;
const isWrappedVersion = this.props.direction === Side.Receive;
return (
<div>
<div className="pb2">
@@ -75,7 +74,7 @@ export class EthWethConversionDialog extends
{this.renderCurrency(isWrappedVersion)}
<div style={{paddingTop: 68}}>
<i
style={{fontSize: 28, color: DARK_BLUE}}
style={{fontSize: 28, color: colors.darkBlue}}
className="zmdi zmdi-arrow-right"
/>
</div>
@@ -85,7 +84,7 @@ export class EthWethConversionDialog extends
className="pt2 mx-auto"
style={{width: 245}}
>
{this.props.direction === Side.receive ?
{this.props.direction === Side.Receive ?
<TokenAmountInput
token={this.props.token}
tokenState={this.props.tokenState}
@@ -109,7 +108,16 @@ export class EthWethConversionDialog extends
className="pt1"
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>
@@ -124,7 +132,7 @@ export class EthWethConversionDialog extends
<div className="mx-auto pt2">
<div
className="center"
style={{color: DARK_BLUE}}
style={{color: colors.darkBlue}}
>
{name}
</div>
@@ -137,6 +145,11 @@ export class EthWethConversionDialog extends
</div>
);
}
private onMaxClick() {
this.setState({
value: this.props.tokenState.balance,
});
}
private onValueChange(isValid: boolean, amount?: BigNumber) {
this.setState({
value: amount,

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import {colors} from 'material-ui/styles';
import * as React from 'react';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants';
interface U2fNotSupportedDialogProps {
@@ -39,7 +39,7 @@ export function U2fNotSupportedDialog(props: U2fNotSupportedDialogProps) {
<li>
Firefox with{' '}
<a
href={constants.FIREFOX_U2F_ADDON}
href={constants.URL_FIREFOX_U2F_ADDON}
target="_blank"
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} : {};
let callToActionLabel;
let inProgressLabel;
if (this.props.direction === Side.deposit) {
if (this.props.direction === Side.Deposit) {
callToActionLabel = 'Wrap';
inProgressLabel = 'Wrapping...';
} else {
@@ -87,9 +87,9 @@ export class EthWethConversionButton extends
const tokenState = this.props.ethTokenState;
let balance = tokenState.balance;
try {
if (direction === Side.deposit) {
if (direction === Side.Deposit) {
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`);
balance = balance.plus(value);
} else {
@@ -104,13 +104,13 @@ export class EthWethConversionButton extends
this.props.onConversionSuccessful();
} catch (err) {
const errMsg = '' + err;
if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) {
if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
} else if (!_.includes(errMsg, 'User denied transaction')) {
utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack);
await errorReporter.reportAsync(err);
const errorMsg = direction === Side.deposit ?
const errorMsg = direction === Side.Deposit ?
'Failed to wrap your ETH. Please try again.' :
'Failed to unwrap your WETH. Please try again.';
this.props.dispatcher.showFlashMessage(errorMsg);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -244,7 +244,9 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
});
const tokenAddress = this.state.chosenTrackTokenAddress;
const token = this.props.tokenByAddress[tokenAddress];
const newTokenEntry = _.assign({}, token);
const newTokenEntry = {
...token,
};
newTokenEntry.isTracked = true;
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 Dialog from 'material-ui/Dialog';
import Divider from 'material-ui/Divider';
import {colors} from 'material-ui/styles';
import * as React from 'react';
import {Blockchain} from 'ts/blockchain';
import {ExpirationInput} from 'ts/components/inputs/expiration_input';
@@ -30,6 +29,7 @@ import {
TokenByAddress,
TokenStateByAddress,
} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {errorReporter} from 'ts/utils/error_reporter';
import {utils} from 'ts/utils/utils';
@@ -78,10 +78,10 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
}
public render() {
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 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 receiveTokenState = this.props.tokenStateByAddress[receiveTokenAddress];
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}
dispatcher={this.props.dispatcher}
label="Selling"
side={Side.deposit}
side={Side.Deposit}
networkId={this.props.networkId}
assetToken={this.props.sideToAssetToken[Side.deposit]}
assetToken={this.props.sideToAssetToken[Side.Deposit]}
updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)}
tokenByAddress={this.props.tokenByAddress}
/>
@@ -112,8 +112,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
label="Sell amount"
token={depositToken}
tokenState={depositTokenState}
amount={this.props.sideToAssetToken[Side.deposit].amount}
onChange={this.onTokenAmountChange.bind(this, depositToken, Side.deposit)}
amount={this.props.sideToAssetToken[Side.Deposit].amount}
onChange={this.onTokenAmountChange.bind(this, depositToken, Side.Deposit)}
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={true}
shouldCheckAllowance={true}
@@ -133,9 +133,9 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
blockchainErr={this.props.blockchainErr}
dispatcher={this.props.dispatcher}
label="Buying"
side={Side.receive}
side={Side.Receive}
networkId={this.props.networkId}
assetToken={this.props.sideToAssetToken[Side.receive]}
assetToken={this.props.sideToAssetToken[Side.Receive]}
updateChosenAssetToken={dispatcher.updateChosenAssetToken.bind(dispatcher)}
tokenByAddress={this.props.tokenByAddress}
/>
@@ -143,8 +143,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
label="Receive amount"
token={receiveToken}
tokenState={receiveTokenState}
amount={this.props.sideToAssetToken[Side.receive].amount}
onChange={this.onTokenAmountChange.bind(this, receiveToken, Side.receive)}
amount={this.props.sideToAssetToken[Side.Receive].amount}
onChange={this.onTokenAmountChange.bind(this, receiveToken, Side.Receive)}
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={false}
shouldCheckAllowance={false}
@@ -154,7 +154,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
</div>
<div className="pt1 sm-pb2 lg-px4 md-px4">
<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
orderExpiryTimestamp={this.props.orderExpiryTimestamp}
updateOrderExpiry={dispatcher.updateOrderExpiry.bind(dispatcher)}
@@ -235,16 +235,16 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
});
}
private async onSignClickedAsync(): Promise<boolean> {
if (this.props.blockchainErr !== '') {
if (this.props.blockchainErr !== BlockchainErrs.NoError) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return false;
}
// 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 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) &&
debitToken.amount.gt(0) && receiveAmount.gt(0) &&
this.props.userAddress !== '' &&

View File

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

View File

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

View File

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

View File

@@ -22,7 +22,7 @@ interface EthAmountInputState {}
export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmountInputState> {
public render() {
const amount = this.props.amount ?
ZeroEx.toUnitAmount(this.props.amount, constants.ETH_DECIMAL_PLACES) :
ZeroEx.toUnitAmount(this.props.amount, constants.DECIMAL_PLACES_ETH) :
undefined;
return (
<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) {
const baseUnitAmountIfExists = _.isUndefined(amount) ?
undefined :
ZeroEx.toBaseUnitAmount(amount, constants.ETH_DECIMAL_PLACES);
ZeroEx.toBaseUnitAmount(amount, constants.DECIMAL_PLACES_ETH);
this.props.onChange(isValid, baseUnitAmountIfExists);
}
}

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import BigNumber from 'bignumber.js';
import * as _ from 'lodash';
import {Paper} from 'material-ui/Paper';
import Paper from 'material-ui/Paper';
import TextField from 'material-ui/TextField';
import * as React from 'react';
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> {
const longUrl = encodeURIComponent(this.getOrderUrl());
const bitlyRequestUrl = constants.BITLY_ENDPOINT + '/v3/shorten?' +
'access_token=' + constants.BITLY_ACCESS_TOKEN +
'&longUrl=' + longUrl;
const bitlyRequestUrl =
`${constants.URL_BITLY_API}/v3/shorten?access_token=${configs.BITLY_ACCESS_TOKEN}&longUrl=${longUrl}`;
const response = await fetch(bitlyRequestUrl);
const responseBody = await response.text();
const bodyObj = JSON.parse(responseBody);

View File

@@ -1,13 +1,13 @@
import BigNumber from 'bignumber.js';
import * as _ from 'lodash';
import Paper from 'material-ui/Paper';
import {colors} from 'material-ui/styles';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
import {Route, Switch} from 'react-router-dom';
import {Blockchain} from 'ts/blockchain';
import {BlockchainErrDialog} from 'ts/components/dialogs/blockchain_err_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 {FillOrder} from 'ts/components/fill_order';
import {Footer} from 'ts/components/footer';
@@ -32,6 +32,7 @@ import {
TokenStateByAddress,
WebsitePaths,
} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils';
@@ -63,22 +64,39 @@ interface PortalAllState {
prevNetworkId: number;
prevNodeVersion: string;
prevUserAddress: string;
hasAcceptedDisclaimer: boolean;
prevPathname: string;
isDisclaimerDialogOpen: boolean;
isWethNoticeDialogOpen: boolean;
}
export class Portal extends React.Component<PortalAllProps, PortalAllState> {
private blockchain: Blockchain;
private sharedOrderIfExists: Order;
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) {
super(props);
this.sharedOrderIfExists = this.getSharedOrderIfExists();
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 = {
prevNetworkId: this.props.networkId,
prevNodeVersion: this.props.nodeVersion,
prevUserAddress: this.props.userAddress,
hasAcceptedDisclaimer: false,
prevPathname: this.props.location.pathname,
isDisclaimerDialogOpen: !hasAcceptedDisclaimer,
isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances,
};
}
public componentDidMount() {
@@ -87,12 +105,6 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
}
public componentWillMount() {
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() {
this.blockchain.destroy();
@@ -128,6 +140,14 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
// tslint:disable-next-line:no-floating-promises
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() {
const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher
@@ -138,6 +158,11 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
flexDirection: 'column',
justifyContent: 'space-between',
};
const portalMenuContainerStyle: React.CSSProperties = {
overflow: 'hidden',
backgroundColor: colors.darkestGrey,
color: colors.white,
};
return (
<div style={portalStyle}>
<DocumentTitle title="0x Portal DApp"/>
@@ -146,9 +171,9 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
blockchainIsLoaded={this.props.blockchainIsLoaded}
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">
{!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="h2 py2">Mainnet unavailable</div>
<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="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 className="col col-12 lg-col-10 md-col-10 sm-col sm-col-12">
<div className="py2" style={{backgroundColor: colors.grey50}}>
@@ -215,8 +240,12 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
toggleDialogFn={updateShouldBlockchainErrDialogBeOpen}
networkId={this.props.networkId}
/>
<WrappedEthSectionNoticeDialog
isOpen={this.state.isWethNoticeDialogOpen}
onToggleDialog={this.onWethNoticeAccepted.bind(this)}
/>
<PortalDisclaimerDialog
isOpen={!this.state.hasAcceptedDisclaimer}
isOpen={this.state.isDisclaimerDialogOpen}
onToggleDialog={this.onPortalDisclaimerAccepted.bind(this)}
/>
<FlashMessage
@@ -224,7 +253,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
flashMessage={this.props.flashMessage}
/>
</div>
<Footer location={this.props.location} />
<Footer />
</div>
);
}
@@ -295,9 +324,15 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
);
}
private onPortalDisclaimerAccepted() {
localStorage.setItem(constants.ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY, 'set');
localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set');
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 {

View File

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

View File

@@ -7,7 +7,6 @@ import Divider from 'material-ui/Divider';
import FlatButton from 'material-ui/FlatButton';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import RaisedButton from 'material-ui/RaisedButton';
import {colors} from 'material-ui/styles';
import ContentAdd from 'material-ui/svg-icons/content/add';
import ContentRemove from 'material-ui/svg-icons/content/remove';
import {
@@ -42,6 +41,7 @@ import {
TokenStateByAddress,
TokenVisibility,
} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants';
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 (this.state.isZRXSpinnerVisible) {
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.setState({
@@ -144,7 +144,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
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 = {
paddingLeft: 3,
display: isTestNetwork ? 'table-cell' : 'none',
@@ -156,7 +156,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
const tokenTableHeight = allTokenRowHeight < MAX_TOKEN_TABLE_HEIGHT ?
allTokenRowHeight :
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 dharmaLoanExplanation = 'If you need access to larger amounts of ether,<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.';
const allowanceExplanation = '0x smart contracts require access to your<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.';
return (
<div className="lg-px4 md-px4 sm-px1 pb2">
@@ -302,7 +302,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
</TableHeaderColumn>
<TableHeaderColumn style={{paddingLeft: 3}}>Balance</TableHeaderColumn>
<TableHeaderColumn>
<div className="inline-block">{!isSmallScreen && 'Trade '}Permissions</div>
<div className="inline-block">Allowance</div>
<HelpTooltip
style={{paddingLeft: 4}}
explanation={allowanceExplanation}
@@ -311,7 +311,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
<TableHeaderColumn>
Action
</TableHeaderColumn>
{this.props.screenWidth !== ScreenWidths.SM &&
{this.props.screenWidth !== ScreenWidths.Sm &&
<TableHeaderColumn>
Send
</TableHeaderColumn>
@@ -333,9 +333,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
</Dialog>
<Dialog
title="Request Dharma Loan"
titleStyle={{fontWeight: 100, backgroundColor: 'rgb(250, 250, 250)'}}
bodyStyle={{backgroundColor: 'rgb(37, 37, 37)'}}
actionsContainerStyle={{backgroundColor: 'rgb(250, 250, 250)'}}
titleStyle={{fontWeight: 100, backgroundColor: colors.white}}
bodyStyle={{backgroundColor: colors.dharmaDarkGrey}}
actionsContainerStyle={{backgroundColor: colors.white}}
autoScrollBodyContent={true}
actions={dharmaDialogActions}
open={this.state.isDharmaDialogVisible}
@@ -357,10 +357,10 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
);
}
private renderTokenTableRows() {
if (!this.props.blockchainIsLoaded || this.props.blockchainErr !== '') {
if (!this.props.blockchainIsLoaded || this.props.blockchainErr !== BlockchainErrs.NoError) {
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 actionPaddingX = isSmallScreen ? 2 : 24;
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) {
const tokenState = this.props.tokenStateByAddress[token.address];
const tokenLink = utils.getEtherScanLinkIfExists(token.address, this.props.networkId,
EtherscanLinkSuffixes.address);
const isMintable = _.includes(configs.symbolsOfMintableTokens, token.symbol) &&
this.props.networkId !== constants.MAINNET_NETWORK_ID;
EtherscanLinkSuffixes.Address);
const isMintable = _.includes(configs.SYMBOLS_OF_MINTABLE_TOKENS, token.symbol) &&
this.props.networkId !== constants.NETWORK_ID_MAINNET;
return (
<TableRow key={token.address} style={{height: TOKEN_TABLE_ROW_HEIGHT}}>
<TableRowColumn
@@ -423,7 +423,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
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
labelReady="Request"
labelLoading="Sending..."
@@ -432,7 +432,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
/>
}
</TableRowColumn>
{this.props.screenWidth !== ScreenWidths.SM &&
{this.props.screenWidth !== ScreenWidths.Sm &&
<TableRowColumn
style={{paddingLeft: actionPaddingX, paddingRight: actionPaddingX}}
>
@@ -456,13 +456,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
return;
}
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 (token.isRegistered) {
// Remove the token from tracked tokens
const newToken = _.assign({}, token, {
const newToken = {
...token,
isTracked: false,
});
};
this.props.dispatcher.updateTokenByAddress([newToken]);
} else {
this.props.dispatcher.removeTokenToTokenByAddress(token);
@@ -507,7 +508,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
return (
<div>
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.
</div>
);
@@ -580,7 +581,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
return true;
} catch (err) {
const errMsg = '' + err;
if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) {
if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
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
// 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({
errorType: BalanceErrs.incorrectNetworkForFaucet,
});
@@ -614,7 +615,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
await utils.sleepAsync(ARTIFICIAL_FAUCET_REQUEST_DELAY);
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();
if (response.status !== constants.SUCCESS_STATUS) {
utils.consoleLog(`Unexpected status code: ${response.status} -> ${responseBody}`);

View File

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

View File

@@ -1,10 +1,10 @@
import * as _ from 'lodash';
import * as React from 'react';
import {Link} from 'react-router-dom';
import {colors} from 'ts/utils/colors';
const CUSTOM_DARK_GRAY = '#231F20';
const DEFAULT_STYLE = {
color: CUSTOM_DARK_GRAY,
color: colors.darkestGrey,
};
interface TopBarMenuItemProps {
@@ -28,7 +28,7 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM
public render() {
const primaryStyles = this.props.isPrimary ? {
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,
paddingLeft: 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 linkColor = _.isUndefined(menuItemColor) ?
CUSTOM_DARK_GRAY :
colors.darkestGrey :
menuItemColor;
return (
<div

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
import {colors} from 'material-ui/styles';
import * as React from 'react';
import {colors} from 'ts/utils/colors';
export interface InputLabelProps {
text: string | Element | React.ReactNode;
@@ -7,7 +7,7 @@ export interface InputLabelProps {
const styles = {
label: {
color: colors.grey500,
color: colors.grey,
fontSize: 12,
pointerEvents: 'none',
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 RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils';
const COMPLETE_STATE_SHOW_LENGTH_MS = 2000;
@@ -31,8 +32,8 @@ export class LifeCycleRaisedButton extends
React.Component<LifeCycleRaisedButtonProps, LifeCycleRaisedButtonState> {
public static defaultProps: Partial<LifeCycleRaisedButtonProps> = {
isDisabled: false,
backgroundColor: 'white',
labelColor: 'rgb(97, 97, 97)',
backgroundColor: colors.white,
labelColor: colors.darkGrey,
};
private buttonTimeoutId: number;
private didUnmount: boolean;

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,8 +1,8 @@
// Polyfills
import 'whatwg-fetch';
import BigNumber from 'bignumber.js';
import {colors, getMuiTheme, MuiThemeProvider} from 'material-ui/styles';
import {bigNumberConfigs} from '@0xproject/utils';
import {MuiThemeProvider} from 'material-ui/styles';
import * as React from 'react';
import {render} from 'react-dom';
import {Provider} from 'react-redux';
@@ -19,59 +19,18 @@ import {NotFound} from 'ts/pages/not_found';
import {Wiki} from 'ts/pages/wiki/wiki';
import {reducer, State} from 'ts/redux/reducer';
import {WebsitePaths} from 'ts/types';
import {constants} from 'ts/utils/constants';
import {muiTheme} from 'ts/utils/mui_theme';
injectTapEventPlugin();
// By default BigNumber's `toString` method converts to exponential notation if the value has
// more then 20 digits. We want to avoid this behavior, so we set EXPONENTIAL_AT to a high number
BigNumber.config({
EXPONENTIAL_AT: 1000,
});
bigNumberConfigs.configure();
// Check if we've introduced an update that requires us to clear the tradeHistory local storage entries
tradeHistoryStorage.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 '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,
// 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

View File

@@ -11,10 +11,10 @@ export const trackedTokenStorage = {
// that introduced a backward incompatible change requiring the tracked tokens to be re-set
clearIfRequired() {
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.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) {
const trackedTokensByUserAddress = this.getTrackedTokensByUserAddress();

View File

@@ -16,7 +16,7 @@ export const tradeHistoryStorage = {
// the blockchain
clearIfRequired() {
const lastClearFillDate = localStorage.getItemIfExists(FILL_CLEAR_KEY);
if (lastClearFillDate !== configs.lastLocalStorageFillClearanceDate) {
if (lastClearFillDate !== configs.LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE) {
const localStorageKeys = localStorage.getAllKeys();
_.each(localStorageKeys, key => {
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) {
const fillsByHash = this.getUserFillsByHash(userAddress, networkId);

View File

@@ -1,18 +1,14 @@
import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
import {Footer} from 'ts/components/footer';
import {TopBar} from 'ts/components/top_bar';
import {Profile} from 'ts/pages/about/profile';
import {ProfileInfo, Styles} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils';
const CUSTOM_BACKGROUND_COLOR = '#F0F0F0';
const CUSTOM_GRAY = '#4C4C4C';
const CUSTOM_LIGHT_GRAY = '#A2A2A2';
const teamRow1: ProfileInfo[] = [
{
name: 'Will Warren',
@@ -145,6 +141,12 @@ const styles: Styles = {
color: 'black',
paddingTop: 110,
},
weAreHiring: {
fontSize: 30,
color: colors.darkestGrey,
fontFamily: 'Roboto Mono',
letterSpacing: 7.5,
},
};
export class About extends React.Component<AboutProps, AboutState> {
@@ -153,12 +155,12 @@ export class About extends React.Component<AboutProps, AboutState> {
}
public render() {
return (
<div style={{backgroundColor: CUSTOM_BACKGROUND_COLOR}}>
<div style={{backgroundColor: colors.lightestGrey}}>
<DocumentTitle title="0x About Us"/>
<TopBar
blockchainIsLoaded={false}
location={this.props.location}
style={{backgroundColor: CUSTOM_BACKGROUND_COLOR}}
style={{backgroundColor: colors.lightestGrey}}
/>
<div
id="about"
@@ -176,7 +178,7 @@ export class About extends React.Component<AboutProps, AboutState> {
</div>
<div
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
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="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:
</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="pb2"
style={{fontSize: 30, color: CUSTOM_GRAY, fontFamily: 'Roboto Mono', letterSpacing: 7.5}}
style={styles.weAreHiring}
>
WE'RE HIRING
</div>
<div
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{' '}
<a
href={constants.ANGELLIST_URL}
href={constants.URL_ANGELLIST}
target="_blank"
style={{color: 'black'}}
>
@@ -226,7 +228,7 @@ export class About extends React.Component<AboutProps, AboutState> {
</div>
</div>
</div>
<Footer location={this.props.location} />
<Footer />
</div>
);
}

View File

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

View File

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

View File

@@ -4,8 +4,7 @@ import {DocsInfo} from 'ts/pages/documentation/docs_info';
import {Type} from 'ts/pages/documentation/type';
import {AnchorTitle} from 'ts/pages/shared/anchor_title';
import {Event, EventArg, HeaderSizes} from 'ts/types';
const CUSTOM_GREEN = 'rgb(77, 162, 75)';
import {colors} from 'ts/utils/colors';
interface EventDefinitionProps {
event: Event;
@@ -50,7 +49,7 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event
);
}
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 type = (
<Type

View File

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

View File

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

View File

@@ -1,24 +1,21 @@
import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react';
import {Link as ScrollLink} from 'react-scroll';
import * as ReactTooltip from 'react-tooltip';
import {DocsInfo} from 'ts/pages/documentation/docs_info';
import {TypeDefinition} from 'ts/pages/documentation/type_definition';
import {Type as TypeDef, TypeDefinitionByName, TypeDocTypes} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {constants} from 'ts/utils/constants';
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.
const typeToUrl: {[typeName: string]: string} = {
Web3: constants.WEB3_DOCS_URL,
Provider: constants.WEB3_PROVIDER_DOCS_URL,
BigNumber: constants.BIGNUMBERJS_GITHUB_URL,
DecodedLogEntryEvent: constants.WEB3_DECODED_LOG_ENTRY_EVENT_URL,
LogEntryEvent: constants.WEB3_LOG_ENTRY_EVENT_URL,
Web3: constants.URL_WEB3_DOCS,
Provider: constants.URL_WEB3_PROVIDER_DOCS,
BigNumber: constants.URL_BIGNUMBERJS_GITHUB,
DecodedLogEntryEvent: constants.URL_WEB3_DECODED_LOG_ENTRY_EVENT,
LogEntryEvent: constants.URL_WEB3_LOG_ENTRY_EVENT,
};
const typePrefix: {[typeName: string]: string} = {
@@ -56,7 +53,7 @@ export function Type(props: TypeProps): any {
case TypeDocTypes.Intrinsic:
case TypeDocTypes.Unknown:
typeName = type.name;
typeNameColor = BUILT_IN_TYPE_COLOR;
typeNameColor = colors.orange;
break;
case TypeDocTypes.Reference:
@@ -90,7 +87,7 @@ export function Type(props: TypeProps): any {
case TypeDocTypes.StringLiteral:
typeName = `'${type.value}'`;
typeNameColor = STRING_LITERAL_COLOR;
typeNameColor = colors.green;
break;
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 {AnchorTitle} from 'ts/pages/shared/anchor_title';
import {CustomType, CustomTypeChild, HeaderSizes, KindString, TypeDocTypes} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {utils} from 'ts/utils/utils';
const KEYWORD_COLOR = '#a81ca6';
interface TypeDefinitionProps {
customType: CustomType;
shouldAddId?: boolean;
@@ -76,11 +75,15 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
);
break;
case KindString['Type alias']:
case KindString.TypeAlias:
typePrefix = 'Type Alias';
codeSnippet = (
<span>
<span style={{color: KEYWORD_COLOR}}>type</span> {customType.name} ={' '}
<span
style={{color: colors.lightPurple}}
>
type
</span> {customType.name} ={' '}
{customType.type.typeDocType !== TypeDocTypes.Reflection ?
<Type type={customType.type} docsInfo={this.props.docsInfo} /> :
<MethodSignature

View File

@@ -1,11 +1,11 @@
import * as _ from 'lodash';
import {colors} from 'material-ui/styles';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
import {Footer} from 'ts/components/footer';
import {TopBar} from 'ts/components/top_bar';
import {Question} from 'ts/pages/faq/question';
import {FAQQuestion, FAQSection, Styles, WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants';
@@ -411,7 +411,7 @@ const sections: FAQSection[] = [
prompt: 'How can I get involved?',
answer: (
<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
developers to contribute proposals, ideas and code.
</div>
@@ -462,7 +462,7 @@ export class FAQ extends React.Component<FAQProps, FAQState> {
{this.renderSections()}
</div>
</div>
<Footer location={this.props.location} />
<Footer />
</div>
);
}

View File

@@ -1,6 +1,7 @@
import * as _ from 'lodash';
import {Card, CardHeader, CardText} from 'material-ui/Card';
import * as React from 'react';
import {colors} from 'ts/utils/colors';
export interface QuestionProps {
prompt: string;
@@ -31,7 +32,7 @@ export class Question extends React.Component<QuestionProps, QuestionState> {
<CardHeader
title={this.props.prompt}
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}
showExpandableButton={true}
/>

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
import {colors} from 'material-ui/styles';
import * as React from 'react';
import DocumentTitle = require('react-document-title');
import {
@@ -11,6 +10,7 @@ import {MarkdownSection} from 'ts/pages/shared/markdown_section';
import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu';
import {SectionHeader} from 'ts/pages/shared/section_header';
import {Article, ArticlesBySection, HeaderSizes, Styles, WebsitePaths} from 'ts/types';
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants';
import {utils} from 'ts/utils/utils';
@@ -112,7 +112,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
>
<div id="0xProtocolWiki" />
<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
</a>
</h1>
@@ -134,7 +134,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
private renderSection(sectionName: string) {
const articles = this.state.articlesBySection[sectionName];
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 (
<div key={`markdown-section-${article.title}`}>
<MarkdownSection
@@ -143,7 +143,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
headerSize={HeaderSizes.H2}
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?{' '}
<a
href={githubLink}

View File

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

View File

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

View File

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

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 {
ContractAddresses,
Environments,
Networks,
OutdatedWrappedEtherByNetworkId,
PublicNodeUrlsByNetworkId,
SmartContractDocSections,
} from 'ts/types';
const BASE_URL = window.location.origin;
const isDevelopment = _.includes(BASE_URL, 'https://0xproject.dev:3572') ||
_.includes(BASE_URL, 'https://localhost:3572') ||
_.includes(BASE_URL, 'https://127.0.0.1');
const isDevelopment = _.includes([
'https://0xproject.localhost:3572',
'https://localhost:3572',
'https://127.0.0.1',
], BASE_URL);
const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs';
export const configs = {
BASE_URL,
ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION,
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
defaultTrackedTokenSymbols: ['WETH', 'ZRX'],
lastLocalStorageFillClearanceDate: '2017-11-22',
lastLocalStorageTrackedTokenClearanceDate: '2017-12-13',
isMainnetEnabled: true,
outdatedWrappedEthers: [
DEFAULT_TRACKED_TOKEN_SYMBOLS: ['WETH', 'ZRX'],
DOMAIN_STAGING: 'staging-0xproject.s3-website-us-east-1.amazonaws.com',
DOMAIN_DEVELOPMENT: '0xproject.localhost:3572',
DOMAIN_PRODUCTION: '0xproject.com',
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: {
address: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c',
@@ -37,4 +117,15 @@ export const configs = {
},
},
] 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 {
ContractAddresses,
Docs,
Networks,
PublicNodeUrlsByNetworkId,
WebsitePaths,
} 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 = {
ANGELLIST_URL: 'https://angel.co/0xproject/jobs',
STAGING_DOMAIN: 'staging-0xproject.s3-website-us-east-1.amazonaws.com',
PRODUCTION_DOMAIN: '0xproject.com',
DEVELOPMENT_DOMAIN: '0xproject.dev:3572',
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',
DECIMAL_PLACES_ETH: 18,
DECIMAL_PLACES_ZRX: 18,
DOCS_SCROLL_DURATION_MS: 0,
DOCS_CONTAINER_ID: 'documentation',
GENESIS_ORDER_BLOCK_BY_NETWORK_ID: {
1: 4145578,
42: 3117574,
50: 0,
} as {[networkId: number]: number},
PUBLIC_PROVIDER_NAME: '0x Public',
// 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,
PARITY_SIGNER_PROVIDER_NAME: 'Parity Signer',
GENERIC_PROVIDER_NAME: 'Injected Web3',
HOME_SCROLL_DURATION_MS: 500,
HTTP_NO_CONTENT_STATUS_CODE: 204,
LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER: 'didAcceptPortalDisclaimer',
LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE: 'hasDismissedWethNotice',
MAKER_FEE: new BigNumber(0),
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'),
WEB3_DOCS_URL: 'https://github.com/ethereum/wiki/wiki/JavaScript-API',
WEB3_PROVIDER_DOCS_URL: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150',
WEB3_DECODED_LOG_ENTRY_EVENT_URL:
'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L123',
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: {
NETWORK_ID_MAINNET: 1,
NETWORK_ID_TESTNET: 42,
NETWORK_ID_TESTRPC: 50,
NETWORK_NAME_BY_ID: {
1: Networks.mainnet,
3: Networks.ropsten,
4: Networks.rinkeby,
42: Networks.kovan,
} as {[symbol: number]: string},
networkIdByName: {
NETWORK_ID_BY_NAME: {
[Networks.mainnet]: 1,
[Networks.ropsten]: 3,
[Networks.rinkeby]: 4,
[Networks.kovan]: 42,
} as {[networkName: string]: number},
docToPath: {
[Docs.ZeroExJs]: WebsitePaths.ZeroExJs,
[Docs.SmartContracts]: WebsitePaths.SmartContracts,
},
smartContractDocSections,
contractAddresses: {
'1.0.0': {
[Networks.mainnet]: {
[smartContractDocSections.Exchange]: '0x12459c951127e0c374ff9105dda097662a027093',
[smartContractDocSections.TokenTransferProxy]: '0x8da0d80f5007ef1e431dd2127178d224e32c2ef4',
[smartContractDocSections.ZRXToken]: '0xe41d2489571d322189246dafa5ebde1f4699f498',
[smartContractDocSections.EtherToken]: '0x2956356cd2a2bf3202f771f50d3d14a367b48070',
[smartContractDocSections.TokenRegistry]: '0x926a74c5c36adf004c87399e65f75628b0f98d2c',
},
[Networks.ropsten]: {
[smartContractDocSections.Exchange]: '0x479cc461fecd078f766ecc58533d6f69580cf3ac',
[smartContractDocSections.TokenTransferProxy]: '0x4e9aad8184de8833365fea970cd9149372fdf1e6',
[smartContractDocSections.ZRXToken]: '0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d',
[smartContractDocSections.EtherToken]: '0xc00fd9820cd2898cc4c054b7bf142de637ad129a',
[smartContractDocSections.TokenRegistry]: '0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed',
},
[Networks.kovan]: {
[smartContractDocSections.Exchange]: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364',
[smartContractDocSections.TokenTransferProxy]: '0x087Eed4Bc1ee3DE49BeFbd66C662B434B15d49d4',
[smartContractDocSections.ZRXToken]: '0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570',
[smartContractDocSections.EtherToken]: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c',
[smartContractDocSections.TokenRegistry]: '0xf18e504561f4347bea557f3d4558f559dddbae7f',
},
},
} as ContractAddresses,
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
PROVIDER_NAME_LEDGER: 'Ledger',
PROVIDER_NAME_METAMASK: 'Metamask',
PROVIDER_NAME_PARITY_SIGNER: 'Parity Signer',
PROVIDER_NAME_GENERIC: 'Injected Web3',
PROVIDER_NAME_PUBLIC: '0x Public',
ROLLBAR_ACCESS_TOKEN: 'a6619002b51c4464928201e6ea94de65',
SUCCESS_STATUS: 200,
UNAVAILABLE_STATUS: 503,
TAKER_FEE: new BigNumber(0),
TESTNET_NAME: 'Kovan',
PROJECT_URL_ETHFINEX: 'https://www.bitfinex.com/ethfinex',
PROJECT_URL_RADAR_RELAY: 'https://radarrelay.com',
PROJECT_URL_PARADEX: 'https://paradex.io',
PROJECT_URL_DYDX: 'https://dydx.exchange',
PROJECT_URL_MELONPORT: 'https://melonport.com',
PROJECT_URL_DISTRICT_0X: 'https://district0x.io',
PROJECT_URL_DHARMA: 'https://dharma.io',
PROJECT_URL_LENDROID: 'https://lendroid.com',
PROJECT_URL_MAKER: 'https://makerdao.com',
PROJECT_URL_ARAGON: 'https://aragon.one',
PROJECT_URL_BLOCKNET: 'https://blocknet.co',
PROJECT_URL_0CEAN: 'http://the0cean.com',
PROJECT_URL_STATUS: 'https://status.im',
PROJECT_URL_AUGUR: 'https://augur.net',
PROJECT_URL_AUCTUS: 'https://auctus.org',
PROJECT_URL_OPEN_ANX: 'https://www.openanx.org',
URL_ANGELLIST: 'https://angel.co/0xproject/jobs',
URL_BIGNUMBERJS_GITHUB: 'http://mikemcl.github.io/bignumber.js',
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,
},
uncaughtErrorLevel: 'error',
hostWhiteList: [constants.PRODUCTION_DOMAIN, constants.STAGING_DOMAIN],
hostWhiteList: [configs.DOMAIN_PRODUCTION, configs.DOMAIN_STAGING],
ignoredMessages: [
// Errors from the third-party scripts
'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 {
return entity.kindString === KindString.Interface ||
entity.kindString === KindString.Function ||
entity.kindString === KindString['Type alias'] ||
entity.kindString === KindString.TypeAlias ||
entity.kindString === KindString.Variable ||
entity.kindString === KindString.Enumeration;
},
@@ -126,7 +126,7 @@ export const typeDocUtils = {
case KindString.Function:
case KindString.Variable:
case KindString.Enumeration:
case KindString['Type alias']:
case KindString.TypeAlias:
if (docsInfo.isPublicType(entity.name)) {
const customType = typeDocUtils._convertCustomType(
entity, docsInfo.sections, sectionName, docsInfo.subPackageName);

View File

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