Merge v2-prototype

This commit is contained in:
Fabio Berger 2018-06-06 11:30:57 +02:00
commit 787eec8be4
49 changed files with 502 additions and 129 deletions

View File

@ -16,17 +16,19 @@
"types": "lib/src/index.d.ts", "types": "lib/src/index.d.ts",
"scripts": { "scripts": {
"watch_without_deps": "yarn pre_build && tsc -w", "watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "build": "yarn pre_build && build:all && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"pre_build": "run-s generate_contract_wrappers copy_artifacts", "pre_build": "run-s generate_contract_wrappers copy_artifacts",
"copy_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts", "copy_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'", "generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
"lint": "tslint --project .", "lint": "tslint --project .",
"test:circleci": "run-s test:coverage", "test:circleci": "run-s test:coverage",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s build test", "rebuild_and_test": "run-s build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"clean": "shx rm -rf _bundles lib test_temp scripts src/contract_wrappers/generated", "clean": "shx rm -rf _bundles lib test_temp scripts src/contract_wrappers/generated",
"build:umd:prod": "NODE_ENV=production webpack",
"build:commonjs": "tsc && copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit", "run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --timeout 10000 --bail --exit",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js", "manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "node scripts/stage_docs.js", "docs:stage": "node scripts/stage_docs.js",

View File

@ -4,8 +4,7 @@ This package allows you to generate TypeScript contract wrappers from ABI files.
It's heavily inspired by [Geth abigen](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) but takes a different approach. It's heavily inspired by [Geth abigen](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts) but takes a different approach.
You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions. You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions.
For an example of the generated [wrapper files](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/src/contract_wrappers/generated) check out 0x.js. [Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/0x.js/contract_templates) are the templates used to generate the contract wrappers used by 0x.js.e
[Here](https://github.com/0xProject/0x-monorepo/tree/development/packages/contract_templates) are the templates used to generate those files.
## Installation ## Installation

View File

@ -15,7 +15,7 @@
"run_mocha": "mocha lib/test/**/*_test.js --exit", "run_mocha": "mocha lib/test/**/*_test.js --exit",
"prepublishOnly": "run-p build", "prepublishOnly": "run-p build",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"test:circleci": "yarn test:coverage", "test:circleci": "yarn test:coverage",

View File

@ -12,7 +12,7 @@
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib scripts", "clean": "shx rm -rf lib scripts",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",
"test:circleci": "yarn test:coverage", "test:circleci": "yarn test:coverage",
"run_mocha": "mocha lib/test/**/*_test.js --bail --exit", "run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",

View File

@ -22,7 +22,7 @@
"lint": "tslint --project .", "lint": "tslint --project .",
"run_mocha": "mocha lib/test/**/*_test.js --exit", "run_mocha": "mocha lib/test/**/*_test.js --exit",
"test": "run-s copy_test_fixtures run_mocha", "test": "run-s copy_test_fixtures run_mocha",
"rebuild-and-test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"test:circleci": "yarn test:coverage", "test:circleci": "yarn test:coverage",

View File

@ -18,7 +18,7 @@
"lint": "tslint --project .", "lint": "tslint --project .",
"test:circleci": "run-s test:coverage", "test:circleci": "run-s test:coverage",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s build test", "rebuild_and_test": "run-s build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"update_compact_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts", "update_compact_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts",

View File

@ -158,7 +158,7 @@ export interface MethodOpts {
/** /**
* gasPrice: Gas price in Wei to use for a transaction * gasPrice: Gas price in Wei to use for a transaction
* gasLimit: The amount of gas to send with a transaction * gasLimit: The amount of gas to send with a transaction (in Gwei)
*/ */
export interface TransactionOpts { export interface TransactionOpts {
gasPrice?: BigNumber; gasPrice?: BigNumber;

View File

@ -16,7 +16,7 @@
"pre_build": "run-s compile copy_artifacts generate_contract_wrappers", "pre_build": "run-s compile copy_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles -u 4 '../migrations/artifacts/2.0.0/**/*' ./lib/src/artifacts;", "copy_artifacts": "copyfiles -u 4 '../migrations/artifacts/2.0.0/**/*' ./lib/src/artifacts;",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s build test", "rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"run_mocha": "mocha 'lib/test/**/*.js' --timeout 100000 --bail --exit", "run_mocha": "mocha 'lib/test/**/*.js' --timeout 100000 --bail --exit",
"compile": "sol-compiler", "compile": "sol-compiler",

View File

@ -11,7 +11,7 @@
"watch_without_deps": "tsc -w", "watch_without_deps": "tsc -w",
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",
"test:circleci": "yarn test:coverage", "test:circleci": "yarn test:coverage",
"run_mocha": "mocha lib/test/**/*_test.js --bail --exit", "run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",

View File

@ -11,7 +11,7 @@
"watch_without_deps": "tsc -w", "watch_without_deps": "tsc -w",
"lint": "tslint --project .", "lint": "tslint --project .",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"test:circleci": "yarn test:coverage", "test:circleci": "yarn test:coverage",

View File

@ -14,7 +14,7 @@
"clean": "shx rm -rf lib artifacts src/contract_wrappers", "clean": "shx rm -rf lib artifacts src/contract_wrappers",
"copy_artifacts": "copyfiles './artifacts/**/*' './contracts/**/*' ./lib", "copy_artifacts": "copyfiles './artifacts/**/*' './contracts/**/*' ./lib",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s build test", "rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --bail --exit", "run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --bail --exit",
"generate_contract_wrappers": "abi-gen --abis 'artifacts/Metacoin.json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers --backend ethers && prettier --write 'src/contract_wrappers/**.ts'", "generate_contract_wrappers": "abi-gen --abis 'artifacts/Metacoin.json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers --backend ethers && prettier --write 'src/contract_wrappers/**.ts'",

View File

@ -16,7 +16,7 @@
"generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|IWallet|IValidator).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'", "generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|IWallet|IValidator).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'",
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json lib/src/artifacts; done;", "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json lib/src/artifacts; done;",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s build test", "rebuild_and_test": "run-s build test",
"test:circleci": "yarn test:coverage", "test:circleci": "yarn test:coverage",
"run_mocha": "mocha lib/test/**/*_test.js --bail --exit", "run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",

View File

@ -19,7 +19,7 @@
"lint": "tslint --project .", "lint": "tslint --project .",
"test:circleci": "run-s test:coverage", "test:circleci": "run-s test:coverage",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s build test", "rebuild_and_test": "run-s build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"update_compact_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts", "update_compact_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts",

View File

@ -22,7 +22,6 @@ const baseColors = {
heroGrey: '#404040', heroGrey: '#404040',
projectsGrey: '#343333', projectsGrey: '#343333',
darkestGrey: '#272727', darkestGrey: '#272727',
dharmaDarkGrey: '#252525',
lightBlue: '#60A4F4', lightBlue: '#60A4F4',
lightBlueA700: '#0091EA', lightBlueA700: '#0091EA',
linkBlue: '#1D5CDE', linkBlue: '#1D5CDE',

View File

@ -13,7 +13,7 @@
"pre_build": "run-s update_contract_fixtures", "pre_build": "run-s update_contract_fixtures",
"update_contract_fixtures": "copyfiles 'test/fixtures/contracts/**/*' ./lib", "update_contract_fixtures": "copyfiles 'test/fixtures/contracts/**/*' ./lib",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s build test", "rebuild_and_test": "run-s build test",
"run_mocha": "mocha lib/test/*_test.js --bail --exit", "run_mocha": "mocha lib/test/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",

View File

@ -13,7 +13,7 @@
"pre_build": "run-s copy_test_fixtures", "pre_build": "run-s copy_test_fixtures",
"lint": "tslint --project .", "lint": "tslint --project .",
"test": "run-s compile_test run_mocha", "test": "run-s compile_test run_mocha",
"rebuild-and-test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"test:circleci": "yarn test:coverage", "test:circleci": "yarn test:coverage",

View File

@ -13,7 +13,7 @@
"build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"lint": "tslint --project .", "lint": "tslint --project .",
"test": "run-s copy_test_environments copy_test_fixtures run_mocha", "test": "run-s copy_test_environments copy_test_fixtures run_mocha",
"rebuild-and-test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",
"copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures", "copy_test_fixtures": "copyfiles -u 2 './test/fixtures/**/*.json' ./lib/test/fixtures",
"copy_test_environments": "copyfiles -u 2 './test/environments/**/*.json' ./lib/test/environments", "copy_test_environments": "copyfiles -u 2 './test/environments/**/*.json' ./lib/test/environments",
"run_mocha": "mocha lib/test/**/*_test.js --exit", "run_mocha": "mocha lib/test/**/*_test.js --exit",

View File

@ -7,6 +7,7 @@
"async-suffix": true, "async-suffix": true,
"boolean-naming": true, "boolean-naming": true,
"no-switch-case-fall-through": true, "no-switch-case-fall-through": true,
"switch-default": true,
"await-promise": true, "await-promise": true,
"custom-no-magic-numbers": [true, 0, 1, 2, 3, -1], "custom-no-magic-numbers": [true, 0, 1, 2, 3, -1],
"binary-expression-operand-order": true, "binary-expression-operand-order": true,

View File

@ -13,7 +13,7 @@
"clean": "shx rm -rf lib scripts", "clean": "shx rm -rf lib scripts",
"lint": "tslint --project .", "lint": "tslint --project .",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild-and-test": "run-s clean build test", "rebuild_and_test": "run-s clean build test",
"test:circleci": "yarn test:coverage", "test:circleci": "yarn test:coverage",
"run_mocha": "mocha lib/test/**/*_test.js --bail --exit", "run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",

View File

@ -37,6 +37,7 @@
"lodash": "^4.17.4", "lodash": "^4.17.4",
"material-ui": "^0.17.1", "material-ui": "^0.17.1",
"moment": "2.21.0", "moment": "2.21.0",
"polished": "^1.9.2",
"query-string": "^6.0.0", "query-string": "^6.0.0",
"react": "15.6.1", "react": "15.6.1",
"react-copy-to-clipboard": "^4.2.3", "react-copy-to-clipboard": "^4.2.3",
@ -52,6 +53,7 @@
"redux": "^3.6.0", "redux": "^3.6.0",
"redux-devtools-extension": "^2.13.2", "redux-devtools-extension": "^2.13.2",
"semver-sort": "0.0.4", "semver-sort": "0.0.4",
"styled-components": "^3.3.0",
"thenby": "^1.2.3", "thenby": "^1.2.3",
"truffle-contract": "2.0.1", "truffle-contract": "2.0.1",
"web3": "^0.20.0", "web3": "^0.20.0",

View File

@ -0,0 +1,124 @@
import { colors } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import { Button } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Input } from 'ts/components/ui/input';
import { Text } from 'ts/components/ui/text';
import { styled } from 'ts/style/theme';
import { backendClient } from 'ts/utils/backend_client';
export interface SubscribeFormProps {}
export enum SubscribeFormStatus {
None,
Error,
Success,
Loading,
Other,
}
export interface SubscribeFormState {
emailText: string;
lastSubmittedEmail: string;
status: SubscribeFormStatus;
}
const FORM_FONT_SIZE = '15px';
// TODO: Translate visible strings. https://app.asana.com/0/628666249318202/697485674422001
export class SubscribeForm extends React.Component<SubscribeFormProps, SubscribeFormState> {
public state = {
emailText: '',
lastSubmittedEmail: '',
status: SubscribeFormStatus.None,
};
public render(): React.ReactNode {
return (
<Container className="flex flex-column items-center justify-between md-mx2 sm-mx2">
<Container marginBottom="15px">
<Text fontFamily="Roboto Mono" fontColor={colors.grey} center={true}>
Subscribe to our newsletter for 0x relayer and dApp updates
</Text>
</Container>
<form onSubmit={this._handleFormSubmitAsync.bind(this)}>
<Container className="flex flex-wrap justify-center items-center">
<Container marginTop="15px">
<Input
placeholder="you@email.com"
value={this.state.emailText}
fontColor={colors.white}
fontSize={FORM_FONT_SIZE}
backgroundColor={colors.projectsGrey}
width="300px"
onChange={this._handleEmailInputChange.bind(this)}
/>
</Container>
<Container marginLeft="15px" marginTop="15px">
<Button
type="submit"
backgroundColor={colors.darkestGrey}
fontColor={colors.white}
fontSize={FORM_FONT_SIZE}
>
Subscribe
</Button>
</Container>
</Container>
</form>
{this._renderMessage()}
</Container>
);
}
private _renderMessage(): React.ReactNode {
let message = null;
switch (this.state.status) {
case SubscribeFormStatus.Error:
message = 'Sorry, something went wrong. Try again later.';
break;
case SubscribeFormStatus.Loading:
message = 'One second...';
break;
case SubscribeFormStatus.Success:
message = `Thanks! ${this.state.lastSubmittedEmail} is now on the mailing list.`;
break;
case SubscribeFormStatus.None:
break;
default:
throw new Error(
'The SubscribeFormStatus switch statement is not exhaustive when choosing an error message.',
);
}
return (
<Container isHidden={!message} marginTop="30px">
<Text center={true} fontFamily="Roboto Mono" fontColor={colors.grey}>
{message || 'spacer text (never shown to user)'}
</Text>
</Container>
);
}
private _handleEmailInputChange(event: React.ChangeEvent<HTMLInputElement>): void {
this.setState({ emailText: event.target.value });
}
private async _handleFormSubmitAsync(event: React.FormEvent<HTMLInputElement>): Promise<void> {
event.preventDefault();
if (_.isUndefined(this.state.emailText) || _.isEmpty(this.state.emailText)) {
return;
}
this.setState({
status: SubscribeFormStatus.Loading,
lastSubmittedEmail: this.state.emailText,
});
try {
const response = await backendClient.subscribeToNewsletterAsync(this.state.emailText);
const status = response.status === 200 ? SubscribeFormStatus.Success : SubscribeFormStatus.Error;
this.setState({ status, emailText: '' });
} catch (error) {
this._setStatus(SubscribeFormStatus.Error);
}
}
private _setStatus(status: SubscribeFormStatus): void {
this.setState({ status });
}
}

View File

@ -5,9 +5,9 @@ import Toggle from 'material-ui/Toggle';
import * as React from 'react'; import * as React from 'react';
import { Blockchain } from 'ts/blockchain'; import { Blockchain } from 'ts/blockchain';
import { Dispatcher } from 'ts/redux/dispatcher'; import { Dispatcher } from 'ts/redux/dispatcher';
import { colors } from 'ts/style/colors';
import { BalanceErrs, Token, TokenState } from 'ts/types'; import { BalanceErrs, Token, TokenState } from 'ts/types';
import { analytics } from 'ts/utils/analytics'; import { analytics } from 'ts/utils/analytics';
import { colors } from 'ts/utils/colors';
import { constants } from 'ts/utils/constants'; import { constants } from 'ts/utils/constants';
import { errorReporter } from 'ts/utils/error_reporter'; import { errorReporter } from 'ts/utils/error_reporter';
import { utils } from 'ts/utils/utils'; import { utils } from 'ts/utils/utils';

View File

@ -5,7 +5,7 @@ import { Placement, Popper, PopperChildrenProps } from 'react-popper';
import { ContinueButtonDisplay, OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; import { ContinueButtonDisplay, OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip';
import { Container } from 'ts/components/ui/container'; import { Container } from 'ts/components/ui/container';
import { Overlay } from 'ts/components/ui/overlay'; import { Overlay } from 'ts/components/ui/overlay';
import { zIndex } from 'ts/utils/style'; import { zIndex } from 'ts/style/z_index';
export interface Step { export interface Step {
target: string; target: string;

View File

@ -2,7 +2,7 @@ import { Styles } from '@0xproject/react-shared';
import * as React from 'react'; import * as React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { colors } from 'ts/utils/colors'; import { colors } from 'ts/style/colors';
export interface BackButtonProps { export interface BackButtonProps {
to: string; to: string;

View File

@ -4,8 +4,8 @@ import * as React from 'react';
import { defaultMenuItemEntries, Menu } from 'ts/components/portal/menu'; import { defaultMenuItemEntries, Menu } from 'ts/components/portal/menu';
import { Identicon } from 'ts/components/ui/identicon'; import { Identicon } from 'ts/components/ui/identicon';
import { colors } from 'ts/style/colors';
import { WebsitePaths } from 'ts/types'; import { WebsitePaths } from 'ts/types';
import { colors } from 'ts/utils/colors';
import { utils } from 'ts/utils/utils'; import { utils } from 'ts/utils/utils';
const IDENTICON_DIAMETER = 45; const IDENTICON_DIAMETER = 45;

View File

@ -2,8 +2,8 @@ import { Styles } from '@0xproject/react-shared';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as React from 'react'; import * as React from 'react';
import { MenuItem } from 'ts/components/ui/menu_item'; import { MenuItem } from 'ts/components/ui/menu_item';
import { colors } from 'ts/style/colors';
import { Environments, WebsitePaths } from 'ts/types'; import { Environments, WebsitePaths } from 'ts/types';
import { colors } from 'ts/utils/colors';
import { configs } from 'ts/utils/configs'; import { configs } from 'ts/utils/configs';
export interface MenuTheme { export interface MenuTheme {

View File

@ -34,6 +34,7 @@ import { Dispatcher } from 'ts/redux/dispatcher';
import { import {
BlockchainErrs, BlockchainErrs,
HashData, HashData,
ItemByAddress,
Order, Order,
ProviderType, ProviderType,
ScreenWidths, ScreenWidths,
@ -43,6 +44,7 @@ import {
TokenVisibility, TokenVisibility,
WebsitePaths, WebsitePaths,
} from 'ts/types'; } from 'ts/types';
import { backendClient } from 'ts/utils/backend_client';
import { configs } from 'ts/utils/configs'; import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants'; import { constants } from 'ts/utils/constants';
import { orderParser } from 'ts/utils/order_parser'; import { orderParser } from 'ts/utils/order_parser';
@ -266,10 +268,6 @@ export class Portal extends React.Component<PortalProps, PortalState> {
toggleDialogFn={updateShouldBlockchainErrDialogBeOpen} toggleDialogFn={updateShouldBlockchainErrDialogBeOpen}
networkId={this.props.networkId} networkId={this.props.networkId}
/> />
<PortalDisclaimerDialog
isOpen={this.state.isDisclaimerDialogOpen}
onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)}
/>
<FlashMessage dispatcher={this.props.dispatcher} flashMessage={this.props.flashMessage} /> <FlashMessage dispatcher={this.props.dispatcher} flashMessage={this.props.flashMessage} />
{this.props.blockchainIsLoaded && ( {this.props.blockchainIsLoaded && (
<LedgerConfigDialog <LedgerConfigDialog
@ -394,18 +392,24 @@ export class Portal extends React.Component<PortalProps, PortalState> {
}, },
]; ];
return ( return (
<Switch> <div>
{_.map(accountManagementItems, item => { <Switch>
return ( {_.map(accountManagementItems, item => {
<Route return (
key={item.pathName} <Route
path={item.pathName} key={item.pathName}
render={this._renderAccountManagementItem.bind(this, item)} path={item.pathName}
/> render={this._renderAccountManagementItem.bind(this, item)}
); />
})}} );
<Route render={this._renderNotFoundMessage.bind(this)} /> })}}
</Switch> <Route render={this._renderNotFoundMessage.bind(this)} />
</Switch>
<PortalDisclaimerDialog
isOpen={this.state.isDisclaimerDialogOpen}
onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)}
/>
</div>
); );
} }
private _renderAccountManagementItem(item: AccountManagementItem): React.ReactNode { private _renderAccountManagementItem(item: AccountManagementItem): React.ReactNode {
@ -587,6 +591,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
return this._blockchain.getTokenBalanceAndAllowanceAsync(userAddressIfExists, tokenAddress); return this._blockchain.getTokenBalanceAndAllowanceAsync(userAddressIfExists, tokenAddress);
}), }),
); );
const priceByAddress = await this._getPriceByAddressAsync(tokenAddresses);
for (let i = 0; i < tokenAddresses.length; i++) { for (let i = 0; i < tokenAddresses.length; i++) {
// Order is preserved in Promise.all // Order is preserved in Promise.all
const [balance, allowance] = balancesAndAllowances[i]; const [balance, allowance] = balancesAndAllowances[i];
@ -595,6 +600,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
balance, balance,
allowance, allowance,
isLoaded: true, isLoaded: true,
price: priceByAddress[tokenAddress],
}; };
} }
this.setState({ this.setState({
@ -602,6 +608,34 @@ export class Portal extends React.Component<PortalProps, PortalState> {
}); });
} }
private async _getPriceByAddressAsync(tokenAddresses: string[]): Promise<ItemByAddress<BigNumber>> {
if (_.isEmpty(tokenAddresses)) {
return {};
}
// for each input token address, search for the corresponding symbol in this.props.tokenByAddress, if it exists
// create a mapping from existing symbols -> address
const tokenAddressBySymbol: { [symbol: string]: string } = {};
_.each(tokenAddresses, address => {
const tokenIfExists = _.get(this.props.tokenByAddress, address);
if (!_.isUndefined(tokenIfExists)) {
const symbol = tokenIfExists.symbol;
tokenAddressBySymbol[symbol] = address;
}
});
const tokenSymbols = _.keys(tokenAddressBySymbol);
try {
const priceBySymbol = await backendClient.getPriceInfoAsync(tokenSymbols);
const priceByAddress = _.mapKeys(priceBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol));
const result = _.mapValues(priceByAddress, price => {
const priceBigNumber = new BigNumber(price);
return priceBigNumber;
});
return result;
} catch (err) {
return {};
}
}
private async _refetchTokenStateAsync(tokenAddress: string): Promise<void> { private async _refetchTokenStateAsync(tokenAddress: string): Promise<void> {
await this._fetchBalancesAndAllowancesAsync([tokenAddress]); await this._fetchBalancesAndAllowancesAsync([tokenAddress]);
} }

View File

@ -7,8 +7,8 @@ import { TopTokens } from 'ts/components/relayer_index/relayer_top_tokens';
import { Container } from 'ts/components/ui/container'; import { Container } from 'ts/components/ui/container';
import { Island } from 'ts/components/ui/island'; import { Island } from 'ts/components/ui/island';
import { TokenIcon } from 'ts/components/ui/token_icon'; import { TokenIcon } from 'ts/components/ui/token_icon';
import { colors } from 'ts/style/colors';
import { Token, WebsiteBackendRelayerInfo } from 'ts/types'; import { Token, WebsiteBackendRelayerInfo } from 'ts/types';
import { colors } from 'ts/utils/colors';
export interface RelayerGridTileProps { export interface RelayerGridTileProps {
relayerInfo: WebsiteBackendRelayerInfo; relayerInfo: WebsiteBackendRelayerInfo;

View File

@ -6,9 +6,9 @@ import { GridList } from 'material-ui/GridList';
import * as React from 'react'; import * as React from 'react';
import { RelayerGridTile } from 'ts/components/relayer_index/relayer_grid_tile'; import { RelayerGridTile } from 'ts/components/relayer_index/relayer_grid_tile';
import { colors } from 'ts/style/colors';
import { ScreenWidths, WebsiteBackendRelayerInfo } from 'ts/types'; import { ScreenWidths, WebsiteBackendRelayerInfo } from 'ts/types';
import { backendClient } from 'ts/utils/backend_client'; import { backendClient } from 'ts/utils/backend_client';
import { colors } from 'ts/utils/colors';
export interface RelayerIndexProps { export interface RelayerIndexProps {
networkId: number; networkId: number;

View File

@ -77,11 +77,11 @@ interface TokenBalancesProps {
interface TokenBalancesState { interface TokenBalancesState {
errorType: BalanceErrs; errorType: BalanceErrs;
trackedTokenStateByAddress: TokenStateByAddress;
isBalanceSpinnerVisible: boolean; isBalanceSpinnerVisible: boolean;
isZRXSpinnerVisible: boolean; isZRXSpinnerVisible: boolean;
isTokenPickerOpen: boolean; isTokenPickerOpen: boolean;
isAddingToken: boolean; isAddingToken: boolean;
trackedTokenStateByAddress: TokenStateByAddress;
} }
export class TokenBalances extends React.Component<TokenBalancesProps, TokenBalancesState> { export class TokenBalances extends React.Component<TokenBalancesProps, TokenBalancesState> {

View File

@ -9,10 +9,10 @@ import { ProviderPicker } from 'ts/components/top_bar/provider_picker';
import { DropDown } from 'ts/components/ui/drop_down'; import { DropDown } from 'ts/components/ui/drop_down';
import { Identicon } from 'ts/components/ui/identicon'; import { Identicon } from 'ts/components/ui/identicon';
import { Dispatcher } from 'ts/redux/dispatcher'; import { Dispatcher } from 'ts/redux/dispatcher';
import { colors } from 'ts/style/colors';
import { zIndex } from 'ts/style/z_index';
import { ProviderType } from 'ts/types'; import { ProviderType } from 'ts/types';
import { colors } from 'ts/utils/colors';
import { constants } from 'ts/utils/constants'; import { constants } from 'ts/utils/constants';
import { zIndex } from 'ts/utils/style';
import { utils } from 'ts/utils/utils'; import { utils } from 'ts/utils/utils';
const ROOT_HEIGHT = 24; const ROOT_HEIGHT = 24;

View File

@ -16,9 +16,9 @@ import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item';
import { DropDown } from 'ts/components/ui/drop_down'; import { DropDown } from 'ts/components/ui/drop_down';
import { Identicon } from 'ts/components/ui/identicon'; import { Identicon } from 'ts/components/ui/identicon';
import { Dispatcher } from 'ts/redux/dispatcher'; import { Dispatcher } from 'ts/redux/dispatcher';
import { zIndex } from 'ts/style/z_index';
import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types'; import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants'; import { constants } from 'ts/utils/constants';
import { zIndex } from 'ts/utils/style';
import { Translate } from 'ts/utils/translate'; import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils'; import { utils } from 'ts/utils/utils';

View File

@ -0,0 +1,79 @@
import { colors } from '@0xproject/react-shared';
import { darken } from 'polished';
import * as React from 'react';
import { styled } from 'ts/style/theme';
export interface ButtonProps {
className?: string;
fontSize?: string;
fontColor?: string;
backgroundColor?: string;
borderColor?: string;
width?: string;
type?: string;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
}
const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, onClick, type, className }) => (
<button type={type} className={className} onClick={onClick}>
{children}
</button>
);
export const Button = styled(PlainButton)`
cursor: pointer;
font-size: ${props => props.fontSize};
color: ${props => props.fontColor};
padding: 0.8em 2.2em;
border-radius: 6px;
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.25);
font-weight: 500;
font-family: 'Roboto';
width: ${props => props.width};
background-color: ${props => props.backgroundColor};
border: ${props => (props.borderColor ? `1px solid ${props.borderColor}` : 'none')};
&:hover {
background-color: ${props => darken(0.1, props.backgroundColor)};
}
&:active {
background-color: ${props => darken(0.2, props.backgroundColor)};
}
`;
Button.defaultProps = {
fontSize: '12px',
backgroundColor: colors.white,
width: 'auto',
};
Button.displayName = 'Button';
type CallToActionType = 'light' | 'dark';
export interface CallToActionProps {
type?: CallToActionType;
fontSize?: string;
width?: string;
}
export const CallToAction: React.StatelessComponent<CallToActionProps> = ({ children, type, fontSize, width }) => {
const isLight = type === 'light';
const backgroundColor = isLight ? colors.white : colors.heroGrey;
const fontColor = isLight ? colors.heroGrey : colors.white;
const borderColor = isLight ? undefined : colors.white;
return (
<Button
fontSize={fontSize}
backgroundColor={backgroundColor}
fontColor={fontColor}
width={width}
borderColor={borderColor}
>
{children}
</Button>
);
};
CallToAction.defaultProps = {
type: 'dark',
};

View File

@ -11,13 +11,20 @@ export interface ContainerProps {
paddingBottom?: StringOrNum; paddingBottom?: StringOrNum;
paddingRight?: StringOrNum; paddingRight?: StringOrNum;
paddingLeft?: StringOrNum; paddingLeft?: StringOrNum;
backgroundColor?: string;
borderRadius?: StringOrNum;
maxWidth?: StringOrNum; maxWidth?: StringOrNum;
children?: React.ReactNode; isHidden?: boolean;
className?: string;
} }
export const Container: React.StatelessComponent<ContainerProps> = (props: ContainerProps) => { export const Container: React.StatelessComponent<ContainerProps> = ({ children, className, isHidden, ...style }) => {
const { children, ...style } = props; const visibility = isHidden ? 'hidden' : undefined;
return <div style={style}>{children}</div>; return (
<div style={{ ...style, visibility }} className={className}>
{children}
</div>
);
}; };
Container.displayName = 'Container'; Container.displayName = 'Container';

View File

@ -0,0 +1,43 @@
import { colors } from '@0xproject/react-shared';
import * as React from 'react';
import { styled } from 'ts/style/theme';
export interface InputProps {
className?: string;
value?: string;
width?: string;
fontSize?: string;
fontColor?: string;
placeholderColor?: string;
placeholder?: string;
backgroundColor?: string;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}
const PlainInput: React.StatelessComponent<InputProps> = ({ value, className, placeholder, onChange }) => (
<input className={className} value={value} onChange={onChange} placeholder={placeholder} />
);
export const Input = styled(PlainInput)`
font-size: ${props => props.fontSize};
width: ${props => props.width};
padding: 0.8em 1.2em;
border-radius: 3px;
font-family: 'Roboto Mono';
color: ${props => props.fontColor};
border: none;
background-color: ${props => props.backgroundColor};
&::placeholder {
color: ${props => props.placeholderColor};
}
`;
Input.defaultProps = {
width: 'auto',
backgroundColor: colors.white,
fontColor: colors.darkestGrey,
placeholderColor: colors.darkGrey,
fontSize: '12px',
};
Input.displayName = 'Input';

View File

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { colors } from 'ts/style/colors';
import { Styleable } from 'ts/types'; import { Styleable } from 'ts/types';
import { colors } from 'ts/utils/colors';
export interface IslandProps { export interface IslandProps {
style?: React.CSSProperties; style?: React.CSSProperties;

View File

@ -2,7 +2,7 @@ import { colors } from '@0xproject/react-shared';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as React from 'react'; import * as React from 'react';
import { zIndex } from 'ts/utils/style'; import { zIndex } from 'ts/style/z_index';
export interface OverlayProps { export interface OverlayProps {
children?: React.ReactNode; children?: React.ReactNode;

View File

@ -0,0 +1,41 @@
import { colors } from '@0xproject/react-shared';
import * as React from 'react';
import { styled } from 'ts/style/theme';
import { Deco, Key } from 'ts/types';
import { Translate } from 'ts/utils/translate';
export type TextTag = 'p' | 'div' | 'span' | 'label';
export interface TextProps {
className?: string;
Tag?: TextTag;
fontSize?: string;
fontFamily?: string;
fontColor?: string;
lineHeight?: string;
center?: boolean;
fontWeight?: number;
}
const PlainText: React.StatelessComponent<TextProps> = ({ children, className, Tag }) => (
<Tag className={className}>{children}</Tag>
);
export const Text = styled(PlainText)`
font-family: ${props => props.fontFamily};
font-weight: ${props => props.fontWeight};
font-size: ${props => props.fontSize};
${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
${props => (props.center ? 'text-align: center' : '')};
color: ${props => props.fontColor};
`;
Text.defaultProps = {
fontFamily: 'Roboto',
fontWeight: 400,
fontColor: colors.white,
fontSize: '14px',
Tag: 'div',
};
Text.displayName = 'Text';

View File

@ -32,10 +32,11 @@ import { TokenIcon } from 'ts/components/ui/token_icon';
import { WalletDisconnectedItem } from 'ts/components/wallet/wallet_disconnected_item'; import { WalletDisconnectedItem } from 'ts/components/wallet/wallet_disconnected_item';
import { WrapEtherItem } from 'ts/components/wallet/wrap_ether_item'; import { WrapEtherItem } from 'ts/components/wallet/wrap_ether_item';
import { Dispatcher } from 'ts/redux/dispatcher'; import { Dispatcher } from 'ts/redux/dispatcher';
import { colors } from 'ts/style/colors';
import { zIndex } from 'ts/style/z_index';
import { import {
BalanceErrs, BalanceErrs,
BlockchainErrs, BlockchainErrs,
ItemByAddress,
ProviderType, ProviderType,
ScreenWidths, ScreenWidths,
Side, Side,
@ -45,10 +46,7 @@ import {
TokenStateByAddress, TokenStateByAddress,
WebsitePaths, WebsitePaths,
} from 'ts/types'; } from 'ts/types';
import { backendClient } from 'ts/utils/backend_client';
import { colors } from 'ts/utils/colors';
import { constants } from 'ts/utils/constants'; import { constants } from 'ts/utils/constants';
import { zIndex } from 'ts/utils/style';
import { utils } from 'ts/utils/utils'; import { utils } from 'ts/utils/utils';
import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles'; import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles';
@ -523,34 +521,6 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
}); });
return trackedTokenStateByAddress; return trackedTokenStateByAddress;
} }
private async _getPriceByAddressAsync(tokenAddresses: string[]): Promise<ItemByAddress<BigNumber>> {
if (_.isEmpty(tokenAddresses)) {
return {};
}
// for each input token address, search for the corresponding symbol in this.props.tokenByAddress, if it exists
// create a mapping from existing symbols -> address
const tokenAddressBySymbol: { [symbol: string]: string } = {};
_.each(tokenAddresses, address => {
const tokenIfExists = _.get(this.props.tokenByAddress, address);
if (!_.isUndefined(tokenIfExists)) {
const symbol = tokenIfExists.symbol;
tokenAddressBySymbol[symbol] = address;
}
});
const tokenSymbols = _.keys(tokenAddressBySymbol);
try {
const priceBySymbol = await backendClient.getPriceInfoAsync(tokenSymbols);
const priceByAddress = _.mapKeys(priceBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol));
const result = _.mapValues(priceByAddress, price => {
const priceBigNumber = new BigNumber(price);
return priceBigNumber;
});
return result;
} catch (err) {
return {};
}
}
private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void { private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void {
this.setState({ this.setState({
wrappedEtherDirection, wrappedEtherDirection,

View File

@ -3,8 +3,8 @@ import FlatButton from 'material-ui/FlatButton';
import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet'; import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
import * as React from 'react'; import * as React from 'react';
import { colors } from 'ts/style/colors';
import { ProviderType } from 'ts/types'; import { ProviderType } from 'ts/types';
import { colors } from 'ts/utils/colors';
import { constants } from 'ts/utils/constants'; import { constants } from 'ts/utils/constants';
import { utils } from 'ts/utils/utils'; import { utils } from 'ts/utils/utils';

View File

@ -10,8 +10,8 @@ import { Blockchain } from 'ts/blockchain';
import { EthAmountInput } from 'ts/components/inputs/eth_amount_input'; import { EthAmountInput } from 'ts/components/inputs/eth_amount_input';
import { TokenAmountInput } from 'ts/components/inputs/token_amount_input'; import { TokenAmountInput } from 'ts/components/inputs/token_amount_input';
import { Dispatcher } from 'ts/redux/dispatcher'; import { Dispatcher } from 'ts/redux/dispatcher';
import { colors } from 'ts/style/colors';
import { BlockchainCallErrs, Side, Token } from 'ts/types'; import { BlockchainCallErrs, Side, Token } from 'ts/types';
import { colors } from 'ts/utils/colors';
import { constants } from 'ts/utils/constants'; import { constants } from 'ts/utils/constants';
import { errorReporter } from 'ts/utils/error_reporter'; import { errorReporter } from 'ts/utils/error_reporter';
import { utils } from 'ts/utils/utils'; import { utils } from 'ts/utils/utils';

View File

@ -1,11 +1,13 @@
import { colors } from '@0xproject/react-shared'; import { colors } from '@0xproject/react-shared';
import * as _ from 'lodash'; import * as _ from 'lodash';
import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react'; import * as React from 'react';
import DocumentTitle = require('react-document-title'); import DocumentTitle = require('react-document-title');
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Footer } from 'ts/components/footer'; import { Footer } from 'ts/components/footer';
import { SubscribeForm } from 'ts/components/forms/subscribe_form';
import { TopBar } from 'ts/components/top_bar/top_bar'; import { TopBar } from 'ts/components/top_bar/top_bar';
import { CallToAction } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Dispatcher } from 'ts/redux/dispatcher'; import { Dispatcher } from 'ts/redux/dispatcher';
import { Deco, Key, Language, ScreenWidths, WebsitePaths } from 'ts/types'; import { Deco, Key, Language, ScreenWidths, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants'; import { constants } from 'ts/utils/constants';
@ -236,7 +238,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
<div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}> <div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}>
<div className="mx-auto max-width-4 clearfix"> <div className="mx-auto max-width-4 clearfix">
{this._renderWhatsNew()} {this._renderWhatsNew()}
<div className="lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-my4 md-my4 sm-mt2 sm-mb4 clearfix"> <div className="lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-mt4 md-mt4 sm-mt2 sm-mb4 clearfix">
<div className="col lg-col-5 md-col-5 col-12 sm-center"> <div className="col lg-col-5 md-col-5 col-12 sm-center">
<img src="/images/landing/hero_chip_image.png" height={isSmallScreen ? 300 : 395} /> <img src="/images/landing/hero_chip_image.png" height={isSmallScreen ? 300 : 395} />
</div> </div>
@ -268,40 +270,31 @@ export class Landing extends React.Component<LandingProps, LandingState> {
> >
{this.props.translate.get(Key.TopTagline)} {this.props.translate.get(Key.TopTagline)}
</div> </div>
<div className="pt3 clearfix sm-mx-auto" style={{ maxWidth: 389 }}> <Container className="pt3 clearfix sm-mx-auto" maxWidth="390px">
<div className="lg-pr2 md-pr2 col col-6 sm-center"> <div className="lg-pr2 md-pr2 lg-col lg-col-6 sm-center sm-col sm-col-12 mb2">
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none"> <Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
<RaisedButton <CallToAction width="175px" type="light">
style={{ borderRadius: 6, minWidth: 157.36 }} {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
buttonStyle={{ borderRadius: 6 }} </CallToAction>
labelStyle={buttonLabelStyle}
label={this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
onClick={_.noop}
/>
</Link> </Link>
</div> </div>
<div className="col col-6 sm-center"> <div className="lg-col lg-col-6 sm-center sm-col sm-col-12">
<a <a
href={constants.URL_ZEROEX_CHAT} href={constants.URL_ZEROEX_CHAT}
target="_blank" target="_blank"
className="text-decoration-none" className="text-decoration-none"
> >
<RaisedButton <CallToAction width="175px">
style={{ borderRadius: 6, minWidth: 150 }} {this.props.translate.get(Key.CommunityCallToAction, Deco.Cap)}
buttonStyle={lightButtonStyle} </CallToAction>
labelColor="white"
backgroundColor={colors.heroGrey}
labelStyle={buttonLabelStyle}
label={this.props.translate.get(Key.CommunityCallToAction, Deco.Cap)}
onClick={_.noop}
/>
</a> </a>
</div> </div>
</div> </Container>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{this.props.translate.getLanguage() === Language.English && <SubscribeForm />}
</div> </div>
); );
} }
@ -349,6 +342,9 @@ export class Landing extends React.Component<LandingProps, LandingState> {
case ScreenWidths.Lg: case ScreenWidths.Lg:
colWidth = isRelayersOnly ? 2 : 2 - i % 2; colWidth = isRelayersOnly ? 2 : 2 - i % 2;
break; break;
default:
throw new Error(`Encountered unknown ScreenWidths value: ${this.state.screenWidth}`);
} }
return ( return (
<div key={`project-${project.logoFileName}`} className={`col col-${colWidth} center`}> <div key={`project-${project.logoFileName}`} className={`col col-${colWidth} center`}>
@ -782,15 +778,9 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div> </div>
<div className="sm-center sm-pt2 lg-table-cell md-table-cell"> <div className="sm-center sm-pt2 lg-table-cell md-table-cell">
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none"> <Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
<RaisedButton <CallToAction fontSize="15px">
style={{ borderRadius: 6, minWidth: 150 }} {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
buttonStyle={lightButtonStyle} </CallToAction>
labelColor={colors.white}
backgroundColor={colors.heroGrey}
labelStyle={buttonLabelStyle}
label={this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
onClick={_.noop}
/>
</Link> </Link>
</div> </div>
</div> </div>

View File

@ -0,0 +1,15 @@
import * as styledComponents from 'styled-components';
const {
default: styled,
css,
injectGlobal,
keyframes,
ThemeProvider,
} = styledComponents as styledComponents.ThemedStyledComponentsModule<IThemeInterface>;
export interface IThemeInterface {}
export const theme = {};
export { styled, css, injectGlobal, keyframes, ThemeProvider };

View File

@ -8,6 +8,7 @@ const ETH_GAS_STATION_ENDPOINT = '/eth_gas_station';
const PRICES_ENDPOINT = '/prices'; const PRICES_ENDPOINT = '/prices';
const RELAYERS_ENDPOINT = '/relayers'; const RELAYERS_ENDPOINT = '/relayers';
const WIKI_ENDPOINT = '/wiki'; const WIKI_ENDPOINT = '/wiki';
const SUBSCRIBE_SUBSTACK_NEWSLETTER_ENDPOINT = '/newsletter_subscriber/substack';
export const backendClient = { export const backendClient = {
async getGasInfoAsync(): Promise<WebsiteBackendGasInfo> { async getGasInfoAsync(): Promise<WebsiteBackendGasInfo> {
@ -33,4 +34,11 @@ export const backendClient = {
const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), WIKI_ENDPOINT); const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), WIKI_ENDPOINT);
return result; return result;
}, },
async subscribeToNewsletterAsync(email: string): Promise<Response> {
const result = await fetchUtils.postAsync(utils.getBackendBaseUrl(), SUBSCRIBE_SUBSTACK_NEWSLETTER_ENDPOINT, {
email,
referrer: window.location.href,
});
return result;
},
}; };

View File

@ -4,22 +4,38 @@ import * as queryString from 'query-string';
import { errorReporter } from 'ts/utils/error_reporter'; import { errorReporter } from 'ts/utils/error_reporter';
const logErrorIfPresent = (response: Response, requestedURL: string) => {
if (response.status !== 200) {
const errorText = `Error requesting url: ${requestedURL}, ${response.status}: ${response.statusText}`;
logUtils.log(errorText);
const error = Error(errorText);
// tslint:disable-next-line:no-floating-promises
errorReporter.reportAsync(error);
throw error;
}
};
export const fetchUtils = { export const fetchUtils = {
async requestAsync(baseUrl: string, path: string, queryParams?: object): Promise<any> { async requestAsync(baseUrl: string, path: string, queryParams?: object): Promise<any> {
const query = queryStringFromQueryParams(queryParams); const query = queryStringFromQueryParams(queryParams);
const url = `${baseUrl}${path}${query}`; const url = `${baseUrl}${path}${query}`;
const response = await fetch(url); const response = await fetch(url);
if (response.status !== 200) { logErrorIfPresent(response, url);
const errorText = `Error requesting url: ${url}, ${response.status}: ${response.statusText}`;
logUtils.log(errorText);
const error = Error(errorText);
// tslint:disable-next-line:no-floating-promises
errorReporter.reportAsync(error);
throw error;
}
const result = await response.json(); const result = await response.json();
return result; return result;
}, },
async postAsync(baseUrl: string, path: string, body: object): Promise<Response> {
const url = `${baseUrl}${path}`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
logErrorIfPresent(response, url);
return response;
},
}; };
function queryStringFromQueryParams(queryParams?: object): string { function queryStringFromQueryParams(queryParams?: object): string {

View File

@ -1,6 +1,6 @@
import { Styles } from '@0xproject/react-shared'; import { Styles } from '@0xproject/react-shared';
import { colors } from 'ts/utils/colors'; import { colors } from 'ts/style/colors';
export const styles: Styles = { export const styles: Styles = {
focusedItem: { focusedItem: {

View File

@ -2044,7 +2044,7 @@ buffer@^4.3.0:
ieee754 "^1.1.4" ieee754 "^1.1.4"
isarray "^1.0.0" isarray "^1.0.0"
buffer@^5.0.5: buffer@^5.0.3, buffer@^5.0.5:
version "5.1.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.1.0.tgz#c913e43678c7cb7c8bd16afbcddb6c5505e8f9fe" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.1.0.tgz#c913e43678c7cb7c8bd16afbcddb6c5505e8f9fe"
dependencies: dependencies:
@ -3061,6 +3061,10 @@ crypto-random-string@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
css-color-keywords@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
css-color-names@0.0.4: css-color-names@0.0.4:
version "0.0.4" version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
@ -3122,6 +3126,14 @@ css-selector-tokenizer@^0.7.0:
fastparse "^1.1.1" fastparse "^1.1.1"
regexpu-core "^1.0.0" regexpu-core "^1.0.0"
css-to-react-native@^2.0.3:
version "2.2.0"
resolved "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.2.0.tgz#d524ef7f39a2747a8914e86563669ba35b7cf2e7"
dependencies:
css-color-keywords "^1.0.0"
fbjs "^0.8.5"
postcss-value-parser "^3.3.0"
cssesc@^0.1.0: cssesc@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
@ -4491,7 +4503,7 @@ faye-websocket@~0.11.0:
dependencies: dependencies:
websocket-driver ">=0.5.1" websocket-driver ">=0.5.1"
fbjs@^0.8.0, fbjs@^0.8.1, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.6, fbjs@^0.8.9: fbjs@^0.8.0, fbjs@^0.8.1, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.5, fbjs@^0.8.6, fbjs@^0.8.9:
version "0.8.16" version "0.8.16"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db"
dependencies: dependencies:
@ -8721,6 +8733,10 @@ plur@^2.1.2:
dependencies: dependencies:
irregular-plurals "^1.0.0" irregular-plurals "^1.0.0"
polished@^1.9.2:
version "1.9.2"
resolved "https://registry.npmjs.org/polished/-/polished-1.9.2.tgz#d705cac66f3a3ed1bd38aad863e2c1e269baf6b6"
popper.js@^1.14.1: popper.js@^1.14.1:
version "1.14.3" version "1.14.3"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095"
@ -9557,6 +9573,10 @@ react-highlight@0xproject/react-highlight:
react "^15.5.4" react "^15.5.4"
react-dom "^15.5.4" react-dom "^15.5.4"
react-is@^16.3.1:
version "16.4.0"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.4.0.tgz#cc9fdc855ac34d2e7d9d2eb7059bbc240d35ffcf"
react-markdown@^3.2.2: react-markdown@^3.2.2:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-3.3.0.tgz#a87cdd822aa9302d6add9687961dd1a82a45d02e" resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-3.3.0.tgz#a87cdd822aa9302d6add9687961dd1a82a45d02e"
@ -11188,6 +11208,29 @@ style-loader@^0.20.2:
loader-utils "^1.1.0" loader-utils "^1.1.0"
schema-utils "^0.4.5" schema-utils "^0.4.5"
styled-components@^3.3.0:
version "3.3.0"
resolved "https://registry.npmjs.org/styled-components/-/styled-components-3.3.0.tgz#335b1b2b673b416cd5ec012010e237ed1f877fe9"
dependencies:
buffer "^5.0.3"
css-to-react-native "^2.0.3"
fbjs "^0.8.16"
hoist-non-react-statics "^2.5.0"
is-plain-object "^2.0.1"
prop-types "^15.5.4"
react-is "^16.3.1"
stylis "^3.5.0"
stylis-rule-sheet "^0.0.10"
supports-color "^3.2.3"
stylis-rule-sheet@^0.0.10:
version "0.0.10"
resolved "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430"
stylis@^3.5.0:
version "3.5.0"
resolved "https://registry.npmjs.org/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1"
supports-color@3.1.2: supports-color@3.1.2:
version "3.1.2" version "3.1.2"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"