Merge branch 'development' into createWethPage

* development: (27 commits)
  Remove re-assignment
  Fix scrolling topBar on Portal
  Fix overflow issue on calculated fillAmount
  Fix faulty import
  Introduce an identityCommandBuilder
  Define types for methodID
  Define types for ethereumjs-abi
  Install types for yargs
  Fix comments
  Fix linter issues
  Fix linter error
  Rename SubscriptionOpts to BlockRange
  Refactor remaining _.assign to spread operator
  Move muiTheme into it's own module
  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
  ...

# Conflicts:
#	packages/website/ts/components/eth_wrappers.tsx
#	packages/website/ts/components/portal.tsx
#	packages/website/ts/utils/configs.ts
#	packages/website/ts/utils/constants.ts
This commit is contained in:
Fabio Berger
2017-12-19 22:58:06 +01:00
92 changed files with 1009 additions and 1048 deletions

View File

@@ -1,10 +1,11 @@
# CHANGELOG
v0.28.0 - _TBD_
v0.x.x - _TBD, 2017_
------------------------
* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken` (#267)
* Removed accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry` (#267)
* Removed `etherTokenContractAddress` from `ZeroEx` constructor arg `ZeroExConfig` (#267)
* Add `etherTokenAddress` arg to `depositAsync` and `withdrawAsync` methods on `zeroEx.etherToken` (#267)
* Removed accidentally included `unsubscribeAll` method from `zeroEx.proxy`, `zeroEx.etherToken` and `zeroEx.tokenRegistry` (#267)
* Removed `etherTokenContractAddress` from `ZeroEx` constructor arg `ZeroExConfig` (#267)
* Rename `SubscriptionOpts` to `BlockRange` (#272)
v0.27.1 - _November 28, 2017_
------------------------

View File

@@ -7,6 +7,7 @@ import * as Web3 from 'web3';
import {
Artifact,
BlockParamLiteral,
BlockRange,
ContractEventArgs,
ContractEvents,
EventCallback,
@@ -14,7 +15,6 @@ import {
InternalZeroExError,
LogWithDecodedArgs,
RawLog,
SubscriptionOpts,
ZeroExError,
} from '../types';
import {AbiDecoder} from '../utils/abi_decoder';
@@ -83,9 +83,9 @@ export class ContractWrapper {
return filterToken;
}
protected async _getLogsAsync<ArgsType extends ContractEventArgs>(
address: string, eventName: ContractEvents, subscriptionOpts: SubscriptionOpts,
address: string, eventName: ContractEvents, blockRange: BlockRange,
indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, subscriptionOpts);
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi, blockRange);
const logs = await this._web3Wrapper.getLogsAsync(filter);
const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
return logsWithDecodedArguments;

View File

@@ -7,6 +7,7 @@ import * as Web3 from 'web3';
import {artifacts} from '../artifacts';
import {
BlockParamLiteral,
BlockRange,
DecodedLogArgs,
ECSignature,
EventCallback,
@@ -25,7 +26,6 @@ import {
OrderTransactionOpts,
OrderValues,
SignedOrder,
SubscriptionOpts,
ValidateOrderFillableOpts,
} from '../types';
import {AbiDecoder} from '../utils/abi_decoder';
@@ -616,20 +616,20 @@ export class ExchangeWrapper extends ContractWrapper {
/**
* Gets historical logs without creating a subscription
* @param eventName The exchange contract event you would like to subscribe to.
* @param subscriptionOpts Subscriptions options that let you configure the subscription.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends ExchangeContractEventArgs>(
eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts, indexFilterValues: IndexedFilterValues,
eventName: ExchangeEvents, blockRange: BlockRange, indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
assert.doesConformToSchema('subscriptionOpts', subscriptionOpts, schemas.subscriptionOptsSchema);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const exchangeContractAddress = this.getContractAddress();
const logs = await this._getLogsAsync<ArgsType>(
exchangeContractAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.ExchangeArtifact.abi,
exchangeContractAddress, eventName, blockRange, indexFilterValues, artifacts.ExchangeArtifact.abi,
);
return logs;
}

View File

@@ -5,11 +5,11 @@ import * as _ from 'lodash';
import {artifacts} from '../artifacts';
import {
BlockRange,
EventCallback,
IndexedFilterValues,
LogWithDecodedArgs,
MethodOpts,
SubscriptionOpts,
TokenContractEventArgs,
TokenEvents,
TransactionOpts,
@@ -291,20 +291,20 @@ export class TokenWrapper extends ContractWrapper {
* Gets historical logs without creating a subscription
* @param tokenAddress An address of the token that emmited the logs.
* @param eventName The token contract event you would like to subscribe to.
* @param subscriptionOpts Subscriptions options that let you configure the subscription.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends TokenContractEventArgs>(
tokenAddress: string, eventName: TokenEvents, subscriptionOpts: SubscriptionOpts,
tokenAddress: string, eventName: TokenEvents, blockRange: BlockRange,
indexFilterValues: IndexedFilterValues): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.doesBelongToStringEnum('eventName', eventName, TokenEvents);
assert.doesConformToSchema('subscriptionOpts', subscriptionOpts, schemas.subscriptionOptsSchema);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._getLogsAsync<ArgsType>(
tokenAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.TokenArtifact.abi,
tokenAddress, eventName, blockRange, indexFilterValues, artifacts.TokenArtifact.abi,
);
return logs;
}

View File

@@ -12,7 +12,7 @@ export {
ExchangeEvents,
TokenEvents,
IndexedFilterValues,
SubscriptionOpts,
BlockRange,
BlockParam,
OrderCancellationRequest,
OrderFillRequest,

View File

@@ -217,7 +217,7 @@ export enum BlockParamLiteral {
export type BlockParam = BlockParamLiteral|number;
export interface SubscriptionOpts {
export interface BlockRange {
fromBlock: BlockParam;
toBlock: BlockParam;
}

View File

@@ -4,7 +4,7 @@ import * as _ from 'lodash';
import * as uuid from 'uuid/v4';
import * as Web3 from 'web3';
import {ContractEvents, IndexedFilterValues, SubscriptionOpts} from '../types';
import {BlockRange, ContractEvents, IndexedFilterValues} from '../types';
const TOPIC_LENGTH = 32;
@@ -14,7 +14,7 @@ export const filterUtils = {
},
getFilter(address: string, eventName: ContractEvents,
indexFilterValues: IndexedFilterValues, abi: Web3.ContractAbi,
subscriptionOpts?: SubscriptionOpts): Web3.FilterObject {
blockRange?: BlockRange): Web3.FilterObject {
const eventAbi = _.find(abi, {name: eventName}) as Web3.EventAbi;
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi, eventName);
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
@@ -24,9 +24,9 @@ export const filterUtils = {
address,
topics,
};
if (!_.isUndefined(subscriptionOpts)) {
if (!_.isUndefined(blockRange)) {
filter = {
...subscriptionOpts,
...blockRange,
...filter,
};
}

View File

@@ -5,6 +5,7 @@ import 'mocha';
import * as Web3 from 'web3';
import {
BlockRange,
DecodedLogEvent,
ExchangeContractErrs,
ExchangeEvents,
@@ -13,7 +14,6 @@ import {
OrderCancellationRequest,
OrderFillRequest,
SignedOrder,
SubscriptionOpts,
Token,
ZeroEx,
} from '../src';
@@ -760,7 +760,7 @@ describe('ExchangeWrapper', () => {
let takerAddress: string;
const fillableAmount = new BigNumber(5);
const shouldThrowOnInsufficientBalanceOrAllowance = true;
const subscriptionOpts: SubscriptionOpts = {
const blockRange: BlockRange = {
fromBlock: 0,
toBlock: BlockParamLiteral.Latest,
};
@@ -781,7 +781,7 @@ describe('ExchangeWrapper', () => {
await zeroEx.awaitTransactionMinedAsync(txHash);
const eventName = ExchangeEvents.LogFill;
const indexFilterValues = {};
const logs = await zeroEx.exchange.getLogsAsync(eventName, subscriptionOpts, indexFilterValues);
const logs = await zeroEx.exchange.getLogsAsync(eventName, blockRange, indexFilterValues);
expect(logs).to.have.length(1);
expect(logs[0].event).to.be.equal(eventName);
});
@@ -795,7 +795,7 @@ describe('ExchangeWrapper', () => {
await zeroEx.awaitTransactionMinedAsync(txHash);
const differentEventName = ExchangeEvents.LogCancel;
const indexFilterValues = {};
const logs = await zeroEx.exchange.getLogsAsync(differentEventName, subscriptionOpts, indexFilterValues);
const logs = await zeroEx.exchange.getLogsAsync(differentEventName, blockRange, indexFilterValues);
expect(logs).to.have.length(0);
});
it('should only get the logs with the correct indexed fields', async () => {
@@ -821,7 +821,7 @@ describe('ExchangeWrapper', () => {
maker: differentMakerAddress,
};
const logs = await zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
eventName, subscriptionOpts, indexFilterValues,
eventName, blockRange, indexFilterValues,
);
expect(logs).to.have.length(1);
const args = logs[0].args;

View File

@@ -7,8 +7,8 @@ import * as Web3 from 'web3';
import {
ApprovalContractEventArgs,
BlockRange,
DecodedLogEvent,
SubscriptionOpts,
Token,
TokenEvents,
TransferContractEventArgs,
@@ -433,7 +433,7 @@ describe('TokenWrapper', () => {
describe('#getLogsAsync', () => {
let tokenAddress: string;
let tokenTransferProxyAddress: string;
const subscriptionOpts: SubscriptionOpts = {
const blockRange: BlockRange = {
fromBlock: 0,
toBlock: BlockParamLiteral.Latest,
};
@@ -449,7 +449,7 @@ describe('TokenWrapper', () => {
const eventName = TokenEvents.Approval;
const indexFilterValues = {};
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
tokenAddress, eventName, subscriptionOpts, indexFilterValues,
tokenAddress, eventName, blockRange, indexFilterValues,
);
expect(logs).to.have.length(1);
const args = logs[0].args;
@@ -464,7 +464,7 @@ describe('TokenWrapper', () => {
const differentEventName = TokenEvents.Transfer;
const indexFilterValues = {};
const logs = await zeroEx.token.getLogsAsync(
tokenAddress, differentEventName, subscriptionOpts, indexFilterValues,
tokenAddress, differentEventName, blockRange, indexFilterValues,
);
expect(logs).to.have.length(0);
});
@@ -478,7 +478,7 @@ describe('TokenWrapper', () => {
_owner: coinbase,
};
const logs = await zeroEx.token.getLogsAsync<ApprovalContractEventArgs>(
tokenAddress, eventName, subscriptionOpts, indexFilterValues,
tokenAddress, eventName, blockRange, indexFilterValues,
);
expect(logs).to.have.length(1);
const args = logs[0].args;

View File

@@ -38,7 +38,7 @@
"@types/handlebars": "^4.0.36",
"@types/mkdirp": "^0.5.1",
"@types/node": "^8.0.53",
"@types/yargs": "^8.0.2",
"@types/yargs": "^10.0.0",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"tslint": "5.8.0",

View File

@@ -23,12 +23,12 @@ const DEFAULT_GAS_PRICE = ((10 ** 9) * 2).toString();
* Compiles all contracts with options passed in through CLI.
* @param argv Instance of process.argv provided by yargs.
*/
async function onCompileCommand(args: CliOptions): Promise<void> {
async function onCompileCommand(argv: CliOptions): Promise<void> {
const opts: CompilerOptions = {
contractsDir: args.contractsDir,
networkId: args.networkId,
optimizerEnabled: args.shouldOptimize ? 1 : 0,
artifactsDir: args.artifactsDir,
contractsDir: argv.contractsDir,
networkId: argv.networkId,
optimizerEnabled: argv.shouldOptimize ? 1 : 0,
artifactsDir: argv.artifactsDir,
};
await commands.compileAsync(opts);
}
@@ -113,6 +113,7 @@ function deployCommandBuilder(yargsInstance: any) {
}
(() => {
const identityCommandBuilder = _.identity;
return yargs
.option('contracts-dir', {
type: 'string',
@@ -150,11 +151,11 @@ function deployCommandBuilder(yargsInstance: any) {
})
.command('compile',
'compile contracts',
_.noop,
identityCommandBuilder,
onCompileCommand)
.command('migrate',
'compile and deploy contracts using migration scripts',
_.noop,
identityCommandBuilder,
onMigrateCommand)
.command('deploy',
'deploy a single contract with provided arguments',

View File

@@ -1,5 +1,6 @@
import {TxData} from '@0xproject/types';
import * as Web3 from 'web3';
import * as yargs from 'yargs';
export enum AbiType {
Function = 'function',
@@ -32,7 +33,7 @@ export interface SolcErrors {
[key: string]: boolean;
}
export interface CliOptions {
export interface CliOptions extends yargs.Arguments {
artifactsDir: string;
contractsDir: string;
jsonrpcPort: number;

View File

@@ -1,8 +1,5 @@
declare module 'bn.js';
declare module 'ethereumjs-abi';
declare module 'chai-bignumber';
declare module 'dirty-chai';
declare module 'yargs';
// HACK: In order to merge the bignumber declaration added by chai-bignumber to the chai Assertion
// interface we must use `namespace` as the Chai definitelyTyped definition does. Since we otherwise
@@ -31,6 +28,11 @@ declare module 'web3-eth-abi' {
export function encodeParameters(typesArray: string[], parameters: any[]): string;
}
declare module 'ethereumjs-abi' {
const soliditySHA3: (argTypes: string[], args: any[]) => Buffer;
const methodID: (name: string, types: string[]) => Buffer;
}
// Truffle injects the following into the global scope
declare var artifacts: any;
declare var contract: any;

View File

@@ -36,7 +36,7 @@
"@types/lodash": "^4.14.86",
"@types/node": "^8.0.53",
"@types/request-promise-native": "^1.0.2",
"@types/yargs": "^8.0.2",
"@types/yargs": "^10.0.0",
"chai": "^4.0.1",
"chai-as-promised": "^7.1.0",
"chai-as-promised-typescript-typings": "^0.0.3",

View File

@@ -1,5 +1,9 @@
# CHANGELOG
v0.x.x - _TBD, 2017_
------------------------
* Rename `subscriptionOptsSchema` to `blockRangeSchema` (#272)
v0.6.7 - _Nov. 14, 2017_
------------------------
* Re-publish JSON-schema previously published under NPM package 0x-json-schemas

View File

@@ -10,8 +10,8 @@ export const blockParamSchema = {
],
};
export const subscriptionOptsSchema = {
id: '/SubscriptionOpts',
export const blockRangeSchema = {
id: '/BlockRange',
properties: {
fromBlock: {$ref: '/BlockParam'},
toBlock: {$ref: '/BlockParam'},

View File

@@ -2,6 +2,10 @@ import {
addressSchema,
numberSchema,
} from '../schemas/basic_type_schemas';
import {
blockParamSchema,
blockRangeSchema,
} from '../schemas/block_range_schema';
import {
ecSignatureParameterSchema,
ecSignatureSchema,
@@ -55,10 +59,6 @@ import {
import {
signedOrdersSchema,
} from '../schemas/signed_orders_schema';
import {
blockParamSchema,
subscriptionOptsSchema,
} from '../schemas/subscription_opts_schema';
import {
tokenSchema,
} from '../schemas/token_schema';
@@ -81,7 +81,7 @@ export const schemas = {
signedOrderSchema,
signedOrdersSchema,
blockParamSchema,
subscriptionOptsSchema,
blockRangeSchema,
tokenSchema,
jsNumber,
txDataSchema,

View File

@@ -23,7 +23,7 @@ const {
signedOrderSchema,
signedOrdersSchema,
blockParamSchema,
subscriptionOptsSchema,
blockRangeSchema,
tokenSchema,
jsNumber,
txDataSchema,
@@ -170,21 +170,21 @@ describe('Schema', () => {
validateAgainstSchema(testCases, blockParamSchema, shouldFail);
});
});
describe('#subscriptionOptsSchema', () => {
describe('#blockRangeSchema', () => {
it('should validate valid subscription opts', () => {
const testCases = [
{fromBlock: 42, toBlock: 'latest'},
{fromBlock: 42},
{},
];
validateAgainstSchema(testCases, subscriptionOptsSchema);
validateAgainstSchema(testCases, blockRangeSchema);
});
it('should fail for invalid subscription opts', () => {
const testCases = [
{fromBlock: '42'},
];
const shouldFail = true;
validateAgainstSchema(testCases, subscriptionOptsSchema, shouldFail);
validateAgainstSchema(testCases, blockRangeSchema, shouldFail);
});
});
describe('#tokenSchema', () => {

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

@@ -1,5 +1,6 @@
import {
BlockParam,
BlockRange,
DecodedLogEvent,
ExchangeContractEventArgs,
ExchangeEvents,
@@ -9,7 +10,6 @@ import {
LogWithDecodedArgs,
Order,
SignedOrder,
SubscriptionOpts,
Token as ZeroExToken,
TransactionReceiptWithDecodedLogs,
ZeroEx,
@@ -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();
}
@@ -162,8 +162,8 @@ export class Blockchain {
// already in the tokenRegistry.
// TODO: Remove this hack once we've updated the TokenRegistries
// Airtable task: https://airtable.com/tblFe0Q9JuKJPYbTn/viwsOG2Y97qdIeCIO/recv3VGmIorFzHBVz
if (configs.shouldDeprecateOldWethToken &&
tokenAddress === configs.newWrappedEthers[this.networkId]) {
if (configs.SHOULD_DEPRECATE_OLD_WETH_TOKEN &&
tokenAddress === configs.NEW_WRAPPED_ETHERS[this.networkId]) {
return true;
}
const tokenIfExists = await this.zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
@@ -194,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');
@@ -213,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();
@@ -228,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
}
@@ -249,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(
@@ -266,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,
@@ -302,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;
@@ -354,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);
@@ -383,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, {
@@ -398,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);
@@ -471,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,
}));
@@ -499,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);
@@ -532,12 +532,12 @@ export class Blockchain {
}
private async fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues) {
const fromBlock = tradeHistoryStorage.getFillsLatestBlock(this.userAddress, this.networkId);
const subscriptionOpts: SubscriptionOpts = {
const blockRange: BlockRange = {
fromBlock,
toBlock: 'latest' as BlockParam,
};
const decodedLogs = await this.zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues,
ExchangeEvents.LogFill, blockRange, indexFilterValues,
);
for (const decodedLog of decodedLogs) {
if (!this.doesLogEventInvolveUser(decodedLog)) {
@@ -599,7 +599,7 @@ 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
@@ -607,8 +607,8 @@ export class Blockchain {
// TODO: Remove this hack once we've updated the TokenRegistries
// Airtable task: https://airtable.com/tblFe0Q9JuKJPYbTn/viwsOG2Y97qdIeCIO/recv3VGmIorFzHBVz
let address = t.address;
if (configs.shouldDeprecateOldWethToken && t.symbol === 'WETH') {
const newEtherTokenAddressIfExists = configs.newWrappedEthers[this.networkId];
if (configs.SHOULD_DEPRECATE_OLD_WETH_TOKEN && t.symbol === 'WETH') {
const newEtherTokenAddressIfExists = configs.NEW_WRAPPED_ETHERS[this.networkId];
if (!_.isUndefined(newEtherTokenAddressIfExists)) {
address = newEtherTokenAddressIfExists;
}
@@ -647,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,
};
@@ -669,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() {
@@ -694,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;
@@ -717,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> {
@@ -741,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);
}
}
@@ -754,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}
@@ -133,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>

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;

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

@@ -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,
@@ -26,13 +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';
@@ -86,7 +85,7 @@ 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,
@@ -100,7 +99,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<a
target="_blank"
href={constants.WETH_IO_URL}
style={{color: LIGHT_GRAY}}
style={{color: colors.grey}}
>
<div className="flex">
<div>About Wrapped ETH</div>
@@ -152,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}
@@ -171,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}
@@ -244,7 +243,7 @@ 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 outdatedWETHIfExists = outdatedWETHByNetworkId[this.props.networkId];
if (_.isUndefined(outdatedWETHIfExists)) {
@@ -266,7 +265,9 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
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, outdatedWETHIfExists.address,
@@ -290,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}
@@ -383,7 +384,8 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
});
}
private getOutdatedWETHAddresses(): string[] {
const outdatedWETHAddresses = _.compact(_.map(configs.outdatedWrappedEthers, outdatedWrappedEtherByNetwork => {
const outdatedWETHAddresses = _.compact(_.map(configs.OUTDATED_WRAPPED_ETHERS,
outdatedWrappedEtherByNetwork => {
const outdatedWrappedEtherIfExists = outdatedWrappedEtherByNetwork[this.props.networkId];
if (_.isUndefined(outdatedWrappedEtherIfExists)) {
return undefined;

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,7 +1,6 @@
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';
@@ -33,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';
@@ -74,7 +74,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
private sharedOrderIfExists: Order;
private throttledScreenWidthUpdate: () => void;
public static hasAlreadyDismissedWethNotice() {
const didDismissWethNotice = localStorage.getItemIfExists(constants.DISMISS_WETH_NOTICE_LOCAL_STORAGE_KEY);
const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE);
const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) &&
!_.isEmpty(didDismissWethNotice);
return hasAlreadyDismissedWethNotice;
@@ -87,7 +87,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`);
const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY);
const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER);
const hasAcceptedDisclaimer = !_.isUndefined(didAcceptPortalDisclaimer) &&
!_.isEmpty(didAcceptPortalDisclaimer);
this.state = {
@@ -158,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"/>
@@ -166,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">
@@ -191,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}}>
@@ -248,7 +253,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
flashMessage={this.props.flashMessage}
/>
</div>
<Footer location={this.props.location} />
<Footer />
</div>
);
}
@@ -319,7 +324,7 @@ 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({
isDisclaimerDialogOpen: false,
});

View File

@@ -70,7 +70,7 @@ 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')) {

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,33 @@ 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.EtherToken,
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,
EtherToken: Sections.EtherToken,
},
sections,
visibleConstructors: [
sections.Exchange,
sections.TokenRegistry,
sections.ZRXToken,
sections.EtherToken,
sections.TokenTransferProxy,
Sections.Exchange,
Sections.TokenRegistry,
Sections.ZRXToken,
Sections.EtherToken,
Sections.TokenTransferProxy,
],
convertToDocAgnosticFormatFn: doxityUtils.convertToDocAgnosticFormat.bind(doxityUtils),
};

View File

@@ -95,6 +95,7 @@ const docsInfoConfig: DocsInfoConfig = {
'ExchangeEvents',
'IndexedFilterValues',
'SubscriptionOpts',
'BlockRange',
'BlockParam',
'OrderFillOrKillRequest',
'OrderCancellationRequest',

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,13 @@ export interface OutdatedWrappedEtherByNetworkId {
};
}
export enum SmartContractDocSections {
Introduction = 'Introduction',
Exchange = 'Exchange',
TokenTransferProxy = 'TokenTransferProxy',
TokenRegistry = 'TokenRegistry',
ZRXToken = 'ZRXToken',
EtherToken = 'EtherToken',
}
// 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,32 +1,108 @@
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.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,
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,
shouldDeprecateOldWethToken: true,
// newWrappedEthers is temporary until we remove the shouldDeprecateOldWethToken flag
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-13',
// NEW_WRAPPED_ETHERS is temporary until we remove the SHOULD_DEPRECATE_OLD_WETH_TOKEN flag
// and add the new WETHs to the tokenRegistry
newWrappedEthers: {
NEW_WRAPPED_ETHERS: {
1: '0xe495bcacaf29a0eb00fb67b86e9cd2a994dd55d8',
42: '0x739e78d6bebbdf24105a5145fa04436589d1cbd9',
} as {[networkId: string]: string},
outdatedWrappedEthers: [
OUTDATED_WRAPPED_ETHERS: [
{
42: {
address: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c',
@@ -44,4 +120,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,190 +1,86 @@
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,
DISMISS_WETH_NOTICE_LOCAL_STORAGE_KEY: 'hasDismissedWethNotice',
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',
WETH_IO_URL: 'https://weth.io/',
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_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';

View File

@@ -266,6 +266,10 @@
dependencies:
"@types/node" "*"
"@types/yargs@^10.0.0":
version "10.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-10.0.0.tgz#b93aa88155fe5106cddf3f934517411ca2a45939"
"@types/yargs@^8.0.2":
version "8.0.2"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-8.0.2.tgz#0f9c7b236e2d78cd8f4b6502de15d0728aa29385"