aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website
diff options
context:
space:
mode:
Diffstat (limited to 'packages/website')
-rw-r--r--packages/website/CHANGELOG.md5
-rw-r--r--packages/website/README.md62
-rw-r--r--packages/website/contracts/Mintable.json343
-rw-r--r--packages/website/md/docs/0xjs/async.md9
-rw-r--r--packages/website/md/docs/0xjs/installation.md4
-rw-r--r--packages/website/md/docs/connect/installation.md2
-rw-r--r--packages/website/md/docs/smart_contracts/introduction.md8
-rw-r--r--packages/website/package.json209
-rw-r--r--packages/website/public/images/ether.pngbin2312 -> 4235 bytes
-rw-r--r--packages/website/public/images/social/discourse.pngbin0 -> 1454 bytes
-rw-r--r--packages/website/public/images/team/jacob.jpgbin0 -> 1177087 bytes
-rw-r--r--packages/website/public/images/team/tom.jpgbin0 -> 41810 bytes
-rw-r--r--packages/website/public/images/token_icons/augur.pngbin146258 -> 23161 bytes
-rw-r--r--packages/website/public/images/token_icons/default.pngbin17037 -> 20225 bytes
-rw-r--r--packages/website/public/images/token_icons/district0x.pngbin67267 -> 25007 bytes
-rw-r--r--packages/website/public/images/token_icons/ether_erc20.pngbin69772 -> 7584 bytes
-rw-r--r--packages/website/public/images/token_icons/firstblood.jpgbin72909 -> 7872 bytes
-rw-r--r--packages/website/public/images/token_icons/qtum.pngbin169182 -> 32496 bytes
-rw-r--r--packages/website/public/images/token_icons/zero_ex.pngbin162879 -> 17905 bytes
-rw-r--r--packages/website/public/images/wrapped_eth_gray.pngbin0 -> 7649 bytes
-rw-r--r--packages/website/ts/blockchain.ts656
-rw-r--r--packages/website/ts/components/dialogs/blockchain_err_dialog.tsx133
-rw-r--r--packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx172
-rw-r--r--packages/website/ts/components/dialogs/ledger_config_dialog.tsx142
-rw-r--r--packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx35
-rw-r--r--packages/website/ts/components/dialogs/send_dialog.tsx51
-rw-r--r--packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx37
-rw-r--r--packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx26
-rw-r--r--packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx33
-rw-r--r--packages/website/ts/components/eth_weth_conversion_button.tsx90
-rw-r--r--packages/website/ts/components/eth_wrappers.tsx374
-rw-r--r--packages/website/ts/components/fill_order.tsx330
-rw-r--r--packages/website/ts/components/fill_order_json.tsx43
-rw-r--r--packages/website/ts/components/fill_warning_dialog.tsx18
-rw-r--r--packages/website/ts/components/flash_messages/token_send_completed.tsx24
-rw-r--r--packages/website/ts/components/flash_messages/transaction_submitted.tsx7
-rw-r--r--packages/website/ts/components/footer.tsx169
-rw-r--r--packages/website/ts/components/generate_order/asset_picker.tsx147
-rw-r--r--packages/website/ts/components/generate_order/generate_order_form.tsx159
-rw-r--r--packages/website/ts/components/generate_order/new_token_form.tsx92
-rw-r--r--packages/website/ts/components/inputs/address_input.tsx27
-rw-r--r--packages/website/ts/components/inputs/allowance_toggle.tsx35
-rw-r--r--packages/website/ts/components/inputs/balance_bounded_input.tsx85
-rw-r--r--packages/website/ts/components/inputs/eth_amount_input.tsx32
-rw-r--r--packages/website/ts/components/inputs/expiration_input.tsx46
-rw-r--r--packages/website/ts/components/inputs/hash_input.tsx20
-rw-r--r--packages/website/ts/components/inputs/identicon_address_input.tsx23
-rw-r--r--packages/website/ts/components/inputs/token_amount_input.tsx43
-rw-r--r--packages/website/ts/components/inputs/token_input.tsx39
-rw-r--r--packages/website/ts/components/order_json.tsx143
-rw-r--r--packages/website/ts/components/portal.tsx281
-rw-r--r--packages/website/ts/components/portal_menu.tsx31
-rw-r--r--packages/website/ts/components/send_button.tsx36
-rw-r--r--packages/website/ts/components/token_balances.tsx436
-rw-r--r--packages/website/ts/components/top_bar.tsx242
-rw-r--r--packages/website/ts/components/top_bar_menu_item.tsx33
-rw-r--r--packages/website/ts/components/track_token_confirmation.tsx34
-rw-r--r--packages/website/ts/components/trade_history/trade_history.tsx44
-rw-r--r--packages/website/ts/components/trade_history/trade_history_item.tsx81
-rw-r--r--packages/website/ts/components/ui/alert.tsx12
-rw-r--r--packages/website/ts/components/ui/badge.tsx9
-rw-r--r--packages/website/ts/components/ui/copy_icon.tsx68
-rw-r--r--packages/website/ts/components/ui/drop_down_menu_item.tsx71
-rw-r--r--packages/website/ts/components/ui/ethereum_address.tsx15
-rw-r--r--packages/website/ts/components/ui/etherscan_icon.tsx35
-rw-r--r--packages/website/ts/components/ui/fake_text_field.tsx7
-rw-r--r--packages/website/ts/components/ui/flash_message.tsx8
-rw-r--r--packages/website/ts/components/ui/help_tooltip.tsx4
-rw-r--r--packages/website/ts/components/ui/identicon.tsx18
-rw-r--r--packages/website/ts/components/ui/input_label.tsx8
-rw-r--r--packages/website/ts/components/ui/labeled_switcher.tsx73
-rw-r--r--packages/website/ts/components/ui/lifecycle_raised_button.tsx38
-rw-r--r--packages/website/ts/components/ui/loading.tsx21
-rw-r--r--packages/website/ts/components/ui/menu_item.tsx13
-rw-r--r--packages/website/ts/components/ui/party.tsx131
-rw-r--r--packages/website/ts/components/ui/required_label.tsx6
-rw-r--r--packages/website/ts/components/ui/simple_loading.tsx12
-rw-r--r--packages/website/ts/components/ui/swap_icon.tsx16
-rw-r--r--packages/website/ts/components/ui/token_icon.tsx14
-rw-r--r--packages/website/ts/components/visual_order.tsx19
-rw-r--r--packages/website/ts/containers/connect_documentation.tsx54
-rw-r--r--packages/website/ts/containers/generate_order_form.tsx18
-rw-r--r--packages/website/ts/containers/portal.tsx65
-rw-r--r--packages/website/ts/containers/smart_contracts_documentation.tsx57
-rw-r--r--packages/website/ts/containers/zero_ex_js_documentation.tsx61
-rw-r--r--packages/website/ts/globals.d.ts31
-rw-r--r--packages/website/ts/index.tsx106
-rw-r--r--packages/website/ts/lazy_component.tsx19
-rw-r--r--packages/website/ts/local_storage/tracked_token_storage.ts27
-rw-r--r--packages/website/ts/local_storage/trade_history_storage.tsx24
-rw-r--r--packages/website/ts/pages/about/about.tsx163
-rw-r--r--packages/website/ts/pages/about/profile.tsx56
-rw-r--r--packages/website/ts/pages/documentation/comment.tsx9
-rw-r--r--packages/website/ts/pages/documentation/custom_enum.tsx9
-rw-r--r--packages/website/ts/pages/documentation/docs_info.ts31
-rw-r--r--packages/website/ts/pages/documentation/documentation.tsx288
-rw-r--r--packages/website/ts/pages/documentation/enum.tsx10
-rw-r--r--packages/website/ts/pages/documentation/event_definition.tsx50
-rw-r--r--packages/website/ts/pages/documentation/interface.tsx32
-rw-r--r--packages/website/ts/pages/documentation/method_block.tsx128
-rw-r--r--packages/website/ts/pages/documentation/method_signature.tsx58
-rw-r--r--packages/website/ts/pages/documentation/source_link.tsx18
-rw-r--r--packages/website/ts/pages/documentation/type.tsx134
-rw-r--r--packages/website/ts/pages/documentation/type_definition.tsx82
-rw-r--r--packages/website/ts/pages/faq/faq.tsx384
-rw-r--r--packages/website/ts/pages/faq/question.tsx21
-rw-r--r--packages/website/ts/pages/landing/landing.tsx574
-rw-r--r--packages/website/ts/pages/not_found.tsx16
-rw-r--r--packages/website/ts/pages/shared/anchor_title.tsx27
-rw-r--r--packages/website/ts/pages/shared/markdown_code_block.tsx25
-rw-r--r--packages/website/ts/pages/shared/markdown_section.tsx29
-rw-r--r--packages/website/ts/pages/shared/nested_sidebar_menu.tsx127
-rw-r--r--packages/website/ts/pages/shared/section_header.tsx16
-rw-r--r--packages/website/ts/pages/shared/version_drop_down.tsx20
-rw-r--r--packages/website/ts/pages/wiki/wiki.tsx126
-rw-r--r--packages/website/ts/redux/dispatcher.ts194
-rw-r--r--packages/website/ts/redux/reducer.ts302
-rw-r--r--packages/website/ts/schemas/order_schema.ts27
-rw-r--r--packages/website/ts/schemas/order_taker_schema.ts8
-rw-r--r--packages/website/ts/schemas/signature_data_schema.ts8
-rw-r--r--packages/website/ts/schemas/token_schema.ts8
-rw-r--r--packages/website/ts/schemas/validator.ts24
-rw-r--r--packages/website/ts/types.ts255
-rw-r--r--packages/website/ts/utils/colors.ts43
-rw-r--r--packages/website/ts/utils/configs.ts128
-rw-r--r--packages/website/ts/utils/constants.ts240
-rw-r--r--packages/website/ts/utils/doc_utils.ts20
-rw-r--r--packages/website/ts/utils/doxity_utils.ts74
-rw-r--r--packages/website/ts/utils/error_reporter.ts12
-rw-r--r--packages/website/ts/utils/mui_theme.ts35
-rw-r--r--packages/website/ts/utils/typedoc_utils.ts212
-rw-r--r--packages/website/ts/utils/utils.ts110
-rw-r--r--packages/website/ts/web3_wrapper.ts163
-rw-r--r--packages/website/tsconfig.json16
-rw-r--r--packages/website/tslint.json16
135 files changed, 5195 insertions, 5284 deletions
diff --git a/packages/website/CHANGELOG.md b/packages/website/CHANGELOG.md
new file mode 100644
index 000000000..6cb8cd0b0
--- /dev/null
+++ b/packages/website/CHANGELOG.md
@@ -0,0 +1,5 @@
+# CHANGELOG
+
+## v0.x.x - _TBD_
+
+ * Added new team members to the about page (#317)
diff --git a/packages/website/README.md b/packages/website/README.md
index 128477372..7d3187781 100644
--- a/packages/website/README.md
+++ b/packages/website/README.md
@@ -1,8 +1,4 @@
-<img src="https://github.com/0xProject/branding/blob/master/0x_Black_CMYK.png" width="200px" >
-
----
-
-[0x][website-url] is an open protocol that facilitates trustless, low friction exchange of Ethereum-based assets. A full description of the protocol may be found in our [whitepaper][whitepaper-url].
+## Website & 0x Portal DApp
This repository contains our website and [0x Portal DApp][portal-url] (over-the-counter exchange), facilitating trustless over-the-counter trading of Ethereum-based tokens using 0x protocol.
@@ -10,10 +6,13 @@ This repository contains our website and [0x Portal DApp][portal-url] (over-the-
[whitepaper-url]: https://0xproject.com/pdfs/0x_white_paper.pdf
[portal-url]: https://0xproject.com/portal
-[![Join the chat at https://gitter.im/0xProject/contracts](https://badges.gitter.im/0xProject/contracts.svg)](https://gitter.im/0xProject/contracts?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+## Contributing
+
+We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository.
-### Local Dev Setup
+Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
+
+## Local Dev Setup
Requires Node version 6.9.5 or higher.
@@ -23,38 +22,47 @@ Add the following to your `/etc/hosts` file:
127.0.0.1 0xproject.localhost
```
-Clone the [0x contracts repo](https://github.com/0xProject/contracts) into the same parent directory as this project.
+### Install dependencies:
-Install [yarn](https://yarnpkg.com/lang/en/docs/install/) in order to install the project dependencies more deterministically.
+```bash
+yarn install
+```
-Install dependencies:
+### Run dev server
-```
-yarn
+```bash
+yarn run dev
```
-Import smart contract artifacts from `contracts` repo:
+Visit [0xproject.localhost:3572](http://0xproject.localhost:3572) in your browser.
-```
-yarn run update_contracts
+### Build
+
+```bash
+yarn build
```
-Start dev server:
+### Clean
-```
-yarn run dev
+```bash
+yarn clean
```
-Visit [0xproject.localhost:3572](http://0xproject.localhost:3572) in your browser.
+### Lint
+```bash
+yarn lint
+```
-##### Recommended Atom packages:
+### Resources
-- [atom-typescript](https://atom.io/packages/atom-typescript)
-- [linter-tslint](https://atom.io/packages/linter-tslint)
+##### Toolkit
-##### Resources
+* [Material Design Icon Font](http://zavoloklom.github.io/material-design-iconic-font/icons.html#directional)
+* [BassCSS toolkit](http://basscss.com/)
+* [Material-UI component library](http://www.material-ui.com/#/)
+
+##### Recommended Atom packages:
-- [Material Design Icon Font](http://zavoloklom.github.io/material-design-iconic-font/icons.html#directional)
-- [BassCSS toolkit](http://basscss.com/)
-- [Material-UI](http://www.material-ui.com/#/)
+* [atom-typescript](https://atom.io/packages/atom-typescript)
+* [linter-tslint](https://atom.io/packages/linter-tslint)
diff --git a/packages/website/contracts/Mintable.json b/packages/website/contracts/Mintable.json
index 52dc7507f..dc46dc829 100644
--- a/packages/website/contracts/Mintable.json
+++ b/packages/website/contracts/Mintable.json
@@ -1,189 +1,190 @@
{
- "contract_name": "Mintable",
- "abi": [
- {
- "constant": false,
- "inputs": [
- {
- "name": "_spender",
- "type": "address"
+ "contract_name": "Mintable",
+ "abi": [
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_spender",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
},
{
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "approve",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "totalSupply",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_from",
- "type": "address"
+ "constant": true,
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
},
{
- "name": "_to",
- "type": "address"
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
},
{
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transferFrom",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "mint",
- "outputs": [],
- "payable": false,
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "_to",
- "type": "address"
- },
- {
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "transfer",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "name": "_owner",
- "type": "address"
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
},
{
- "name": "_spender",
- "type": "address"
- }
- ],
- "name": "allowance",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "type": "function"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_from",
- "type": "address"
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "mint",
+ "outputs": [],
+ "payable": false,
+ "type": "function"
},
{
- "indexed": true,
- "name": "_to",
- "type": "address"
+ "constant": false,
+ "inputs": [
+ {
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "type": "function"
},
{
- "indexed": false,
- "name": "_value",
- "type": "uint256"
- }
- ],
- "name": "Transfer",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "name": "_owner",
- "type": "address"
+ "constant": true,
+ "inputs": [
+ {
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "name": "_spender",
+ "type": "address"
+ }
+ ],
+ "name": "allowance",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "type": "function"
},
{
- "indexed": true,
- "name": "_spender",
- "type": "address"
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
},
{
- "indexed": false,
- "name": "_value",
- "type": "uint256"
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "name": "_owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "name": "_spender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "name": "_value",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
}
- ],
- "name": "Approval",
- "type": "event"
- }
- ],
- "unlinked_binary": "0x6060604052341561000c57fe5b5b6105018061001c6000396000f300606060405236156100675763ffffffff60e060020a600035041663095ea7b3811461006957806318160ddd1461009c57806323b872dd146100be57806370a08231146100f7578063a0712d6814610125578063a9059cbb1461013a578063dd62ed3e1461016d575bfe5b341561007157fe5b610088600160a060020a03600435166024356101a1565b604080519115158252519081900360200190f35b34156100a457fe5b6100ac61020c565b60408051918252519081900360200190f35b34156100c657fe5b610088600160a060020a0360043581169060243516604435610212565b604080519115158252519081900360200190f35b34156100ff57fe5b6100ac600160a060020a0360043516610335565b60408051918252519081900360200190f35b341561012d57fe5b610138600435610354565b005b341561014257fe5b610088600160a060020a03600435166024356103bc565b604080519115158252519081900360200190f35b341561017557fe5b6100ac600160a060020a036004358116906024351661046e565b60408051918252519081900360200190f35b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a03808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906102555750828110155b801561027b5750600160a060020a03841660009081526020819052604090205483810110155b1561032757600160a060020a03808516600090815260208190526040808220805487019055918716815220805484900390556000198110156102e557600160a060020a03808616600090815260016020908152604080832033909416835292905220805484900390555b83600160a060020a031685600160a060020a03166000805160206104b6833981519152856040518082815260200191505060405180910390a36001915061032c565b600091505b5b509392505050565b600160a060020a0381166000908152602081905260409020545b919050565b68056bc75e2d6310000081111561036b5760006000fd5b600160a060020a03331660009081526020819052604090205461038f90829061049b565b600160a060020a0333166000908152602081905260409020556002546103b5908261049b565b6002555b50565b600160a060020a0333166000908152602081905260408120548290108015906103ff5750600160a060020a03831660009081526020819052604090205482810110155b1561045f57600160a060020a0333811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191936000805160206104b6833981519152929081900390910190a3506001610206565b506000610206565b5b92915050565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b6000828201838110156104aa57fe5b8091505b50929150505600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a72305820998c8326b9629e063eb4867166e72c68a8c2e3ebca6a9d35ebc78c041c7aa47b0029",
- "networks": {},
- "schema_version": "0.0.5",
- "updated_at": 1503413048892
-} \ No newline at end of file
+ ],
+ "unlinked_binary":
+ "0x6060604052341561000c57fe5b5b6105018061001c6000396000f300606060405236156100675763ffffffff60e060020a600035041663095ea7b3811461006957806318160ddd1461009c57806323b872dd146100be57806370a08231146100f7578063a0712d6814610125578063a9059cbb1461013a578063dd62ed3e1461016d575bfe5b341561007157fe5b610088600160a060020a03600435166024356101a1565b604080519115158252519081900360200190f35b34156100a457fe5b6100ac61020c565b60408051918252519081900360200190f35b34156100c657fe5b610088600160a060020a0360043581169060243516604435610212565b604080519115158252519081900360200190f35b34156100ff57fe5b6100ac600160a060020a0360043516610335565b60408051918252519081900360200190f35b341561012d57fe5b610138600435610354565b005b341561014257fe5b610088600160a060020a03600435166024356103bc565b604080519115158252519081900360200190f35b341561017557fe5b6100ac600160a060020a036004358116906024351661046e565b60408051918252519081900360200190f35b600160a060020a03338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60025481565b600160a060020a03808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906102555750828110155b801561027b5750600160a060020a03841660009081526020819052604090205483810110155b1561032757600160a060020a03808516600090815260208190526040808220805487019055918716815220805484900390556000198110156102e557600160a060020a03808616600090815260016020908152604080832033909416835292905220805484900390555b83600160a060020a031685600160a060020a03166000805160206104b6833981519152856040518082815260200191505060405180910390a36001915061032c565b600091505b5b509392505050565b600160a060020a0381166000908152602081905260409020545b919050565b68056bc75e2d6310000081111561036b5760006000fd5b600160a060020a03331660009081526020819052604090205461038f90829061049b565b600160a060020a0333166000908152602081905260409020556002546103b5908261049b565b6002555b50565b600160a060020a0333166000908152602081905260408120548290108015906103ff5750600160a060020a03831660009081526020819052604090205482810110155b1561045f57600160a060020a0333811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191936000805160206104b6833981519152929081900390910190a3506001610206565b506000610206565b5b92915050565b600160a060020a038083166000908152600160209081526040808320938516835292905220545b92915050565b6000828201838110156104aa57fe5b8091505b50929150505600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a72305820998c8326b9629e063eb4867166e72c68a8c2e3ebca6a9d35ebc78c041c7aa47b0029",
+ "networks": {},
+ "schema_version": "0.0.5",
+ "updated_at": 1503413048892
+}
diff --git a/packages/website/md/docs/0xjs/async.md b/packages/website/md/docs/0xjs/async.md
index 63924c76c..8abaef331 100644
--- a/packages/website/md/docs/0xjs/async.md
+++ b/packages/website/md/docs/0xjs/async.md
@@ -1,6 +1,7 @@
0x.js is a promise-based library. This means that whenever an asynchronous call is required, the library method will return a native Javascript promise. You can therefore choose between using `promise` or `async/await` syntax when calling our async methods.
-*Async/await syntax (recommended):*
+_Async/await syntax (recommended):_
+
```javascript
try {
var availableAddresses = await zeroEx.getAvailableAddressesAsync();
@@ -9,9 +10,11 @@ try {
}
```
-*Promise syntax:*
+_Promise syntax:_
+
```javascript
-zeroEx.getAvailableAddressesAsync()
+zeroEx
+ .getAvailableAddressesAsync()
.then(function(availableAddresses) {
console.log(availableAddresses);
})
diff --git a/packages/website/md/docs/0xjs/installation.md b/packages/website/md/docs/0xjs/installation.md
index 457b27a04..5f5c9137e 100644
--- a/packages/website/md/docs/0xjs/installation.md
+++ b/packages/website/md/docs/0xjs/installation.md
@@ -1,6 +1,6 @@
0x.js ships as both a [UMD](https://github.com/umdjs/umd) module and a [CommonJS](https://en.wikipedia.org/wiki/CommonJS) package.
-#### CommonJS *(recommended)*:
+#### CommonJS _(recommended)_:
**Install**
@@ -11,7 +11,7 @@ npm install 0x.js --save
**Import**
```javascript
-import {ZeroEx} from '0x.js';
+import { ZeroEx } from '0x.js';
```
#### UMD:
diff --git a/packages/website/md/docs/connect/installation.md b/packages/website/md/docs/connect/installation.md
index b14bc1b52..184fa6e0d 100644
--- a/packages/website/md/docs/connect/installation.md
+++ b/packages/website/md/docs/connect/installation.md
@@ -7,7 +7,7 @@ npm install @0xproject/connect --save
**Import**
```javascript
-import {HttpClient} from '@0xproject/connect';
+import { HttpClient } from '@0xproject/connect';
```
### Wiki
diff --git a/packages/website/md/docs/smart_contracts/introduction.md b/packages/website/md/docs/smart_contracts/introduction.md
index 406177f84..20396289b 100644
--- a/packages/website/md/docs/smart_contracts/introduction.md
+++ b/packages/website/md/docs/smart_contracts/introduction.md
@@ -2,7 +2,7 @@ Welcome to the [0x smart contracts](https://github.com/0xProject/contracts) docu
### Helpful wiki articles:
-- [Overview of 0x protocol architecture](https://0xproject.com/wiki#Architecture)
-- [0x smart contract interactions](https://0xproject.com/wiki#Contract-Interactions)
-- [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses)
-- [0x protocol message format](https://0xproject.com/wiki#Message-Format)
+* [Overview of 0x protocol architecture](https://0xproject.com/wiki#Architecture)
+* [0x smart contract interactions](https://0xproject.com/wiki#Contract-Interactions)
+* [Deployed smart contract addresses](https://0xproject.com/wiki#Deployed-Addresses)
+* [0x protocol message format](https://0xproject.com/wiki#Message-Format)
diff --git a/packages/website/package.json b/packages/website/package.json
index 9234ad601..fcfa12301 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -1,107 +1,106 @@
{
- "name": "website",
- "version": "0.0.1",
- "private": true,
- "description": "Website and 0x portal dapp",
- "scripts": {
- "build": "NODE_ENV=production webpack; exit 0;",
- "clean": "shx rm -f public/bundle*",
- "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'",
- "dev": "webpack-dev-server --content-base public --https",
- "update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../website/contracts; done;",
- "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers",
- "deploy_live": "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers"
- },
- "config": {
- "artifacts": "Mintable"
- },
- "author": "Fabio Berger",
- "license": "Apache-2.0",
- "dependencies": {
- "@0xproject/subproviders": "0.0.1",
- "0x.js": "0xproject/0x.js/packages/0x.js#0x.js@0.27.1",
- "accounting": "^0.4.1",
- "basscss": "^8.0.3",
- "bignumber.js": "~4.1.0",
- "blockies": "^0.0.2",
- "compare-versions": "^3.0.1",
- "dateformat": "^2.0.0",
- "deep-equal": "^1.0.1",
- "dharma-loan-frame": "^0.0.12",
- "ethereum-address": "^0.0.4",
- "ethereumjs-tx": "^1.3.3",
- "ethereumjs-util": "^5.1.1",
- "find-versions": "^2.0.0",
- "is-mobile": "^0.2.2",
- "jsonschema": "^1.2.0",
- "ledgerco": "0xProject/ledger-node-js-api",
- "less": "^2.7.2",
- "lodash": "^4.17.4",
- "material-ui": "^0.17.1",
- "moment": "^2.18.1",
- "query-string": "^5.0.1",
- "react": "15.6.1",
- "react-copy-to-clipboard": "^4.2.3",
- "react-document-title": "^2.0.3",
- "react-dom": "15.6.1",
- "react-highlight": "^0.10.0",
- "react-html5video": "^2.1.0",
- "react-inlinesvg": "^0.5.5",
- "react-markdown": "^2.5.0",
- "react-recaptcha": "^2.3.2",
- "react-redux": "^5.0.3",
- "react-router-dom": "^4.1.1",
- "react-router-hash-link": "^1.1.0",
- "react-scroll": "^1.5.2",
- "react-tap-event-plugin": "^2.0.1",
- "react-tooltip": "^3.2.7",
- "react-waypoint": "^7.0.4",
- "redux": "^3.6.0",
- "scroll-to-element": "^2.0.0",
- "semver-sort": "0.0.4",
- "thenby": "^1.2.3",
- "truffle-contract": "2.0.1",
- "tslint-config-0xproject": "^0.0.2",
- "web3": "^0.20.0",
- "web3-provider-engine": "^13.0.1",
- "whatwg-fetch": "^2.0.3",
- "xml-js": "^1.3.2"
- },
- "devDependencies": {
- "@types/accounting": "^0.4.1",
- "@types/dateformat": "^1.0.1",
- "@types/deep-equal": "^1.0.0",
- "@types/jsonschema": "^1.1.1",
- "@types/lodash": "^4.14.86",
- "@types/material-ui": "0.18.0",
- "@types/moment": "^2.13.0",
- "@types/node": "^8.0.53",
- "@types/query-string": "^5.0.1",
- "@types/react": "^15.0.15",
- "@types/react-copy-to-clipboard": "^4.2.0",
- "@types/react-dom": "^0.14.23",
- "@types/react-redux": "^4.4.37",
- "@types/react-router-dom": "^4.0.4",
- "@types/react-scroll": "0.0.31",
- "@types/react-tap-event-plugin": "0.0.30",
- "@types/redux": "^3.6.0",
- "awesome-typescript-loader": "^3.1.3",
- "copy-webpack-plugin": "^4.0.1",
- "copyfiles": "^1.2.0",
- "css-loader": "0.23.x",
- "exports-loader": "0.6.x",
- "imports-loader": "0.6.x",
- "json-loader": "^0.5.4",
- "less-loader": "^2.2.3",
- "raw-loader": "^0.5.1",
- "shx": "^0.2.2",
- "source-map-loader": "^0.1.6",
- "style-loader": "0.13.x",
- "tslint": "5.8.0",
- "typescript": "~2.6.1",
- "web3-typescript-typings": "^0.7.2",
- "webpack": "^3.1.0",
- "webpack-dev-middleware": "^1.10.0",
- "webpack-dev-server": "^2.5.0"
- }
+ "name": "@0xproject/website",
+ "version": "0.0.8",
+ "private": true,
+ "description": "Website and 0x portal dapp",
+ "scripts": {
+ "build": "NODE_ENV=production webpack; exit 0;",
+ "clean": "shx rm -f public/bundle*",
+ "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'",
+ "dev": "webpack-dev-server --content-base public --https",
+ "update_contracts": "for i in ${npm_package_config_artifacts}; do copyfiles -u 4 ../contracts/build/contracts/$i.json ../website/contracts; done;",
+ "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers",
+ "deploy_live": "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers"
+ },
+ "config": {
+ "artifacts": "Mintable"
+ },
+ "author": "Fabio Berger",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "0x.js": "^0.30.1",
+ "@0xproject/subproviders": "^0.3.2",
+ "@0xproject/utils": "^0.2.1",
+ "accounting": "^0.4.1",
+ "basscss": "^8.0.3",
+ "blockies": "^0.0.2",
+ "compare-versions": "^3.0.1",
+ "dateformat": "^2.0.0",
+ "deep-equal": "^1.0.1",
+ "dharma-loan-frame": "^0.0.12",
+ "ethereumjs-tx": "^1.3.3",
+ "ethereumjs-util": "^5.1.1",
+ "find-versions": "^2.0.0",
+ "is-mobile": "^0.2.2",
+ "jsonschema": "^1.2.0",
+ "ledgerco": "0xProject/ledger-node-js-api",
+ "less": "^2.7.2",
+ "lodash": "^4.17.4",
+ "material-ui": "^0.17.1",
+ "moment": "^2.18.1",
+ "query-string": "^5.0.1",
+ "react": "15.6.1",
+ "react-copy-to-clipboard": "^4.2.3",
+ "react-document-title": "^2.0.3",
+ "react-dom": "15.6.1",
+ "react-highlight": "^0.10.0",
+ "react-html5video": "^2.1.0",
+ "react-inlinesvg": "^0.5.5",
+ "react-markdown": "^2.5.0",
+ "react-recaptcha": "^2.3.2",
+ "react-redux": "^5.0.3",
+ "react-router-dom": "^4.1.1",
+ "react-router-hash-link": "^1.1.0",
+ "react-scroll": "^1.5.2",
+ "react-tap-event-plugin": "^2.0.1",
+ "react-tooltip": "^3.2.7",
+ "react-waypoint": "^7.0.4",
+ "redux": "^3.6.0",
+ "scroll-to-element": "^2.0.0",
+ "semver-sort": "0.0.4",
+ "thenby": "^1.2.3",
+ "truffle-contract": "2.0.1",
+ "tslint-config-0xproject": "^0.0.2",
+ "web3": "^0.20.0",
+ "web3-provider-engine": "^13.0.1",
+ "whatwg-fetch": "^2.0.3",
+ "xml-js": "^1.3.2"
+ },
+ "devDependencies": {
+ "@types/accounting": "^0.4.1",
+ "@types/dateformat": "^1.0.1",
+ "@types/deep-equal": "^1.0.0",
+ "@types/jsonschema": "^1.1.1",
+ "@types/lodash": "^4.14.86",
+ "@types/material-ui": "0.18.0",
+ "@types/moment": "^2.13.0",
+ "@types/node": "^8.0.53",
+ "@types/query-string": "^5.0.1",
+ "@types/react": "^15.0.15",
+ "@types/react-copy-to-clipboard": "^4.2.0",
+ "@types/react-dom": "^0.14.23",
+ "@types/react-redux": "^4.4.37",
+ "@types/react-router-dom": "^4.0.4",
+ "@types/react-scroll": "0.0.31",
+ "@types/react-tap-event-plugin": "0.0.30",
+ "@types/redux": "^3.6.0",
+ "awesome-typescript-loader": "^3.1.3",
+ "copy-webpack-plugin": "^4.0.1",
+ "copyfiles": "^1.2.0",
+ "css-loader": "0.23.x",
+ "exports-loader": "0.6.x",
+ "imports-loader": "0.6.x",
+ "json-loader": "^0.5.4",
+ "less-loader": "^2.2.3",
+ "raw-loader": "^0.5.1",
+ "shx": "^0.2.2",
+ "source-map-loader": "^0.1.6",
+ "style-loader": "0.13.x",
+ "tslint": "5.8.0",
+ "typescript": "~2.6.1",
+ "web3-typescript-typings": "^0.9.5",
+ "webpack": "^3.1.0",
+ "webpack-dev-middleware": "^1.10.0",
+ "webpack-dev-server": "^2.5.0"
+ }
}
diff --git a/packages/website/public/images/ether.png b/packages/website/public/images/ether.png
index 6a40a976d..c92f45681 100644
--- a/packages/website/public/images/ether.png
+++ b/packages/website/public/images/ether.png
Binary files differ
diff --git a/packages/website/public/images/social/discourse.png b/packages/website/public/images/social/discourse.png
new file mode 100644
index 000000000..4bca3de0d
--- /dev/null
+++ b/packages/website/public/images/social/discourse.png
Binary files differ
diff --git a/packages/website/public/images/team/jacob.jpg b/packages/website/public/images/team/jacob.jpg
new file mode 100644
index 000000000..62ff412d2
--- /dev/null
+++ b/packages/website/public/images/team/jacob.jpg
Binary files differ
diff --git a/packages/website/public/images/team/tom.jpg b/packages/website/public/images/team/tom.jpg
new file mode 100644
index 000000000..a6b763816
--- /dev/null
+++ b/packages/website/public/images/team/tom.jpg
Binary files differ
diff --git a/packages/website/public/images/token_icons/augur.png b/packages/website/public/images/token_icons/augur.png
index 31c257ba9..b7d61100a 100644
--- a/packages/website/public/images/token_icons/augur.png
+++ b/packages/website/public/images/token_icons/augur.png
Binary files differ
diff --git a/packages/website/public/images/token_icons/default.png b/packages/website/public/images/token_icons/default.png
index 7ce754030..5c9ea4b0f 100644
--- a/packages/website/public/images/token_icons/default.png
+++ b/packages/website/public/images/token_icons/default.png
Binary files differ
diff --git a/packages/website/public/images/token_icons/district0x.png b/packages/website/public/images/token_icons/district0x.png
index edb8f2238..7427b1146 100644
--- a/packages/website/public/images/token_icons/district0x.png
+++ b/packages/website/public/images/token_icons/district0x.png
Binary files differ
diff --git a/packages/website/public/images/token_icons/ether_erc20.png b/packages/website/public/images/token_icons/ether_erc20.png
index f4154db7b..bc8beae8b 100644
--- a/packages/website/public/images/token_icons/ether_erc20.png
+++ b/packages/website/public/images/token_icons/ether_erc20.png
Binary files differ
diff --git a/packages/website/public/images/token_icons/firstblood.jpg b/packages/website/public/images/token_icons/firstblood.jpg
index 64bb65605..9cd23b10e 100644
--- a/packages/website/public/images/token_icons/firstblood.jpg
+++ b/packages/website/public/images/token_icons/firstblood.jpg
Binary files differ
diff --git a/packages/website/public/images/token_icons/qtum.png b/packages/website/public/images/token_icons/qtum.png
index 97e227c5c..b7f09dfd2 100644
--- a/packages/website/public/images/token_icons/qtum.png
+++ b/packages/website/public/images/token_icons/qtum.png
Binary files differ
diff --git a/packages/website/public/images/token_icons/zero_ex.png b/packages/website/public/images/token_icons/zero_ex.png
index 6c6deef11..8ed9a984b 100644
--- a/packages/website/public/images/token_icons/zero_ex.png
+++ b/packages/website/public/images/token_icons/zero_ex.png
Binary files differ
diff --git a/packages/website/public/images/wrapped_eth_gray.png b/packages/website/public/images/wrapped_eth_gray.png
new file mode 100644
index 000000000..397b31b1c
--- /dev/null
+++ b/packages/website/public/images/wrapped_eth_gray.png
Binary files differ
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index 76640a072..5530701c0 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -1,7 +1,7 @@
import {
BlockParam,
+ BlockRange,
DecodedLogEvent,
- ExchangeContractErrs,
ExchangeContractEventArgs,
ExchangeEvents,
IndexedFilterValues,
@@ -10,11 +10,9 @@ import {
LogWithDecodedArgs,
Order,
SignedOrder,
- SubscriptionOpts,
Token as ZeroExToken,
TransactionReceiptWithDecodedLogs,
ZeroEx,
- ZeroExError,
} from '0x.js';
import {
InjectedWeb3Subprovider,
@@ -23,24 +21,19 @@ import {
LedgerWalletSubprovider,
RedundantRPCSubprovider,
} from '@0xproject/subproviders';
-import {promisify} from '@0xproject/utils';
-import BigNumber from 'bignumber.js';
-import compareVersions = require('compare-versions');
-import ethUtil = require('ethereumjs-util');
-import findVersions = require('find-versions');
+import { BigNumber, intervalUtils, promisify } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
import contract = require('truffle-contract');
-import {TokenSendCompleted} from 'ts/components/flash_messages/token_send_completed';
-import {TransactionSubmitted} from 'ts/components/flash_messages/transaction_submitted';
-import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage';
-import {tradeHistoryStorage} from 'ts/local_storage/trade_history_storage';
-import {Dispatcher} from 'ts/redux/dispatcher';
+import { TokenSendCompleted } from 'ts/components/flash_messages/token_send_completed';
+import { TransactionSubmitted } from 'ts/components/flash_messages/transaction_submitted';
+import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
+import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage';
+import { Dispatcher } from 'ts/redux/dispatcher';
import {
BlockchainCallErrs,
BlockchainErrs,
ContractInstance,
- ContractResponse,
EtherscanLinkSuffixes,
ProviderType,
Side,
@@ -49,58 +42,55 @@ import {
TokenByAddress,
TokenStateByAddress,
} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
-import {errorReporter} from 'ts/utils/error_reporter';
-import {utils} from 'ts/utils/utils';
-import {Web3Wrapper} from 'ts/web3_wrapper';
+import { configs } from 'ts/utils/configs';
+import { constants } from 'ts/utils/constants';
+import { errorReporter } from 'ts/utils/error_reporter';
+import { utils } from 'ts/utils/utils';
+import { Web3Wrapper } from 'ts/web3_wrapper';
import Web3 = require('web3');
import ProviderEngine = require('web3-provider-engine');
import FilterSubprovider = require('web3-provider-engine/subproviders/filters');
import * as MintableArtifacts from '../contracts/Mintable.json';
-const ALLOWANCE_TO_ZERO_GAS_AMOUNT = 45730;
const BLOCK_NUMBER_BACK_TRACK = 50;
export class Blockchain {
public networkId: number;
public nodeVersion: string;
- private zeroEx: ZeroEx;
- private dispatcher: Dispatcher;
- private web3Wrapper?: Web3Wrapper;
- private exchangeAddress: string;
- private tokenTransferProxy: ContractInstance;
- private tokenRegistry: ContractInstance;
- private userAddress: string;
- private cachedProvider: Web3.Provider;
- private ledgerSubprovider: LedgerWalletSubprovider;
- private zrxPollIntervalId: number;
- private static async onPageLoadAsync() {
+ private _zeroEx: ZeroEx;
+ private _dispatcher: Dispatcher;
+ private _web3Wrapper?: Web3Wrapper;
+ private _exchangeAddress: string;
+ private _userAddress: string;
+ private _cachedProvider: Web3.Provider;
+ private _ledgerSubprovider: LedgerWalletSubprovider;
+ private _zrxPollIntervalId: NodeJS.Timer;
+ private static async _onPageLoadAsync(): Promise<void> {
if (document.readyState === 'complete') {
return; // Already loaded
}
- return new Promise((resolve, reject) => {
- window.onload = resolve;
+ return new Promise<void>((resolve, reject) => {
+ window.onload = () => resolve();
});
}
- private static getNameGivenProvider(provider: Web3.Provider): string {
+ 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) {
+ 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;
@@ -110,9 +100,7 @@ export class Blockchain {
provider = new ProviderEngine();
provider.addProvider(new InjectedWeb3Subprovider(injectedWeb3));
provider.addProvider(new FilterSubprovider());
- provider.addProvider(new RedundantRPCSubprovider(
- publicNodeUrlsIfExistsForNetworkId,
- ));
+ provider.addProvider(new RedundantRPCSubprovider(publicNodeUrlsIfExistsForNetworkId));
provider.start();
} else if (doesInjectedWeb3Exist) {
// Since no public node for this network, all requests go to injectedWeb3 instance
@@ -123,41 +111,37 @@ 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;
- provider.addProvider(new RedundantRPCSubprovider(
- constants.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
- ));
+ const networkId = configs.IS_MAINNET_ENABLED ? constants.NETWORK_ID_MAINNET : constants.NETWORK_ID_TESTNET;
+ provider.addProvider(new RedundantRPCSubprovider(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId]));
provider.start();
}
return provider;
}
constructor(dispatcher: Dispatcher, isSalePage: boolean = false) {
- this.dispatcher = dispatcher;
- this.userAddress = '';
+ this._dispatcher = dispatcher;
+ this._userAddress = '';
// tslint:disable-next-line:no-floating-promises
- this.onPageLoadInitFireAndForgetAsync();
+ this._onPageLoadInitFireAndForgetAsync();
}
public async networkIdUpdatedFireAndForgetAsync(newNetworkId: number) {
const isConnected = !_.isUndefined(newNetworkId);
if (!isConnected) {
this.networkId = newNetworkId;
- this.dispatcher.encounteredBlockchainError(BlockchainErrs.DISCONNECTED_FROM_ETHEREUM_NODE);
- this.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
+ this._dispatcher.encounteredBlockchainError(BlockchainErrs.DisconnectedFromEthereumNode);
+ this._dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
} else if (this.networkId !== newNetworkId) {
this.networkId = newNetworkId;
- this.dispatcher.encounteredBlockchainError('');
- await this.fetchTokenInformationAsync();
- await this.rehydrateStoreWithContractEvents();
+ this._dispatcher.encounteredBlockchainError(BlockchainErrs.NoError);
+ await this._fetchTokenInformationAsync();
+ await this._rehydrateStoreWithContractEvents();
}
}
public async userAddressUpdatedFireAndForgetAsync(newUserAddress: string) {
- if (this.userAddress !== newUserAddress) {
- this.userAddress = newUserAddress;
- await this.fetchTokenInformationAsync();
- await this.rehydrateStoreWithContractEvents();
+ if (this._userAddress !== newUserAddress) {
+ this._userAddress = newUserAddress;
+ await this._fetchTokenInformationAsync();
+ await this._rehydrateStoreWithContractEvents();
}
}
public async nodeVersionUpdatedFireAndForgetAsync(nodeVersion: string) {
@@ -166,80 +150,85 @@ export class Blockchain {
}
}
public async isAddressInTokenRegistryAsync(tokenAddress: string): Promise<boolean> {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
- const tokenIfExists = await this.zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ // HACK: temporarily whitelist the new WETH token address `as if` they were
+ // already in the tokenRegistry.
+ // TODO: Remove this hack once we've updated the TokenRegistries
+ // Airtable task: https://airtable.com/tblFe0Q9JuKJPYbTn/viwsOG2Y97qdIeCIO/recv3VGmIorFzHBVz
+ if (configs.SHOULD_DEPRECATE_OLD_WETH_TOKEN && tokenAddress === configs.NEW_WRAPPED_ETHERS[this.networkId]) {
+ return true;
+ }
+ const tokenIfExists = await this._zeroEx.tokenRegistry.getTokenIfExistsAsync(tokenAddress);
return !_.isUndefined(tokenIfExists);
}
public getLedgerDerivationPathIfExists(): string {
- if (_.isUndefined(this.ledgerSubprovider)) {
+ if (_.isUndefined(this._ledgerSubprovider)) {
return undefined;
}
- const path = this.ledgerSubprovider.getPath();
+ const path = this._ledgerSubprovider.getPath();
return path;
}
public updateLedgerDerivationPathIfExists(path: string) {
- if (_.isUndefined(this.ledgerSubprovider)) {
+ if (_.isUndefined(this._ledgerSubprovider)) {
return; // noop
}
- this.ledgerSubprovider.setPath(path);
+ this._ledgerSubprovider.setPath(path);
}
public updateLedgerDerivationIndex(pathIndex: number) {
- if (_.isUndefined(this.ledgerSubprovider)) {
+ if (_.isUndefined(this._ledgerSubprovider)) {
return; // noop
}
- this.ledgerSubprovider.setPathIndex(pathIndex);
+ this._ledgerSubprovider.setPathIndex(pathIndex);
}
public async providerTypeUpdatedFireAndForgetAsync(providerType: ProviderType) {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
// Should actually be Web3.Provider|ProviderEngine union type but it causes issues
// 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');
}
// Cache injected provider so that we can switch the user back to it easily
- this.cachedProvider = this.web3Wrapper.getProviderObj();
+ this._cachedProvider = this._web3Wrapper.getProviderObj();
- this.dispatcher.updateUserAddress(''); // Clear old userAddress
+ this._dispatcher.updateUserAddress(''); // Clear old userAddress
provider = new ProviderEngine();
const ledgerWalletConfigs = {
networkId: this.networkId,
ledgerEthereumClientFactoryAsync: ledgerEthereumBrowserClientFactoryAsync,
};
- this.ledgerSubprovider = new LedgerSubprovider(ledgerWalletConfigs);
- provider.addProvider(this.ledgerSubprovider);
+ 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;
- provider.addProvider(new RedundantRPCSubprovider(
- constants.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId],
- ));
+ const networkId = configs.IS_MAINNET_ENABLED
+ ? constants.NETWORK_ID_MAINNET
+ : constants.NETWORK_ID_TESTNET;
+ provider.addProvider(new RedundantRPCSubprovider(configs.PUBLIC_NODE_URLS_BY_NETWORK_ID[networkId]));
provider.start();
- this.web3Wrapper.destroy();
+ this._web3Wrapper.destroy();
const shouldPollUserAddress = false;
- this.web3Wrapper = new Web3Wrapper(this.dispatcher, provider, this.networkId, shouldPollUserAddress);
- this.zeroEx.setProvider(provider, networkId);
- await this.postInstantiationOrUpdatingProviderZeroExAsync();
+ this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress);
+ this._zeroEx.setProvider(provider, networkId);
+ await this._postInstantiationOrUpdatingProviderZeroExAsync();
break;
}
- case ProviderType.INJECTED: {
- if (_.isUndefined(this.cachedProvider)) {
+ case ProviderType.Injected: {
+ if (_.isUndefined(this._cachedProvider)) {
return; // Going from injected to injected, so we noop
}
- provider = this.cachedProvider;
+ provider = this._cachedProvider;
const shouldPollUserAddress = true;
- this.web3Wrapper = new Web3Wrapper(this.dispatcher, provider, this.networkId, shouldPollUserAddress);
- this.zeroEx.setProvider(provider, this.networkId);
- await this.postInstantiationOrUpdatingProviderZeroExAsync();
- delete this.ledgerSubprovider;
- delete this.cachedProvider;
+ this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, this.networkId, shouldPollUserAddress);
+ this._zeroEx.setProvider(provider, this.networkId);
+ await this._postInstantiationOrUpdatingProviderZeroExAsync();
+ delete this._ledgerSubprovider;
+ delete this._cachedProvider;
break;
}
@@ -247,40 +236,54 @@ export class Blockchain {
throw utils.spawnSwitchErr('providerType', providerType);
}
- await this.fetchTokenInformationAsync();
+ 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(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
+ 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(
- token.address, this.userAddress, amountInBaseUnits,
+ const txHash = await this._zeroEx.token.setProxyAllowanceAsync(
+ token.address,
+ this._userAddress,
+ amountInBaseUnits,
);
- await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
+ await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const allowance = amountInBaseUnits;
- this.dispatcher.replaceTokenAllowanceByAddress(token.address, allowance);
+ this._dispatcher.replaceTokenAllowanceByAddress(token.address, allowance);
}
- public async transferAsync(token: Token, toAddress: string,
- amountInBaseUnits: BigNumber): Promise<void> {
- const txHash = await this.zeroEx.token.transferAsync(
- token.address, this.userAddress, toAddress, amountInBaseUnits,
- );
- await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
- const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.tx);
- this.dispatcher.showFlashMessage(React.createElement(TokenSendCompleted, {
- etherScanLinkIfExists,
- token,
+ public async transferAsync(token: Token, toAddress: string, amountInBaseUnits: BigNumber): Promise<void> {
+ const txHash = await this._zeroEx.token.transferAsync(
+ token.address,
+ this._userAddress,
toAddress,
amountInBaseUnits,
- }));
- }
- public portalOrderToSignedOrder(maker: string, taker: string, makerTokenAddress: string,
- takerTokenAddress: string, makerTokenAmount: BigNumber,
- takerTokenAmount: BigNumber, makerFee: BigNumber,
- takerFee: BigNumber, expirationUnixTimestampSec: BigNumber,
- feeRecipient: string,
- signatureData: SignatureData, salt: BigNumber): SignedOrder {
+ );
+ await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
+ const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.Tx);
+ this._dispatcher.showFlashMessage(
+ React.createElement(TokenSendCompleted, {
+ etherScanLinkIfExists,
+ token,
+ toAddress,
+ amountInBaseUnits,
+ }),
+ );
+ }
+ public portalOrderToSignedOrder(
+ maker: string,
+ taker: string,
+ makerTokenAddress: string,
+ takerTokenAddress: string,
+ makerTokenAmount: BigNumber,
+ takerTokenAmount: BigNumber,
+ makerFee: BigNumber,
+ takerFee: BigNumber,
+ expirationUnixTimestampSec: BigNumber,
+ feeRecipient: string,
+ signatureData: SignatureData,
+ salt: BigNumber,
+ ): SignedOrder {
const ecSignature = signatureData;
const exchangeContractAddress = this.getExchangeContractAddressIfExists();
const takerOrNullAddress = _.isEmpty(taker) ? constants.NULL_ADDRESS : taker;
@@ -301,127 +304,140 @@ export class Blockchain {
};
return signedOrder;
}
- public async fillOrderAsync(signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber): Promise<BigNumber> {
- utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES);
+ public async fillOrderAsync(signedOrder: SignedOrder, fillTakerTokenAmount: BigNumber): Promise<BigNumber> {
+ utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
const shouldThrowOnInsufficientBalanceOrAllowance = true;
- const txHash = await this.zeroEx.exchange.fillOrderAsync(
- signedOrder, fillTakerTokenAmount, shouldThrowOnInsufficientBalanceOrAllowance, this.userAddress,
+ const txHash = await this._zeroEx.exchange.fillOrderAsync(
+ signedOrder,
+ fillTakerTokenAmount,
+ shouldThrowOnInsufficientBalanceOrAllowance,
+ this._userAddress,
);
- const receipt = await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
+ const receipt = await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const logs: Array<LogWithDecodedArgs<ExchangeContractEventArgs>> = receipt.logs as any;
- this.zeroEx.exchange.throwLogErrorsAsErrors(logs);
- const logFill = _.find(logs, {event: 'LogFill'});
- const args = logFill.args as any as LogFillContractEventArgs;
+ this._zeroEx.exchange.throwLogErrorsAsErrors(logs);
+ const logFill = _.find(logs, { event: 'LogFill' });
+ const args = (logFill.args as any) as LogFillContractEventArgs;
const filledTakerTokenAmount = args.filledTakerTokenAmount;
return filledTakerTokenAmount;
}
- public async cancelOrderAsync(signedOrder: SignedOrder,
- cancelTakerTokenAmount: BigNumber): Promise<BigNumber> {
- const txHash = await this.zeroEx.exchange.cancelOrderAsync(
- signedOrder, cancelTakerTokenAmount,
- );
- const receipt = await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
+ public async cancelOrderAsync(signedOrder: SignedOrder, cancelTakerTokenAmount: BigNumber): Promise<BigNumber> {
+ const txHash = await this._zeroEx.exchange.cancelOrderAsync(signedOrder, cancelTakerTokenAmount);
+ const receipt = await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
const logs: Array<LogWithDecodedArgs<ExchangeContractEventArgs>> = receipt.logs as any;
- this.zeroEx.exchange.throwLogErrorsAsErrors(logs);
- const logCancel = _.find(logs, {event: ExchangeEvents.LogCancel});
- const args = logCancel.args as any as LogCancelContractEventArgs;
+ this._zeroEx.exchange.throwLogErrorsAsErrors(logs);
+ const logCancel = _.find(logs, { event: ExchangeEvents.LogCancel });
+ const args = (logCancel.args as any) as LogCancelContractEventArgs;
const cancelledTakerTokenAmount = args.cancelledTakerTokenAmount;
return cancelledTakerTokenAmount;
}
public async getUnavailableTakerAmountAsync(orderHash: string): Promise<BigNumber> {
utils.assert(ZeroEx.isValidOrderHash(orderHash), 'Must be valid orderHash');
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
- const unavailableTakerAmount = await this.zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash);
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ const unavailableTakerAmount = await this._zeroEx.exchange.getUnavailableTakerAmountAsync(orderHash);
return unavailableTakerAmount;
}
public getExchangeContractAddressIfExists() {
- return this.exchangeAddress;
- }
- public async validateFillOrderThrowIfInvalidAsync(signedOrder: SignedOrder,
- fillTakerTokenAmount: BigNumber,
- takerAddress: string): Promise<void> {
- await this.zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
- signedOrder, fillTakerTokenAmount, takerAddress);
+ return this._exchangeAddress;
+ }
+ public async validateFillOrderThrowIfInvalidAsync(
+ signedOrder: SignedOrder,
+ fillTakerTokenAmount: BigNumber,
+ takerAddress: string,
+ ): Promise<void> {
+ await this._zeroEx.exchange.validateFillOrderThrowIfInvalidAsync(
+ signedOrder,
+ fillTakerTokenAmount,
+ takerAddress,
+ );
}
- public async validateCancelOrderThrowIfInvalidAsync(order: Order,
- cancelTakerTokenAmount: BigNumber): Promise<void> {
- await this.zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount);
+ public async validateCancelOrderThrowIfInvalidAsync(
+ order: Order,
+ cancelTakerTokenAmount: BigNumber,
+ ): Promise<void> {
+ await this._zeroEx.exchange.validateCancelOrderThrowIfInvalidAsync(order, cancelTakerTokenAmount);
}
public isValidAddress(address: string): boolean {
const lowercaseAddress = address.toLowerCase();
- return this.web3Wrapper.isAddress(lowercaseAddress);
+ 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);
+ const [currBalance] = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, token.address);
- this.zrxPollIntervalId = window.setInterval(async () => {
- const [balance] = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, token.address);
- if (!balance.eq(currBalance)) {
- this.dispatcher.replaceTokenBalanceByAddress(token.address, balance);
- clearInterval(this.zrxPollIntervalId);
- delete this.zrxPollIntervalId;
- }
- }, 5000);
+ this._zrxPollIntervalId = intervalUtils.setAsyncExcludingInterval(
+ async () => {
+ const [balance] = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, token.address);
+ if (!balance.eq(currBalance)) {
+ this._dispatcher.replaceTokenBalanceByAddress(token.address, balance);
+ intervalUtils.clearAsyncExcludingInterval(this._zrxPollIntervalId);
+ delete this._zrxPollIntervalId;
+ }
+ },
+ 5000,
+ (err: Error) => {
+ utils.consoleLog(`Polling tokenBalance failed: ${err}`);
+ intervalUtils.clearAsyncExcludingInterval(this._zrxPollIntervalId);
+ delete this._zrxPollIntervalId;
+ },
+ );
}
public async signOrderHashAsync(orderHash: string): Promise<SignatureData> {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
- const makerAddress = this.userAddress;
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ const makerAddress = this._userAddress;
// If makerAddress is undefined, this means they have a web3 instance injected into their browser
// but no account addresses associated with it.
if (_.isUndefined(makerAddress)) {
throw new Error('Tried to send a sign request but user has no associated addresses');
}
- const ecSignature = await this.zeroEx.signOrderHashAsync(orderHash, makerAddress);
+ const ecSignature = await this._zeroEx.signOrderHashAsync(orderHash, makerAddress);
const signatureData = _.extend({}, ecSignature, {
hash: orderHash,
});
- this.dispatcher.updateSignatureData(signatureData);
+ this._dispatcher.updateSignatureData(signatureData);
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);
+ const mintableContract = await this._instantiateContractIfExistsAsync(MintableArtifacts, token.address);
await mintableContract.mint(constants.MINT_AMOUNT, {
- from: this.userAddress,
+ from: this._userAddress,
});
const balanceDelta = constants.MINT_AMOUNT;
- this.dispatcher.updateTokenBalanceByAddress(token.address, balanceDelta);
+ this._dispatcher.updateTokenBalanceByAddress(token.address, balanceDelta);
}
public async getBalanceInEthAsync(owner: string): Promise<BigNumber> {
- const balance = await this.web3Wrapper.getBalanceInEthAsync(owner);
+ const balance = await this._web3Wrapper.getBalanceInEthAsync(owner);
return balance;
}
- public async convertEthToWrappedEthTokensAsync(amount: BigNumber): Promise<void> {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
- utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES);
+ public async convertEthToWrappedEthTokensAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> {
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
- const txHash = await this.zeroEx.etherToken.depositAsync(amount, this.userAddress);
- await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
+ const txHash = await this._zeroEx.etherToken.depositAsync(etherTokenAddress, amount, this._userAddress);
+ await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
}
- public async convertWrappedEthTokensToEthAsync(amount: BigNumber): Promise<void> {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
- utils.assert(this.doesUserAddressExist(), BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES);
+ public async convertWrappedEthTokensToEthAsync(etherTokenAddress: string, amount: BigNumber): Promise<void> {
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
- const txHash = await this.zeroEx.etherToken.withdrawAsync(amount, this.userAddress);
- await this.showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
+ const txHash = await this._zeroEx.etherToken.withdrawAsync(etherTokenAddress, amount, this._userAddress);
+ await this._showEtherScanLinkAndAwaitTransactionMinedAsync(txHash);
}
public async doesContractExistAtAddressAsync(address: string) {
- const doesContractExist = await this.web3Wrapper.doesContractExistAtAddressAsync(address);
+ const doesContractExist = await this._web3Wrapper.doesContractExistAtAddressAsync(address);
return doesContractExist;
}
public async getCurrentUserTokenBalanceAndAllowanceAsync(tokenAddress: string): Promise<BigNumber[]> {
- const tokenBalanceAndAllowance = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, tokenAddress);
- return tokenBalanceAndAllowance;
+ const tokenBalanceAndAllowance = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, tokenAddress);
+ return tokenBalanceAndAllowance;
}
- public async getTokenBalanceAndAllowanceAsync(ownerAddress: string, tokenAddress: string):
- Promise<BigNumber[]> {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
+ public async getTokenBalanceAndAllowanceAsync(ownerAddress: string, tokenAddress: string): Promise<BigNumber[]> {
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
if (_.isEmpty(ownerAddress)) {
const zero = new BigNumber(0);
@@ -429,9 +445,9 @@ export class Blockchain {
}
let balance = new BigNumber(0);
let allowance = new BigNumber(0);
- if (this.doesUserAddressExist()) {
- balance = await this.zeroEx.token.getBalanceAsync(tokenAddress, ownerAddress);
- allowance = await this.zeroEx.token.getProxyAllowanceAsync(tokenAddress, ownerAddress);
+ if (this._doesUserAddressExist()) {
+ balance = await this._zeroEx.token.getBalanceAsync(tokenAddress, ownerAddress);
+ allowance = await this._zeroEx.token.getProxyAllowanceAsync(tokenAddress, ownerAddress);
}
return [balance, allowance];
}
@@ -440,11 +456,8 @@ export class Blockchain {
for (const token of tokens) {
let balance = new BigNumber(0);
let allowance = new BigNumber(0);
- if (this.doesUserAddressExist()) {
- [
- balance,
- allowance,
- ] = await this.getTokenBalanceAndAllowanceAsync(this.userAddress, token.address);
+ if (this._doesUserAddressExist()) {
+ [balance, allowance] = await this.getTokenBalanceAndAllowanceAsync(this._userAddress, token.address);
}
const tokenState = {
balance,
@@ -452,110 +465,113 @@ export class Blockchain {
};
tokenStateByAddress[token.address] = tokenState;
}
- this.dispatcher.updateTokenStateByAddress(tokenStateByAddress);
+ this._dispatcher.updateTokenStateByAddress(tokenStateByAddress);
}
public async getUserAccountsAsync() {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
- const userAccountsIfExists = await this.zeroEx.getAvailableAddressesAsync();
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ const userAccountsIfExists = await this._zeroEx.getAvailableAddressesAsync();
return userAccountsIfExists;
}
// HACK: When a user is using a Ledger, we simply dispatch the selected userAddress, which
// by-passes the web3Wrapper logic for updating the prevUserAddress. We therefore need to
// manually update it. This should only be called by the LedgerConfigDialog.
public updateWeb3WrapperPrevUserAddress(newUserAddress: string) {
- this.web3Wrapper.updatePrevUserAddress(newUserAddress);
+ this._web3Wrapper.updatePrevUserAddress(newUserAddress);
}
public destroy() {
- clearInterval(this.zrxPollIntervalId);
- this.web3Wrapper.destroy();
- // tslint:disable-next-line:no-floating-promises
- this.stopWatchingExchangeLogFillEventsAsync(); // fire and forget
- }
- private async showEtherScanLinkAndAwaitTransactionMinedAsync(
- txHash: string): Promise<TransactionReceiptWithDecodedLogs> {
- const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.tx);
- this.dispatcher.showFlashMessage(React.createElement(TransactionSubmitted, {
- etherScanLinkIfExists,
- }));
- const receipt = await this.zeroEx.awaitTransactionMinedAsync(txHash);
+ intervalUtils.clearAsyncExcludingInterval(this._zrxPollIntervalId);
+ this._web3Wrapper.destroy();
+ this._stopWatchingExchangeLogFillEvents();
+ }
+ private async _showEtherScanLinkAndAwaitTransactionMinedAsync(
+ txHash: string,
+ ): Promise<TransactionReceiptWithDecodedLogs> {
+ const etherScanLinkIfExists = utils.getEtherScanLinkIfExists(txHash, this.networkId, EtherscanLinkSuffixes.Tx);
+ this._dispatcher.showFlashMessage(
+ React.createElement(TransactionSubmitted, {
+ etherScanLinkIfExists,
+ }),
+ );
+ const receipt = await this._zeroEx.awaitTransactionMinedAsync(txHash);
return receipt;
}
- private doesUserAddressExist(): boolean {
- return this.userAddress !== '';
+ private _doesUserAddressExist(): boolean {
+ return this._userAddress !== '';
}
- private async rehydrateStoreWithContractEvents() {
+ private async _rehydrateStoreWithContractEvents() {
// Ensure we are only ever listening to one set of events
- await this.stopWatchingExchangeLogFillEventsAsync();
+ this._stopWatchingExchangeLogFillEvents();
- if (!this.doesUserAddressExist()) {
+ if (!this._doesUserAddressExist()) {
return; // short-circuit
}
- if (!_.isUndefined(this.zeroEx)) {
+ if (!_.isUndefined(this._zeroEx)) {
// Since we do not have an index on the `taker` address and want to show
// transactions where an account is either the `maker` or `taker`, we loop
// through all fill events, and filter/cache them client-side.
const filterIndexObj = {};
- await this.startListeningForExchangeLogFillEventsAsync(filterIndexObj);
+ await this._startListeningForExchangeLogFillEventsAsync(filterIndexObj);
}
}
- 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);
+ private async _startListeningForExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues): Promise<void> {
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ utils.assert(this._doesUserAddressExist(), BlockchainCallErrs.UserHasNoAssociatedAddresses);
// Fetch historical logs
- await this.fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues);
+ await this._fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues);
// Start a subscription for new logs
- const exchangeAddress = this.getExchangeContractAddressIfExists();
- const subscriptionId = this.zeroEx.exchange.subscribe(
- ExchangeEvents.LogFill, indexFilterValues,
+ this._zeroEx.exchange.subscribe(
+ ExchangeEvents.LogFill,
+ indexFilterValues,
async (err: Error, decodedLogEvent: DecodedLogEvent<LogFillContractEventArgs>) => {
- if (err) {
- // Note: it's not entirely clear from the documentation which
- // errors will be thrown by `watch`. For now, let's log the error
- // to rollbar and stop watching when one occurs
- // tslint:disable-next-line:no-floating-promises
- errorReporter.reportAsync(err); // fire and forget
- // tslint:disable-next-line:no-floating-promises
- this.stopWatchingExchangeLogFillEventsAsync(); // fire and forget
- return;
- } else {
- const decodedLog = decodedLogEvent.log;
- if (!this.doesLogEventInvolveUser(decodedLog)) {
- return; // We aren't interested in the fill event
- }
- this.updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
- const fill = await this.convertDecodedLogToFillAsync(decodedLog);
- if (decodedLogEvent.isRemoved) {
- tradeHistoryStorage.removeFillFromUser(this.userAddress, this.networkId, fill);
+ if (err) {
+ // Note: it's not entirely clear from the documentation which
+ // errors will be thrown by `watch`. For now, let's log the error
+ // to rollbar and stop watching when one occurs
+ // tslint:disable-next-line:no-floating-promises
+ errorReporter.reportAsync(err); // fire and forget
+ return;
} else {
- tradeHistoryStorage.addFillToUser(this.userAddress, this.networkId, fill);
+ const decodedLog = decodedLogEvent.log;
+ if (!this._doesLogEventInvolveUser(decodedLog)) {
+ return; // We aren't interested in the fill event
+ }
+ this._updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
+ const fill = await this._convertDecodedLogToFillAsync(decodedLog);
+ if (decodedLogEvent.isRemoved) {
+ tradeHistoryStorage.removeFillFromUser(this._userAddress, this.networkId, fill);
+ } else {
+ tradeHistoryStorage.addFillToUser(this._userAddress, this.networkId, fill);
+ }
}
- }
- });
+ },
+ );
}
- private async fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues) {
- const fromBlock = tradeHistoryStorage.getFillsLatestBlock(this.userAddress, this.networkId);
- const subscriptionOpts: SubscriptionOpts = {
+ private async _fetchHistoricalExchangeLogFillEventsAsync(indexFilterValues: IndexedFilterValues) {
+ const fromBlock = tradeHistoryStorage.getFillsLatestBlock(this._userAddress, this.networkId);
+ const blockRange: BlockRange = {
fromBlock,
toBlock: 'latest' as BlockParam,
};
- const decodedLogs = await this.zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
- ExchangeEvents.LogFill, subscriptionOpts, indexFilterValues,
+ const decodedLogs = await this._zeroEx.exchange.getLogsAsync<LogFillContractEventArgs>(
+ ExchangeEvents.LogFill,
+ blockRange,
+ indexFilterValues,
);
for (const decodedLog of decodedLogs) {
- if (!this.doesLogEventInvolveUser(decodedLog)) {
+ if (!this._doesLogEventInvolveUser(decodedLog)) {
continue; // We aren't interested in the fill event
}
- this.updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
- const fill = await this.convertDecodedLogToFillAsync(decodedLog);
- tradeHistoryStorage.addFillToUser(this.userAddress, this.networkId, fill);
+ this._updateLatestFillsBlockIfNeeded(decodedLog.blockNumber);
+ const fill = await this._convertDecodedLogToFillAsync(decodedLog);
+ tradeHistoryStorage.addFillToUser(this._userAddress, this.networkId, fill);
}
}
- private async convertDecodedLogToFillAsync(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>) {
+ private async _convertDecodedLogToFillAsync(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>) {
const args = decodedLog.args;
- const blockTimestamp = await this.web3Wrapper.getBlockTimestampAsync(decodedLog.blockHash);
+ const blockTimestamp = await this._web3Wrapper.getBlockTimestampAsync(decodedLog.blockHash);
const fill = {
filledTakerTokenAmount: args.filledTakerTokenAmount,
filledMakerTokenAmount: args.filledMakerTokenAmount,
@@ -572,13 +588,12 @@ export class Blockchain {
};
return fill;
}
- private doesLogEventInvolveUser(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>) {
+ private _doesLogEventInvolveUser(decodedLog: LogWithDecodedArgs<LogFillContractEventArgs>) {
const args = decodedLog.args;
- const isUserMakerOrTaker = args.maker === this.userAddress ||
- args.taker === this.userAddress;
+ const isUserMakerOrTaker = args.maker === this._userAddress || args.taker === this._userAddress;
return isUserMakerOrTaker;
}
- private updateLatestFillsBlockIfNeeded(blockNumber: number) {
+ private _updateLatestFillsBlockIfNeeded(blockNumber: number) {
const isBlockPending = _.isNull(blockNumber);
if (!isBlockPending) {
// Hack: I've observed the behavior where a client won't register certain fill events
@@ -587,27 +602,39 @@ export class Blockchain {
// would still attempt to re-fetch events from the previous 50 blocks, but won't need to
// re-fetch all events in all blocks.
// TODO: Debug if this is a race condition, and apply a more precise fix
- const blockNumberToSet = blockNumber - BLOCK_NUMBER_BACK_TRACK < 0 ?
- 0 :
- blockNumber - BLOCK_NUMBER_BACK_TRACK;
- tradeHistoryStorage.setFillsLatestBlock(this.userAddress, this.networkId, blockNumberToSet);
+ const blockNumberToSet =
+ blockNumber - BLOCK_NUMBER_BACK_TRACK < 0 ? 0 : blockNumber - BLOCK_NUMBER_BACK_TRACK;
+ tradeHistoryStorage.setFillsLatestBlock(this._userAddress, this.networkId, blockNumberToSet);
}
}
- private async stopWatchingExchangeLogFillEventsAsync() {
- this.zeroEx.exchange.unsubscribeAll();
+ private _stopWatchingExchangeLogFillEvents(): void {
+ this._zeroEx.exchange.unsubscribeAll();
}
- private async getTokenRegistryTokensByAddressAsync(): Promise<TokenByAddress> {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
- const tokenRegistryTokens = await this.zeroEx.tokenRegistry.getTokensAsync();
+ private async _getTokenRegistryTokensByAddressAsync(): Promise<TokenByAddress> {
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ const tokenRegistryTokens = await this._zeroEx.tokenRegistry.getTokensAsync();
const tokenByAddress: TokenByAddress = {};
_.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => {
// HACK: For now we have a hard-coded list of iconUrls for the dummyTokens
// TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry
- const iconUrl = constants.iconUrlBySymbol[t.symbol];
+ const iconUrl = configs.ICON_URL_BY_SYMBOL[t.symbol];
+ // HACK: Temporarily we hijack the WETH addresses fetched from the tokenRegistry
+ // so that we can take our time with actually updating it. This ensures that when
+ // we deploy the new WETH page, everyone will re-fill their trackedTokens with the
+ // new canonical WETH.
+ // TODO: Remove this hack once we've updated the TokenRegistries
+ // Airtable task: https://airtable.com/tblFe0Q9JuKJPYbTn/viwsOG2Y97qdIeCIO/recv3VGmIorFzHBVz
+ let address = t.address;
+ if (configs.SHOULD_DEPRECATE_OLD_WETH_TOKEN && t.symbol === 'WETH') {
+ const newEtherTokenAddressIfExists = configs.NEW_WRAPPED_ETHERS[this.networkId];
+ if (!_.isUndefined(newEtherTokenAddressIfExists)) {
+ address = newEtherTokenAddressIfExists;
+ }
+ }
const token: Token = {
iconUrl,
- address: t.address,
+ address,
name: t.name,
symbol: t.symbol,
decimals: t.decimals,
@@ -618,8 +645,8 @@ export class Blockchain {
});
return tokenByAddress;
}
- private async onPageLoadInitFireAndForgetAsync() {
- await Blockchain.onPageLoadAsync(); // wait for page to load
+ private async _onPageLoadInitFireAndForgetAsync() {
+ await Blockchain._onPageLoadAsync(); // wait for page to load
// Hack: We need to know the networkId the injectedWeb3 is connected to (if it is defined) in
// order to properly instantiate the web3Wrapper. Since we must use the async call, we cannot
@@ -637,62 +664,63 @@ 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;
+ const provider = await Blockchain._getProviderAsync(injectedWeb3, networkIdIfExists);
+ const networkId = !_.isUndefined(networkIdIfExists)
+ ? networkIdIfExists
+ : configs.IS_MAINNET_ENABLED ? constants.NETWORK_ID_MAINNET : constants.NETWORK_ID_TESTNET;
const zeroExConfigs = {
networkId,
};
- this.zeroEx = new ZeroEx(provider, zeroExConfigs);
- this.updateProviderName(injectedWeb3);
+ this._zeroEx = new ZeroEx(provider, zeroExConfigs);
+ this._updateProviderName(injectedWeb3);
const shouldPollUserAddress = true;
- this.web3Wrapper = new Web3Wrapper(this.dispatcher, provider, networkId, shouldPollUserAddress);
- await this.postInstantiationOrUpdatingProviderZeroExAsync();
+ this._web3Wrapper = new Web3Wrapper(this._dispatcher, provider, networkId, shouldPollUserAddress);
+ await this._postInstantiationOrUpdatingProviderZeroExAsync();
}
// This method should always be run after instantiating or updating the provider
// of the ZeroEx instance.
- private async postInstantiationOrUpdatingProviderZeroExAsync() {
- utils.assert(!_.isUndefined(this.zeroEx), 'ZeroEx must be instantiated.');
- this.exchangeAddress = this.zeroEx.exchange.getContractAddress();
+ private async _postInstantiationOrUpdatingProviderZeroExAsync() {
+ utils.assert(!_.isUndefined(this._zeroEx), 'ZeroEx must be instantiated.');
+ this._exchangeAddress = this._zeroEx.exchange.getContractAddress();
}
- private updateProviderName(injectedWeb3: Web3) {
+ private _updateProviderName(injectedWeb3: Web3) {
const doesInjectedWeb3Exist = !_.isUndefined(injectedWeb3);
- const providerName = doesInjectedWeb3Exist ?
- Blockchain.getNameGivenProvider(injectedWeb3.currentProvider) :
- constants.PUBLIC_PROVIDER_NAME;
- this.dispatcher.updateInjectedProviderName(providerName);
- }
- private async fetchTokenInformationAsync() {
- utils.assert(!_.isUndefined(this.networkId),
- 'Cannot call fetchTokenInformationAsync if disconnected from Ethereum node');
+ const providerName = doesInjectedWeb3Exist
+ ? Blockchain._getNameGivenProvider(injectedWeb3.currentProvider)
+ : constants.PROVIDER_NAME_PUBLIC;
+ this._dispatcher.updateInjectedProviderName(providerName);
+ }
+ private async _fetchTokenInformationAsync() {
+ utils.assert(
+ !_.isUndefined(this.networkId),
+ 'Cannot call fetchTokenInformationAsync if disconnected from Ethereum node',
+ );
- this.dispatcher.updateBlockchainIsLoaded(false);
- this.dispatcher.clearTokenByAddress();
+ this._dispatcher.updateBlockchainIsLoaded(false);
+ this._dispatcher.clearTokenByAddress();
- const tokenRegistryTokensByAddress = await this.getTokenRegistryTokensByAddressAsync();
+ const tokenRegistryTokensByAddress = await this._getTokenRegistryTokensByAddressAsync();
// HACK: We need to fetch the userAddress here because otherwise we cannot save the
// tracked tokens in localStorage under the users address nor fetch the token
// balances and allowances and we need to do this in order not to trigger the blockchain
// loading dialog to show up twice. First to load the contracts, and second to load the
// balances and allowances.
- this.userAddress = await this.web3Wrapper.getFirstAccountIfExistsAsync();
- if (!_.isEmpty(this.userAddress)) {
- this.dispatcher.updateUserAddress(this.userAddress);
+ this._userAddress = await this._web3Wrapper.getFirstAccountIfExistsAsync();
+ if (!_.isEmpty(this._userAddress)) {
+ this._dispatcher.updateUserAddress(this._userAddress);
}
- let trackedTokensIfExists = trackedTokenStorage.getTrackedTokensIfExists(this.userAddress, this.networkId);
+ 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;
});
_.each(trackedTokensIfExists, token => {
- trackedTokenStorage.addTrackedTokenToUser(this.userAddress, this.networkId, token);
+ trackedTokenStorage.addTrackedTokenToUser(this._userAddress, this.networkId, token);
});
} else {
// Properly set all tokenRegistry tokens `isTracked` to true if they are in the existing trackedTokens array
@@ -703,22 +731,22 @@ export class Blockchain {
});
}
const allTokens = _.uniq([...tokenRegistryTokens, ...trackedTokensIfExists]);
- this.dispatcher.updateTokenByAddress(allTokens);
+ this._dispatcher.updateTokenByAddress(allTokens);
// Get balance/allowance for tracked tokens
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.updateBlockchainIsLoaded(true);
+ 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> {
+ private async _instantiateContractIfExistsAsync(artifact: any, address?: string): Promise<ContractInstance> {
const c = await contract(artifact);
- const providerObj = this.web3Wrapper.getProviderObj();
+ const providerObj = this._web3Wrapper.getProviderObj();
c.setProvider(providerObj);
const artifactNetworkConfigs = artifact.networks[this.networkId];
@@ -733,23 +761,21 @@ 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);
}
}
try {
- const contractInstance = _.isUndefined(address) ?
- await c.deployed() :
- await c.at(address);
+ const contractInstance = _.isUndefined(address) ? await c.deployed() : await c.at(address);
return contractInstance;
} catch (err) {
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);
}
}
}
diff --git a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
index 963bd4388..f555ca6b1 100644
--- a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
+++ b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
@@ -1,12 +1,12 @@
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 {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
+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';
interface BlockchainErrDialogProps {
blockchain: Blockchain;
@@ -31,127 +31,126 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp
const hasWalletAddress = this.props.userAddress !== '';
return (
<Dialog
- title={this.getTitle(hasWalletAddress)}
- titleStyle={{fontWeight: 100}}
+ title={this._getTitle(hasWalletAddress)}
+ titleStyle={{ fontWeight: 100 }}
actions={dialogActions}
open={this.props.isOpen}
- contentStyle={{width: 400}}
+ contentStyle={{ width: 400 }}
onRequestClose={this.props.toggleDialogFn.bind(this.props.toggleDialogFn, false)}
autoScrollBodyContent={true}
>
- <div className="pt2" style={{color: colors.grey700}}>
- {this.renderExplanation(hasWalletAddress)}
+ <div className="pt2" style={{ color: colors.grey700 }}>
+ {this._renderExplanation(hasWalletAddress)}
</div>
</Dialog>
);
}
- private getTitle(hasWalletAddress: boolean) {
- if (this.props.blockchainErr === BlockchainErrs.A_CONTRACT_NOT_DEPLOYED_ON_NETWORK) {
+ private _getTitle(hasWalletAddress: boolean) {
+ 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) {
- return this.renderContractsNotDeployedExplanation();
+ private _renderExplanation(hasWalletAddress: boolean) {
+ 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) {
- return this.renderDisconnectedFromNode();
+ return this._renderNoWalletFoundExplanation();
+ } else if (this.props.blockchainErr === BlockchainErrs.DisconnectedFromEthereumNode) {
+ return this._renderDisconnectedFromNode();
} else {
- return this.renderUnexpectedErrorExplanation();
+ return this._renderUnexpectedErrorExplanation();
}
}
- private renderDisconnectedFromNode() {
+ private _renderDisconnectedFromNode() {
return (
<div>
- You were disconnected from the backing Ethereum node.
- {' '}If using <a href={constants.METAMASK_CHROME_STORE_URL} target="_blank">
+ You were disconnected from the backing Ethereum node. 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
- {' '}the page. If using a locally hosted Ethereum node, make sure it's still running.
+ </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>
);
}
- private renderUnexpectedErrorExplanation() {
- return (
- <div>
- We encountered an unexpected error. Please try refreshing the page.
- </div>
- );
+ private _renderUnexpectedErrorExplanation() {
+ return <div>We encountered an unexpected error. Please try refreshing the page.</div>;
}
- private renderNoWalletFoundExplanation() {
+ private _renderNoWalletFoundExplanation() {
return (
<div>
<div>
- We were unable to access an Ethereum wallet you control. In order to interact
- {' '}with the 0x portal dApp,
- we need a way to interact with one of your Ethereum wallets.
- {' '}There are two easy ways you can enable us to do that:
+ We were unable to access an Ethereum wallet you control. In order to interact with the 0x portal
+ dApp, we need a way to interact with one of your Ethereum wallets. There are two easy ways you can
+ enable us to do that:
</div>
<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.
+ </a>{' '}
+ Chrome extension Ethereum wallet. Once installed and set up, refresh this page.
<div className="pt1">
- <span className="bold">Note:</span>
- {' '}If you already have Metamask installed, make sure it is unlocked.
+ <span className="bold">Note:</span> If you already have Metamask installed, make sure it is
+ unlocked.
</div>
</div>
<h4>Parity Signer</h4>
<div>
- The <a href={constants.PARITY_CHROME_STORE_URL} 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.'}
+ 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.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>
- {' '}If you have done one of the above steps and are still seeing this message,
- {' '}we might still be unable to retrieve an Ethereum address by calling `web3.eth.accounts`.
- {' '}Make sure you have created at least one Ethereum address.
+ <span className="bold">Note:</span> If you have done one of the above steps and are still seeing
+ this message, we might still be unable to retrieve an Ethereum address by calling
+ `web3.eth.accounts`. Make sure you have created at least one Ethereum address.
</div>
</div>
);
}
- private renderContractsNotDeployedExplanation() {
+ private _renderContractsNotDeployedExplanation() {
return (
<div>
<div>
- The 0x smart contracts are not deployed on the Ethereum network you are
- {' '}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}).` :
- `.`
- }
+ The 0x smart contracts are not deployed on the Ethereum network you are 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.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
- Chrome extension</a>, make sure to start your local Parity node with{' '}
- {configs.isMainnetEnabled ?
- '`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.'
- }
+ 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.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.'}
</div>
</div>
);
diff --git a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
index aba5b9faf..661cc1d8c 100644
--- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
+++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
@@ -1,14 +1,14 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
-import RadioButton from 'material-ui/RadioButton';
-import RadioButtonGroup from 'material-ui/RadioButton/RadioButtonGroup';
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';
+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';
+import { colors } from 'ts/utils/colors';
interface EthWethConversionDialogProps {
+ direction: Side;
onComplete: (direction: Side, value: BigNumber) => void;
onCancelled: () => void;
isOpen: boolean;
@@ -19,105 +19,129 @@ interface EthWethConversionDialogProps {
interface EthWethConversionDialogState {
value?: BigNumber;
- direction: Side;
shouldShowIncompleteErrs: boolean;
hasErrors: boolean;
}
-export class EthWethConversionDialog extends
- React.Component<EthWethConversionDialogProps, EthWethConversionDialogState> {
+export class EthWethConversionDialog extends React.Component<
+ EthWethConversionDialogProps,
+ EthWethConversionDialogState
+> {
constructor() {
super();
this.state = {
- direction: Side.deposit,
shouldShowIncompleteErrs: false,
- hasErrors: true,
+ hasErrors: false,
};
}
public render() {
const convertDialogActions = [
- <FlatButton
- key="cancel"
- label="Cancel"
- onTouchTap={this.onCancel.bind(this)}
- />,
- <FlatButton
- key="convert"
- label="Convert"
- primary={true}
- onTouchTap={this.onConvertClick.bind(this)}
- />,
+ <FlatButton key="cancel" label="Cancel" onTouchTap={this._onCancel.bind(this)} />,
+ <FlatButton key="convert" label="Convert" primary={true} onTouchTap={this._onConvertClick.bind(this)} />,
];
+ const title = this.props.direction === Side.Deposit ? 'Wrap ETH' : 'Unwrap WETH';
return (
<Dialog
- title="I want to convert"
- titleStyle={{fontWeight: 100}}
+ title={title}
+ titleStyle={{ fontWeight: 100 }}
actions={convertDialogActions}
+ contentStyle={{ width: 448 }}
open={this.props.isOpen}
>
- {this.renderConversionDialogBody()}
+ {this._renderConversionDialogBody()}
</Dialog>
);
}
- private renderConversionDialogBody() {
+ private _renderConversionDialogBody() {
+ 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;
+ return (
+ <div>
+ <div className="pb2">{explanation}</div>
+ <div className="mx-auto" style={{ maxWidth: 312 }}>
+ <div className="flex">
+ {this._renderCurrency(isWrappedVersion)}
+ <div style={{ paddingTop: 68 }}>
+ <i style={{ fontSize: 28, color: colors.darkBlue }} className="zmdi zmdi-arrow-right" />
+ </div>
+ {this._renderCurrency(!isWrappedVersion)}
+ </div>
+ <div className="pt2 mx-auto" style={{ width: 245 }}>
+ {this.props.direction === Side.Receive ? (
+ <TokenAmountInput
+ token={this.props.token}
+ tokenState={this.props.tokenState}
+ shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
+ shouldCheckBalance={true}
+ shouldCheckAllowance={false}
+ onChange={this._onValueChange.bind(this)}
+ amount={this.state.value}
+ onVisitBalancesPageClick={this.props.onCancelled}
+ />
+ ) : (
+ <EthAmountInput
+ balance={this.props.etherBalance}
+ amount={this.state.value}
+ onChange={this._onValueChange.bind(this)}
+ shouldCheckBalance={true}
+ shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
+ onVisitBalancesPageClick={this.props.onCancelled}
+ />
+ )}
+ <div className="pt1" style={{ fontSize: 12 }}>
+ <div className="left">1 ETH = 1 WETH</div>
+ {this.props.direction === Side.Receive && (
+ <div
+ className="right"
+ onClick={this._onMaxClick.bind(this)}
+ style={{
+ color: colors.darkBlue,
+ textDecoration: 'underline',
+ cursor: 'pointer',
+ }}
+ >
+ Max
+ </div>
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+ private _renderCurrency(isWrappedVersion: boolean) {
+ const name = isWrappedVersion ? 'Wrapped Ether' : 'Ether';
+ const iconUrl = isWrappedVersion ? '/images/token_icons/ether_erc20.png' : '/images/ether.png';
+ const symbol = isWrappedVersion ? 'WETH' : 'ETH';
return (
- <div className="mx-auto" style={{maxWidth: 300}}>
- <RadioButtonGroup
- className="pb1"
- defaultSelected={this.state.direction}
- name="conversionDirection"
- onChange={this.onConversionDirectionChange.bind(this)}
- >
- <RadioButton
- className="pb1"
- value={Side.deposit}
- label="Ether -> Ether Tokens"
- />
- <RadioButton
- value={Side.receive}
- label="Ether Tokens -> Ether"
- />
- </RadioButtonGroup>
- {this.state.direction === Side.receive ?
- <TokenAmountInput
- label="Amount to convert"
- token={this.props.token}
- tokenState={this.props.tokenState}
- shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
- shouldCheckBalance={true}
- shouldCheckAllowance={false}
- onChange={this.onValueChange.bind(this)}
- amount={this.state.value}
- onVisitBalancesPageClick={this.props.onCancelled}
- /> :
- <EthAmountInput
- label="Amount to convert"
- balance={this.props.etherBalance}
- amount={this.state.value}
- onChange={this.onValueChange.bind(this)}
- shouldCheckBalance={true}
- shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
- onVisitBalancesPageClick={this.props.onCancelled}
- />
- }
+ <div className="mx-auto pt2">
+ <div className="center" style={{ color: colors.darkBlue }}>
+ {name}
+ </div>
+ <div className="center py2">
+ <img src={iconUrl} style={{ width: 60 }} />
+ </div>
+ <div className="center" style={{ fontSize: 12 }}>
+ ({symbol})
+ </div>
</div>
);
}
- private onConversionDirectionChange(e: any, direction: Side) {
+ private _onMaxClick() {
this.setState({
- value: undefined,
- shouldShowIncompleteErrs: false,
- direction,
- hasErrors: true,
+ value: this.props.tokenState.balance,
});
}
- private onValueChange(isValid: boolean, amount?: BigNumber) {
+ private _onValueChange(isValid: boolean, amount?: BigNumber) {
this.setState({
value: amount,
hasErrors: !isValid,
});
}
- private onConvertClick() {
+ private _onConvertClick() {
if (this.state.hasErrors) {
this.setState({
shouldShowIncompleteErrs: true,
@@ -127,10 +151,10 @@ export class EthWethConversionDialog extends
this.setState({
value: undefined,
});
- this.props.onComplete(this.state.direction, value);
+ this.props.onComplete(this.props.direction, value);
}
}
- private onCancel() {
+ private _onCancel() {
this.setState({
value: undefined,
});
diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
index d3c95a011..60db93c52 100644
--- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
+++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
@@ -1,24 +1,18 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
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,
- TableHeader,
- TableHeaderColumn,
- TableRow,
- TableRowColumn,
-} from 'material-ui/Table';
+import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
import TextField from 'material-ui/TextField';
import * as React from 'react';
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 {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+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';
const VALID_ETHEREUM_DERIVATION_PATH_PREFIX = `44'/60'`;
@@ -52,58 +46,45 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
stepIndex: LedgerSteps.CONNECT,
userAddresses: [],
addressBalances: [],
- derivationPath: constants.DEFAULT_DERIVATION_PATH,
+ derivationPath: configs.DEFAULT_DERIVATION_PATH,
derivationErrMsg: '',
};
}
public render() {
const dialogActions = [
- <FlatButton
- key="ledgerConnectCancel"
- label="Cancel"
- onTouchTap={this.onClose.bind(this)}
- />,
+ <FlatButton key="ledgerConnectCancel" label="Cancel" onTouchTap={this._onClose.bind(this)} />,
];
- const dialogTitle = this.state.stepIndex === LedgerSteps.CONNECT ?
- 'Connect to your Ledger' :
- 'Select desired address';
+ const dialogTitle =
+ this.state.stepIndex === LedgerSteps.CONNECT ? 'Connect to your Ledger' : 'Select desired address';
return (
<Dialog
title={dialogTitle}
- titleStyle={{fontWeight: 100}}
+ titleStyle={{ fontWeight: 100 }}
actions={dialogActions}
open={this.props.isOpen}
- onRequestClose={this.onClose.bind(this)}
+ onRequestClose={this._onClose.bind(this)}
autoScrollBodyContent={true}
- bodyStyle={{paddingBottom: 0}}
+ bodyStyle={{ paddingBottom: 0 }}
>
- <div style={{color: colors.grey700, paddingTop: 1}}>
- {this.state.stepIndex === LedgerSteps.CONNECT &&
- this.renderConnectStep()
- }
- {this.state.stepIndex === LedgerSteps.SELECT_ADDRESS &&
- this.renderSelectAddressStep()
- }
+ <div style={{ color: colors.grey700, paddingTop: 1 }}>
+ {this.state.stepIndex === LedgerSteps.CONNECT && this._renderConnectStep()}
+ {this.state.stepIndex === LedgerSteps.SELECT_ADDRESS && this._renderSelectAddressStep()}
</div>
</Dialog>
);
}
- private renderConnectStep() {
+ private _renderConnectStep() {
return (
<div>
- <div className="h4 pt3">
- Follow these instructions before proceeding:
- </div>
+ <div className="h4 pt3">Follow these instructions before proceeding:</div>
<ol>
- <li className="pb1">
- Connect your Ledger Nano S & Open the Ethereum application
- </li>
- <li className="pb1">
- Verify that Browser Support is enabled in Settings
- </li>
+ <li className="pb1">Connect your Ledger Nano S & Open the Ethereum application</li>
+ <li className="pb1">Verify that Browser Support is enabled in Settings</li>
<li className="pb1">
If no Browser Support is found in settings, verify that you have{' '}
- <a href="https://www.ledgerwallet.com/apps/manager" target="_blank">Firmware >1.2</a>
+ <a href="https://www.ledgerwallet.com/apps/manager" target="_blank">
+ Firmware >1.2
+ </a>
</li>
</ol>
<div className="center pb3">
@@ -112,85 +93,74 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
labelReady="Connect to Ledger"
labelLoading="Connecting..."
labelComplete="Connected!"
- onClickAsyncFn={this.onConnectLedgerClickAsync.bind(this, true)}
+ onClickAsyncFn={this._onConnectLedgerClickAsync.bind(this, true)}
/>
- {this.state.didConnectFail &&
- <div className="pt2 left-align" style={{color: colors.red200}}>
+ {this.state.didConnectFail && (
+ <div className="pt2 left-align" style={{ color: colors.red200 }}>
Failed to connect. Follow the instructions and try again.
</div>
- }
+ )}
</div>
</div>
);
}
- private renderSelectAddressStep() {
+ private _renderSelectAddressStep() {
return (
<div>
<div>
- <Table
- bodyStyle={{height: 300}}
- onRowSelection={this.onAddressSelected.bind(this)}
- >
+ <Table bodyStyle={{ height: 300 }} onRowSelection={this._onAddressSelected.bind(this)}>
<TableHeader displaySelectAll={false}>
<TableRow>
<TableHeaderColumn colSpan={2}>Address</TableHeaderColumn>
<TableHeaderColumn>Balance</TableHeaderColumn>
</TableRow>
</TableHeader>
- <TableBody>
- {this.renderAddressTableRows()}
- </TableBody>
+ <TableBody>{this._renderAddressTableRows()}</TableBody>
</Table>
</div>
- <div className="flex pt2" style={{height: 100}}>
- <div className="overflow-hidden" style={{width: 180}}>
+ <div className="flex pt2" style={{ height: 100 }}>
+ <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}
- onChange={this.onDerivationPathChanged.bind(this)}
+ onChange={this._onDerivationPathChanged.bind(this)}
/>
</div>
- <div className="pl2" style={{paddingTop: 28}}>
+ <div className="pl2" style={{ paddingTop: 28 }}>
<LifeCycleRaisedButton
labelReady="Update"
labelLoading="Updating..."
labelComplete="Updated!"
- onClickAsyncFn={this.onFetchAddressesForDerivationPathAsync.bind(this, true)}
+ onClickAsyncFn={this._onFetchAddressesForDerivationPathAsync.bind(this)}
/>
</div>
</div>
</div>
);
}
- private renderAddressTableRows() {
+ private _renderAddressTableRows() {
const rows = _.map(this.state.userAddresses, (userAddress: string, i: number) => {
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';
const balanceString = `${balance.toString()} ${isKovanNetwork ? 'Kovan ' : ''}ETH`;
return (
- <TableRow key={userAddress} style={{height: 40}}>
+ <TableRow key={userAddress} style={{ height: 40 }}>
<TableRowColumn colSpan={2}>
- <div
- data-tip={true}
- data-for={addressTooltipId}
- >
+ <div data-tip={true} data-for={addressTooltipId}>
{userAddress}
</div>
<ReactTooltip id={addressTooltipId}>{userAddress}</ReactTooltip>
</TableRowColumn>
<TableRowColumn>
- <div
- data-tip={true}
- data-for={balanceTooltipId}
- >
+ <div data-tip={true} data-for={balanceTooltipId}>
{balanceString}
</div>
<ReactTooltip id={balanceTooltipId}>{balanceString}</ReactTooltip>
@@ -200,14 +170,14 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
});
return rows;
}
- private onClose() {
+ private _onClose() {
this.setState({
didConnectFail: false,
});
const isOpen = false;
this.props.toggleDialogFn(isOpen);
}
- private onAddressSelected(selectedRowIndexes: number[]) {
+ private _onAddressSelected(selectedRowIndexes: number[]) {
const selectedRowIndex = selectedRowIndexes[0];
this.props.blockchain.updateLedgerDerivationIndex(selectedRowIndex);
const selectedAddress = this.state.userAddresses[selectedRowIndex];
@@ -221,13 +191,15 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
const isOpen = false;
this.props.toggleDialogFn(isOpen);
}
- private async onFetchAddressesForDerivationPathAsync() {
+ private async _onFetchAddressesForDerivationPathAsync(): Promise<boolean> {
const currentlySetPath = this.props.blockchain.getLedgerDerivationPathIfExists();
+ let didSucceed;
if (currentlySetPath === this.state.derivationPath) {
- return;
+ didSucceed = true;
+ return didSucceed;
}
this.props.blockchain.updateLedgerDerivationPathIfExists(this.state.derivationPath);
- const didSucceed = await this.fetchAddressesAndBalancesAsync();
+ didSucceed = await this._fetchAddressesAndBalancesAsync();
if (!didSucceed) {
this.setState({
derivationErrMsg: 'Failed to connect to Ledger.',
@@ -235,11 +207,11 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
}
return didSucceed;
}
- private async fetchAddressesAndBalancesAsync() {
+ private async _fetchAddressesAndBalancesAsync() {
let userAddresses: string[];
const addressBalances: BigNumber[] = [];
try {
- userAddresses = await this.getUserAddressesAsync();
+ userAddresses = await this._getUserAddressesAsync();
for (const address of userAddresses) {
const balance = await this.props.blockchain.getBalanceInEthAsync(address);
addressBalances.push(balance);
@@ -257,7 +229,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
});
return true;
}
- private onDerivationPathChanged(e: any, derivationPath: string) {
+ private _onDerivationPathChanged(e: any, derivationPath: string) {
let derivationErrMsg = '';
if (!_.startsWith(derivationPath, VALID_ETHEREUM_DERIVATION_PATH_PREFIX)) {
derivationErrMsg = 'Must be valid Ethereum path.';
@@ -268,8 +240,8 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
derivationErrMsg,
});
}
- private async onConnectLedgerClickAsync() {
- const didSucceed = await this.fetchAddressesAndBalancesAsync();
+ private async _onConnectLedgerClickAsync() {
+ const didSucceed = await this._fetchAddressesAndBalancesAsync();
if (didSucceed) {
this.setState({
stepIndex: LedgerSteps.SELECT_ADDRESS,
@@ -277,7 +249,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
}
return didSucceed;
}
- private async getUserAddressesAsync(): Promise<string[]> {
+ private async _getUserAddressesAsync(): Promise<string[]> {
let userAddresses: string[];
userAddresses = await this.props.blockchain.getUserAccountsAsync();
diff --git a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
index 1d90624ee..3ecc454a0 100644
--- a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
+++ b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
@@ -1,8 +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 {constants} from 'ts/utils/constants';
+import { colors } from 'ts/utils/colors';
interface PortalDisclaimerDialogProps {
isOpen: boolean;
@@ -13,31 +12,23 @@ export function PortalDisclaimerDialog(props: PortalDisclaimerDialogProps) {
return (
<Dialog
title="0x Portal Disclaimer"
- titleStyle={{fontWeight: 100}}
- actions={[
- <FlatButton
- key="portalAgree"
- label="I Agree"
- onTouchTap={props.onToggleDialog.bind(this)}
- />,
- ]}
+ titleStyle={{ fontWeight: 100 }}
+ actions={[<FlatButton key="portalAgree" label="I Agree" onTouchTap={props.onToggleDialog} />]}
open={props.isOpen}
- onRequestClose={props.onToggleDialog.bind(this)}
+ onRequestClose={props.onToggleDialog}
autoScrollBodyContent={true}
modal={true}
>
- <div className="pt2" style={{color: colors.grey700}}>
+ <div className="pt2" style={{ color: colors.grey700 }}>
<div>
- 0x Portal is a free software-based tool intended to help users to
- buy and sell ERC20-compatible blockchain tokens through the 0x protocol
- on a purely peer-to-peer basis. 0x portal is not a regulated marketplace,
- exchange or intermediary of any kind, and therefore, you should only use
- 0x portal to exchange tokens that are not securities, commodity interests,
- or any other form of regulated instrument. 0x has not attempted to screen
- or otherwise limit the tokens that you may enter in 0x Portal. By clicking
- “I Agree” below, you understand that you are solely responsible for using 0x
- Portal and buying and selling tokens using 0x Portal in compliance with all
- applicable laws and regulations.
+ 0x Portal is a free software-based tool intended to help users to buy and sell ERC20-compatible
+ blockchain tokens through the 0x protocol on a purely peer-to-peer basis. 0x portal is not a
+ regulated marketplace, exchange or intermediary of any kind, and therefore, you should only use 0x
+ portal to exchange tokens that are not securities, commodity interests, or any other form of
+ regulated instrument. 0x has not attempted to screen or otherwise limit the tokens that you may
+ enter in 0x Portal. By clicking “I Agree” below, you understand that you are solely responsible for
+ using 0x Portal and buying and selling tokens using 0x Portal in compliance with all applicable laws
+ and regulations.
</div>
</div>
</Dialog>
diff --git a/packages/website/ts/components/dialogs/send_dialog.tsx b/packages/website/ts/components/dialogs/send_dialog.tsx
index 31afc3386..b3dbce598 100644
--- a/packages/website/ts/components/dialogs/send_dialog.tsx
+++ b/packages/website/ts/components/dialogs/send_dialog.tsx
@@ -1,14 +1,11 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
-import RadioButton from 'material-ui/RadioButton';
-import RadioButtonGroup from 'material-ui/RadioButton/RadioButtonGroup';
import * as React from 'react';
-import {AddressInput} from 'ts/components/inputs/address_input';
-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';
+import { AddressInput } from 'ts/components/inputs/address_input';
+import { TokenAmountInput } from 'ts/components/inputs/token_amount_input';
+import { Token, TokenState } from 'ts/types';
interface SendDialogProps {
onComplete: (recipient: string, value: BigNumber) => void;
@@ -36,37 +33,33 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState
}
public render() {
const transferDialogActions = [
- <FlatButton
- key="cancelTransfer"
- label="Cancel"
- onTouchTap={this.onCancel.bind(this)}
- />,
+ <FlatButton key="cancelTransfer" label="Cancel" onTouchTap={this._onCancel.bind(this)} />,
<FlatButton
key="sendTransfer"
- disabled={this.hasErrors()}
+ disabled={this._hasErrors()}
label="Send"
primary={true}
- onTouchTap={this.onSendClick.bind(this)}
+ onTouchTap={this._onSendClick.bind(this)}
/>,
];
return (
<Dialog
title="I want to send"
- titleStyle={{fontWeight: 100}}
+ titleStyle={{ fontWeight: 100 }}
actions={transferDialogActions}
open={this.props.isOpen}
>
- {this.renderSendDialogBody()}
+ {this._renderSendDialogBody()}
</Dialog>
);
}
- private renderSendDialogBody() {
+ private _renderSendDialogBody() {
return (
- <div className="mx-auto" style={{maxWidth: 300}}>
- <div style={{height: 80}}>
+ <div className="mx-auto" style={{ maxWidth: 300 }}>
+ <div style={{ height: 80 }}>
<AddressInput
initialAddress={this.state.recipient}
- updateAddress={this.onRecipientChange.bind(this)}
+ updateAddress={this._onRecipientChange.bind(this)}
isRequired={true}
label={'Recipient address'}
hintText={'Address'}
@@ -79,27 +72,27 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState
shouldShowIncompleteErrs={this.state.shouldShowIncompleteErrs}
shouldCheckBalance={true}
shouldCheckAllowance={false}
- onChange={this.onValueChange.bind(this)}
+ onChange={this._onValueChange.bind(this)}
amount={this.state.value}
onVisitBalancesPageClick={this.props.onCancelled}
/>
</div>
);
}
- private onRecipientChange(recipient?: string) {
+ private _onRecipientChange(recipient?: string) {
this.setState({
shouldShowIncompleteErrs: false,
recipient,
});
}
- private onValueChange(isValid: boolean, amount?: BigNumber) {
+ private _onValueChange(isValid: boolean, amount?: BigNumber) {
this.setState({
isAmountValid: isValid,
value: amount,
});
}
- private onSendClick() {
- if (this.hasErrors()) {
+ private _onSendClick() {
+ if (this._hasErrors()) {
this.setState({
shouldShowIncompleteErrs: true,
});
@@ -112,15 +105,13 @@ export class SendDialog extends React.Component<SendDialogProps, SendDialogState
this.props.onComplete(this.state.recipient, value);
}
}
- private onCancel() {
+ private _onCancel() {
this.setState({
value: undefined,
});
this.props.onCancelled();
}
- private hasErrors() {
- return _.isUndefined(this.state.recipient) ||
- _.isUndefined(this.state.value) ||
- !this.state.isAmountValid;
+ private _hasErrors() {
+ return _.isUndefined(this.state.recipient) || _.isUndefined(this.state.value) || !this.state.isAmountValid;
}
}
diff --git a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
index 70c7d1ab6..3f29d46f8 100644
--- a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
+++ b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
@@ -1,14 +1,12 @@
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 {TrackTokenConfirmation} from 'ts/components/track_token_confirmation';
-import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {Token, TokenByAddress} from 'ts/types';
-import {constants} from 'ts/utils/constants';
+import { Blockchain } from 'ts/blockchain';
+import { TrackTokenConfirmation } from 'ts/components/track_token_confirmation';
+import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { Token, TokenByAddress } from 'ts/types';
interface TrackTokenConfirmationDialogProps {
tokens: Token[];
@@ -25,8 +23,10 @@ interface TrackTokenConfirmationDialogState {
isAddingTokenToTracked: boolean;
}
-export class TrackTokenConfirmationDialog extends
- React.Component<TrackTokenConfirmationDialogProps, TrackTokenConfirmationDialogState> {
+export class TrackTokenConfirmationDialog extends React.Component<
+ TrackTokenConfirmationDialogProps,
+ TrackTokenConfirmationDialogState
+> {
constructor(props: TrackTokenConfirmationDialogProps) {
super(props);
this.state = {
@@ -38,17 +38,17 @@ export class TrackTokenConfirmationDialog extends
return (
<Dialog
title="Tracking confirmation"
- titleStyle={{fontWeight: 100}}
+ titleStyle={{ fontWeight: 100 }}
actions={[
<FlatButton
key="trackNo"
label="No"
- onTouchTap={this.onTrackConfirmationRespondedAsync.bind(this, false)}
+ onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)}
/>,
<FlatButton
key="trackYes"
label="Yes"
- onTouchTap={this.onTrackConfirmationRespondedAsync.bind(this, true)}
+ onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)}
/>,
]}
open={this.props.isOpen}
@@ -66,7 +66,7 @@ export class TrackTokenConfirmationDialog extends
</Dialog>
);
}
- private async onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) {
+ private async _onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) {
if (!didUserAcceptTracking) {
this.props.onToggleDialog(didUserAcceptTracking);
return;
@@ -75,16 +75,17 @@ 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);
this.props.dispatcher.updateTokenByAddress([newTokenEntry]);
- const [
- balance,
- allowance,
- ] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync(token.address);
+ const [balance, allowance] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync(
+ token.address,
+ );
this.props.dispatcher.updateTokenStateByAddress({
[token.address]: {
balance,
diff --git a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx
index 09c32c997..098e3e26d 100644
--- a/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx
+++ b/packages/website/ts/components/dialogs/u2f_not_supported_dialog.tsx
@@ -1,8 +1,8 @@
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {constants} from 'ts/utils/constants';
+import { colors } from 'ts/utils/colors';
+import { constants } from 'ts/utils/constants';
interface U2fNotSupportedDialogProps {
isOpen: boolean;
@@ -13,24 +13,16 @@ export function U2fNotSupportedDialog(props: U2fNotSupportedDialogProps) {
return (
<Dialog
title="U2F Not Supported"
- titleStyle={{fontWeight: 100}}
- actions={[
- <FlatButton
- key="u2fNo"
- label="Ok"
- onTouchTap={props.onToggleDialog.bind(this)}
- />,
- ]}
+ titleStyle={{ fontWeight: 100 }}
+ actions={[<FlatButton key="u2fNo" label="Ok" onTouchTap={props.onToggleDialog.bind(this)} />]}
open={props.isOpen}
onRequestClose={props.onToggleDialog.bind(this)}
autoScrollBodyContent={true}
>
- <div className="pt2" style={{color: colors.grey700}}>
+ <div className="pt2" style={{ color: colors.grey700 }}>
<div>
- It looks like your browser does not support U2F connections
- required for us to communicate with your hardware wallet.
- Please use a browser that supports U2F connections and try
- again.
+ It looks like your browser does not support U2F connections required for us to communicate with your
+ hardware wallet. Please use a browser that supports U2F connections and try again.
</div>
<div>
<ul>
@@ -39,9 +31,9 @@ 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'}}
+ style={{ textDecoration: 'underline' }}
>
this extension
</a>.
diff --git a/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx
new file mode 100644
index 000000000..9e91ff12d
--- /dev/null
+++ b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx
@@ -0,0 +1,33 @@
+import Dialog from 'material-ui/Dialog';
+import FlatButton from 'material-ui/FlatButton';
+import { colors } from 'material-ui/styles';
+import * as React from 'react';
+
+interface WrappedEthSectionNoticeDialogProps {
+ isOpen: boolean;
+ onToggleDialog: () => void;
+}
+
+export function WrappedEthSectionNoticeDialog(props: WrappedEthSectionNoticeDialogProps) {
+ return (
+ <Dialog
+ title="Dedicated Wrapped Ether Section"
+ titleStyle={{ fontWeight: 100 }}
+ actions={[
+ <FlatButton key="acknowledgeWrapEthSection" label="Sounds good" onTouchTap={props.onToggleDialog} />,
+ ]}
+ open={props.isOpen}
+ onRequestClose={props.onToggleDialog}
+ autoScrollBodyContent={true}
+ modal={true}
+ >
+ <div className="pt2" style={{ color: colors.grey700 }}>
+ <div>
+ We have recently updated the Wrapped Ether token (WETH) used by 0x Portal. Don't worry, unwrapping
+ Ether tied to the old Wrapped Ether token can be done at any time by clicking on the "Wrap ETH"
+ section in the menu to the left.
+ </div>
+ </div>
+ </Dialog>
+ );
+}
diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx
index a83b1543f..300e71f1f 100644
--- a/packages/website/ts/components/eth_weth_conversion_button.tsx
+++ b/packages/website/ts/components/eth_weth_conversion_button.tsx
@@ -1,23 +1,26 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
-import {Blockchain} from 'ts/blockchain';
-import {EthWethConversionDialog} from 'ts/components/dialogs/eth_weth_conversion_dialog';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {BlockchainCallErrs, Side, Token, TokenState} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {errorReporter} from 'ts/utils/error_reporter';
-import {utils} from 'ts/utils/utils';
+import { Blockchain } from 'ts/blockchain';
+import { EthWethConversionDialog } from 'ts/components/dialogs/eth_weth_conversion_dialog';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { BlockchainCallErrs, Side, Token, TokenState } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { errorReporter } from 'ts/utils/error_reporter';
+import { utils } from 'ts/utils/utils';
interface EthWethConversionButtonProps {
+ direction: Side;
ethToken: Token;
ethTokenState: TokenState;
dispatcher: Dispatcher;
blockchain: Blockchain;
userEtherBalance: BigNumber;
- onError: () => void;
+ isOutdatedWrappedEther: boolean;
+ onConversionSuccessful?: () => void;
+ isDisabled?: boolean;
}
interface EthWethConversionButtonState {
@@ -25,8 +28,14 @@ interface EthWethConversionButtonState {
isEthConversionHappening: boolean;
}
-export class EthWethConversionButton extends
- React.Component<EthWethConversionButtonProps, EthWethConversionButtonState> {
+export class EthWethConversionButton extends React.Component<
+ EthWethConversionButtonProps,
+ EthWethConversionButtonState
+> {
+ public static defaultProps: Partial<EthWethConversionButtonProps> = {
+ isDisabled: false,
+ onConversionSuccessful: _.noop,
+ };
public constructor(props: EthWethConversionButtonProps) {
super(props);
this.state = {
@@ -35,20 +44,30 @@ export class EthWethConversionButton extends
};
}
public render() {
- const labelStyle = this.state.isEthConversionHappening ? {fontSize: 10} : {};
+ const labelStyle = this.state.isEthConversionHappening ? { fontSize: 10 } : {};
+ let callToActionLabel;
+ let inProgressLabel;
+ if (this.props.direction === Side.Deposit) {
+ callToActionLabel = 'Wrap';
+ inProgressLabel = 'Wrapping...';
+ } else {
+ callToActionLabel = 'Unwrap';
+ inProgressLabel = 'Unwrapping...';
+ }
return (
<div>
<RaisedButton
- style={{width: '100%'}}
+ style={{ width: '100%' }}
labelStyle={labelStyle}
- disabled={this.state.isEthConversionHappening}
- label={this.state.isEthConversionHappening ? 'Converting...' : 'Convert'}
- onClick={this.toggleConversionDialog.bind(this)}
+ disabled={this.props.isDisabled || this.state.isEthConversionHappening}
+ label={this.state.isEthConversionHappening ? inProgressLabel : callToActionLabel}
+ onClick={this._toggleConversionDialog.bind(this)}
/>
<EthWethConversionDialog
+ direction={this.props.direction}
isOpen={this.state.isEthConversionDialogVisible}
- onComplete={this.onConversionAmountSelectedAsync.bind(this)}
- onCancelled={this.toggleConversionDialog.bind(this)}
+ onComplete={this._onConversionAmountSelectedAsync.bind(this)}
+ onCancelled={this._toggleConversionDialog.bind(this)}
etherBalance={this.props.userEtherBalance}
token={this.props.ethToken}
tokenState={this.props.ethTokenState}
@@ -56,41 +75,48 @@ export class EthWethConversionButton extends
</div>
);
}
- private toggleConversionDialog() {
+ private _toggleConversionDialog() {
this.setState({
isEthConversionDialogVisible: !this.state.isEthConversionDialogVisible,
});
}
- private async onConversionAmountSelectedAsync(direction: Side, value: BigNumber) {
+ private async _onConversionAmountSelectedAsync(direction: Side, value: BigNumber) {
this.setState({
isEthConversionHappening: true,
});
- this.toggleConversionDialog();
+ this._toggleConversionDialog();
const token = this.props.ethToken;
const tokenState = this.props.ethTokenState;
let balance = tokenState.balance;
try {
- if (direction === Side.deposit) {
- await this.props.blockchain.convertEthToWrappedEthTokensAsync(value);
- const ethAmount = ZeroEx.toUnitAmount(value, constants.ETH_DECIMAL_PLACES);
- this.props.dispatcher.showFlashMessage(`Successfully converted ${ethAmount.toString()} ETH to WETH`);
+ if (direction === Side.Deposit) {
+ await this.props.blockchain.convertEthToWrappedEthTokensAsync(token.address, value);
+ 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 {
- await this.props.blockchain.convertWrappedEthTokensToEthAsync(value);
+ await this.props.blockchain.convertWrappedEthTokensToEthAsync(token.address, value);
const tokenAmount = ZeroEx.toUnitAmount(value, token.decimals);
- this.props.dispatcher.showFlashMessage(`Successfully converted ${tokenAmount.toString()} WETH to ETH`);
+ this.props.dispatcher.showFlashMessage(`Successfully unwrapped ${tokenAmount.toString()} WETH to ETH`);
balance = balance.minus(value);
}
- this.props.dispatcher.replaceTokenBalanceByAddress(token.address, balance);
+ if (!this.props.isOutdatedWrappedEther) {
+ this.props.dispatcher.replaceTokenBalanceByAddress(token.address, balance);
+ }
+ this.props.onConversionSuccessful();
} catch (err) {
- const errMsg = '' + err;
- if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) {
+ const errMsg = `${err}`;
+ 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);
+ 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);
await errorReporter.reportAsync(err);
- this.props.onError();
}
}
this.setState({
diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx
new file mode 100644
index 000000000..d074ec787
--- /dev/null
+++ b/packages/website/ts/components/eth_wrappers.tsx
@@ -0,0 +1,374 @@
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
+import * as _ from 'lodash';
+import Divider from 'material-ui/Divider';
+import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
+import * as moment from 'moment';
+import * as React from 'react';
+import ReactTooltip = require('react-tooltip');
+import { Blockchain } from 'ts/blockchain';
+import { EthWethConversionButton } from 'ts/components/eth_weth_conversion_button';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import {
+ EtherscanLinkSuffixes,
+ OutdatedWrappedEtherByNetworkId,
+ Side,
+ Token,
+ TokenByAddress,
+ 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 ICON_DIMENSION = 40;
+const ETHER_ICON_PATH = '/images/ether.png';
+const OUTDATED_WETH_ICON_PATH = '/images/wrapped_eth_gray.png';
+
+interface OutdatedWETHAddressToIsStateLoaded {
+ [address: string]: boolean;
+}
+interface OutdatedWETHStateByAddress {
+ [address: string]: TokenState;
+}
+
+interface EthWrappersProps {
+ networkId: number;
+ blockchain: Blockchain;
+ dispatcher: Dispatcher;
+ tokenByAddress: TokenByAddress;
+ tokenStateByAddress: TokenStateByAddress;
+ userAddress: string;
+ userEtherBalance: BigNumber;
+}
+
+interface EthWrappersState {
+ outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded;
+ outdatedWETHStateByAddress: OutdatedWETHStateByAddress;
+}
+
+export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersState> {
+ constructor(props: EthWrappersProps) {
+ super(props);
+ const outdatedWETHAddresses = this._getOutdatedWETHAddresses();
+ const outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded = {};
+ const outdatedWETHStateByAddress: OutdatedWETHStateByAddress = {};
+ _.each(outdatedWETHAddresses, outdatedWETHAddress => {
+ outdatedWETHAddressToIsStateLoaded[outdatedWETHAddress] = false;
+ outdatedWETHStateByAddress[outdatedWETHAddress] = {
+ balance: new BigNumber(0),
+ allowance: new BigNumber(0),
+ };
+ });
+ this.state = {
+ outdatedWETHAddressToIsStateLoaded,
+ outdatedWETHStateByAddress,
+ };
+ }
+ public componentDidMount() {
+ window.scrollTo(0, 0);
+ // tslint:disable-next-line:no-floating-promises
+ this._fetchOutdatedWETHStateAsync();
+ }
+ public render() {
+ 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, constants.DECIMAL_PLACES_ETH);
+ const isBidirectional = true;
+ const etherscanUrl = utils.getEtherScanLinkIfExists(
+ etherToken.address,
+ this.props.networkId,
+ EtherscanLinkSuffixes.Address,
+ );
+ const tokenLabel = this._renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH);
+ return (
+ <div className="clearfix lg-px4 md-px4 sm-px2" style={{ minHeight: 600 }}>
+ <div className="relative">
+ <h3>ETH Wrapper</h3>
+ <div className="absolute" style={{ top: 0, right: 0 }}>
+ <a target="_blank" href={constants.URL_WETH_IO} style={{ color: colors.grey }}>
+ <div className="flex">
+ <div>About Wrapped ETH</div>
+ <div className="pl1">
+ <i className="zmdi zmdi-open-in-new" />
+ </div>
+ </div>
+ </a>
+ </div>
+ </div>
+ <Divider />
+ <div>
+ <div className="py2">Wrap ETH into an ERC20-compliant Ether token. 1 ETH = 1 WETH.</div>
+ <div>
+ <Table selectable={false} style={{ backgroundColor: colors.grey50 }}>
+ <TableHeader displaySelectAll={false} adjustForCheckbox={false}>
+ <TableRow>
+ <TableHeaderColumn>ETH Token</TableHeaderColumn>
+ <TableHeaderColumn>Balance</TableHeaderColumn>
+ <TableHeaderColumn className="center">
+ {this._renderActionColumnTitle(isBidirectional)}
+ </TableHeaderColumn>
+ </TableRow>
+ </TableHeader>
+ <TableBody displayRowCheckbox={false}>
+ <TableRow key="ETH">
+ <TableRowColumn className="py1">
+ <div className="flex">
+ <img
+ style={{
+ width: ICON_DIMENSION,
+ height: ICON_DIMENSION,
+ }}
+ src={ETHER_ICON_PATH}
+ />
+ <div className="ml2 sm-hide xs-hide" style={{ marginTop: 12 }}>
+ ETH
+ </div>
+ </div>
+ </TableRowColumn>
+ <TableRowColumn>
+ {this.props.userEtherBalance.toFixed(PRECISION)} ETH
+ </TableRowColumn>
+ <TableRowColumn>
+ <EthWethConversionButton
+ isOutdatedWrappedEther={false}
+ direction={Side.Deposit}
+ ethToken={etherToken}
+ ethTokenState={etherTokenState}
+ dispatcher={this.props.dispatcher}
+ blockchain={this.props.blockchain}
+ userEtherBalance={this.props.userEtherBalance}
+ />
+ </TableRowColumn>
+ </TableRow>
+ <TableRow key="WETH">
+ <TableRowColumn className="py1">
+ {this._renderTokenLink(tokenLabel, etherscanUrl)}
+ </TableRowColumn>
+ <TableRowColumn>{wethBalance.toFixed(PRECISION)} WETH</TableRowColumn>
+ <TableRowColumn>
+ <EthWethConversionButton
+ isOutdatedWrappedEther={false}
+ direction={Side.Receive}
+ ethToken={etherToken}
+ ethTokenState={etherTokenState}
+ dispatcher={this.props.dispatcher}
+ blockchain={this.props.blockchain}
+ userEtherBalance={this.props.userEtherBalance}
+ />
+ </TableRowColumn>
+ </TableRow>
+ </TableBody>
+ </Table>
+ </div>
+ </div>
+ <div>
+ <h4>Outdated WETH</h4>
+ <Divider />
+ <div className="pt2" style={{ lineHeight: 1.5 }}>
+ The{' '}
+ <a href="https://blog.0xproject.com/canonical-weth-a9aa7d0279dd" target="_blank">
+ canonical WETH
+ </a>{' '}
+ contract is updated when necessary. Unwrap outdated WETH in order to
 retrieve your ETH and move
+ it to the updated WETH token.
+ </div>
+ <div>
+ <Table selectable={false} style={{ backgroundColor: colors.grey50 }}>
+ <TableHeader displaySelectAll={false} adjustForCheckbox={false}>
+ <TableRow>
+ <TableHeaderColumn>WETH Version</TableHeaderColumn>
+ <TableHeaderColumn>Balance</TableHeaderColumn>
+ <TableHeaderColumn className="center">
+ {this._renderActionColumnTitle(!isBidirectional)}
+ </TableHeaderColumn>
+ </TableRow>
+ </TableHeader>
+ <TableBody displayRowCheckbox={false}>
+ {this._renderOutdatedWeths(etherToken, etherTokenState)}
+ </TableBody>
+ </Table>
+ </div>
+ </div>
+ </div>
+ );
+ }
+ private _renderActionColumnTitle(isBidirectional: boolean) {
+ let iconClass = 'zmdi-long-arrow-right';
+ let leftSymbol = 'WETH';
+ let rightSymbol = 'ETH';
+ if (isBidirectional) {
+ iconClass = 'zmdi-swap';
+ leftSymbol = 'ETH';
+ rightSymbol = 'WETH';
+ }
+ return (
+ <div className="flex mx-auto" style={{ width: 85 }}>
+ <div style={{ paddingTop: 3 }}>{leftSymbol}</div>
+ <div className="px1">
+ <i style={{ fontSize: 18 }} className={`zmdi ${iconClass}`} />
+ </div>
+ <div style={{ paddingTop: 3 }}>{rightSymbol}</div>
+ </div>
+ );
+ }
+ private _renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) {
+ const rows = _.map(
+ configs.OUTDATED_WRAPPED_ETHERS,
+ (outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => {
+ const outdatedWETHIfExists = outdatedWETHByNetworkId[this.props.networkId];
+ if (_.isUndefined(outdatedWETHIfExists)) {
+ return null; // noop
+ }
+ const timestampMsRange = outdatedWETHIfExists.timestampMsRange;
+ let dateRange: string;
+ if (!_.isUndefined(timestampMsRange)) {
+ const startMoment = moment(timestampMsRange.startTimestampMs);
+ const endMoment = moment(timestampMsRange.endTimestampMs);
+ dateRange = `${startMoment.format(DATE_FORMAT)}-${endMoment.format(DATE_FORMAT)}`;
+ } else {
+ dateRange = '-';
+ }
+ const outdatedEtherToken = {
+ ...etherToken,
+ address: outdatedWETHIfExists.address,
+ };
+ const isStateLoaded = this.state.outdatedWETHAddressToIsStateLoaded[outdatedWETHIfExists.address];
+ const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETHIfExists.address];
+ const balanceInEthIfExists = isStateLoaded
+ ? ZeroEx.toUnitAmount(outdatedEtherTokenState.balance, constants.DECIMAL_PLACES_ETH).toFixed(
+ PRECISION,
+ )
+ : undefined;
+ const onConversionSuccessful = this._onOutdatedConversionSuccessfulAsync.bind(
+ this,
+ outdatedWETHIfExists.address,
+ );
+ const etherscanUrl = utils.getEtherScanLinkIfExists(
+ outdatedWETHIfExists.address,
+ this.props.networkId,
+ EtherscanLinkSuffixes.Address,
+ );
+ const tokenLabel = this._renderToken(dateRange, outdatedEtherToken.address, OUTDATED_WETH_ICON_PATH);
+ return (
+ <TableRow key={`weth-${outdatedWETHIfExists.address}`}>
+ <TableRowColumn className="py1">
+ {this._renderTokenLink(tokenLabel, etherscanUrl)}
+ </TableRowColumn>
+ <TableRowColumn>
+ {isStateLoaded ? (
+ `${balanceInEthIfExists} WETH`
+ ) : (
+ <i className="zmdi zmdi-spinner zmdi-hc-spin" />
+ )}
+ </TableRowColumn>
+ <TableRowColumn>
+ <EthWethConversionButton
+ isDisabled={!isStateLoaded}
+ isOutdatedWrappedEther={true}
+ direction={Side.Receive}
+ ethToken={outdatedEtherToken}
+ ethTokenState={outdatedEtherTokenState}
+ dispatcher={this.props.dispatcher}
+ blockchain={this.props.blockchain}
+ userEtherBalance={this.props.userEtherBalance}
+ onConversionSuccessful={onConversionSuccessful}
+ />
+ </TableRowColumn>
+ </TableRow>
+ );
+ },
+ );
+ return rows;
+ }
+ private _renderTokenLink(tokenLabel: React.ReactNode, etherscanUrl: string) {
+ return (
+ <span>
+ {_.isUndefined(etherscanUrl) ? (
+ tokenLabel
+ ) : (
+ <a href={etherscanUrl} target="_blank" style={{ textDecoration: 'none' }}>
+ {tokenLabel}
+ </a>
+ )}
+ </span>
+ );
+ }
+ private _renderToken(name: string, address: string, imgPath: string) {
+ const tooltipId = `tooltip-${address}`;
+ return (
+ <div className="flex">
+ <img style={{ width: ICON_DIMENSION, height: ICON_DIMENSION }} src={imgPath} />
+ <div className="ml2 sm-hide xs-hide" style={{ marginTop: 12 }}>
+ <span data-tip={true} data-for={tooltipId}>
+ {name}
+ </span>
+ <ReactTooltip id={tooltipId}>{address}</ReactTooltip>
+ </div>
+ </div>
+ );
+ }
+ private async _onOutdatedConversionSuccessfulAsync(outdatedWETHAddress: string) {
+ this.setState({
+ outdatedWETHAddressToIsStateLoaded: {
+ ...this.state.outdatedWETHAddressToIsStateLoaded,
+ [outdatedWETHAddress]: false,
+ },
+ });
+ const [balance, allowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync(
+ this.props.userAddress,
+ outdatedWETHAddress,
+ );
+ this.setState({
+ outdatedWETHAddressToIsStateLoaded: {
+ ...this.state.outdatedWETHAddressToIsStateLoaded,
+ [outdatedWETHAddress]: true,
+ },
+ outdatedWETHStateByAddress: {
+ ...this.state.outdatedWETHStateByAddress,
+ [outdatedWETHAddress]: {
+ balance,
+ allowance,
+ },
+ },
+ });
+ }
+ private async _fetchOutdatedWETHStateAsync() {
+ const outdatedWETHAddresses = this._getOutdatedWETHAddresses();
+ const outdatedWETHAddressToIsStateLoaded: OutdatedWETHAddressToIsStateLoaded = {};
+ const outdatedWETHStateByAddress: OutdatedWETHStateByAddress = {};
+ for (const address of outdatedWETHAddresses) {
+ const [balance, allowance] = await this.props.blockchain.getTokenBalanceAndAllowanceAsync(
+ this.props.userAddress,
+ address,
+ );
+ outdatedWETHStateByAddress[address] = {
+ balance,
+ allowance,
+ };
+ outdatedWETHAddressToIsStateLoaded[address] = true;
+ }
+ this.setState({
+ outdatedWETHStateByAddress,
+ outdatedWETHAddressToIsStateLoaded,
+ });
+ }
+ private _getOutdatedWETHAddresses(): string[] {
+ const outdatedWETHAddresses = _.compact(
+ _.map(configs.OUTDATED_WRAPPED_ETHERS, outdatedWrappedEtherByNetwork => {
+ const outdatedWrappedEtherIfExists = outdatedWrappedEtherByNetwork[this.props.networkId];
+ if (_.isUndefined(outdatedWrappedEtherIfExists)) {
+ return undefined;
+ }
+ const address = outdatedWrappedEtherIfExists.address;
+ return address;
+ }),
+ );
+ return outdatedWETHAddresses;
+ }
+} // tslint:disable:max-file-line-count
diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx
index 388c72d8e..1a150e9ee 100644
--- a/packages/website/ts/components/fill_order.tsx
+++ b/packages/website/ts/components/fill_order.tsx
@@ -1,46 +1,29 @@
-import {Order as ZeroExOrder, ZeroEx} from '0x.js';
+import { Order as ZeroExOrder, ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
import * as accounting from 'accounting';
-import BigNumber from 'bignumber.js';
import * as _ from 'lodash';
-import {Card, CardHeader, CardText} from 'material-ui/Card';
+import { Card, CardHeader, CardText } from 'material-ui/Card';
import Divider from 'material-ui/Divider';
-import Paper from 'material-ui/Paper';
import RaisedButton from 'material-ui/RaisedButton';
-import TextField from 'material-ui/TextField';
-import * as moment from 'moment';
import * as React from 'react';
-import {Link} from 'react-router-dom';
-import {Blockchain} from 'ts/blockchain';
-import {TrackTokenConfirmationDialog} from 'ts/components/dialogs/track_token_confirmation_dialog';
-import {FillOrderJSON} from 'ts/components/fill_order_json';
-import {FillWarningDialog} from 'ts/components/fill_warning_dialog';
-import {TokenAmountInput} from 'ts/components/inputs/token_amount_input';
-import {Alert} from 'ts/components/ui/alert';
-import {EthereumAddress} from 'ts/components/ui/ethereum_address';
-import {Identicon} from 'ts/components/ui/identicon';
-import {VisualOrder} from 'ts/components/visual_order';
-import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {orderSchema} from 'ts/schemas/order_schema';
-import {SchemaValidator} from 'ts/schemas/validator';
-import {
- AlertTypes,
- BlockchainErrs,
- ContractResponse,
- ExchangeContractErrs,
- Order,
- OrderToken,
- Side,
- Token,
- TokenByAddress,
- TokenStateByAddress,
- WebsitePaths,
-} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {errorReporter} from 'ts/utils/error_reporter';
-import {utils} from 'ts/utils/utils';
-
-const CUSTOM_LIGHT_GRAY = '#BBBBBB';
+import { Link } from 'react-router-dom';
+import { Blockchain } from 'ts/blockchain';
+import { TrackTokenConfirmationDialog } from 'ts/components/dialogs/track_token_confirmation_dialog';
+import { FillOrderJSON } from 'ts/components/fill_order_json';
+import { FillWarningDialog } from 'ts/components/fill_warning_dialog';
+import { TokenAmountInput } from 'ts/components/inputs/token_amount_input';
+import { Alert } from 'ts/components/ui/alert';
+import { EthereumAddress } from 'ts/components/ui/ethereum_address';
+import { Identicon } from 'ts/components/ui/identicon';
+import { VisualOrder } from 'ts/components/visual_order';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { orderSchema } from 'ts/schemas/order_schema';
+import { SchemaValidator } from 'ts/schemas/validator';
+import { AlertTypes, BlockchainErrs, Order, Token, TokenByAddress, 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';
interface FillOrderProps {
blockchain: Blockchain;
@@ -75,7 +58,7 @@ interface FillOrderState {
}
export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
- private validator: SchemaValidator;
+ private _validator: SchemaValidator;
constructor(props: FillOrderProps) {
super(props);
this.state = {
@@ -96,12 +79,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
isConfirmingTokenTracking: false,
tokensToTrack: [],
};
- this.validator = new SchemaValidator();
+ this._validator = new SchemaValidator();
}
public componentWillMount() {
if (!_.isEmpty(this.state.orderJSON)) {
// tslint:disable-next-line:no-floating-promises
- this.validateFillOrderFireAndForgetAsync(this.state.orderJSON);
+ this._validateFillOrderFireAndForgetAsync(this.state.orderJSON);
}
}
public componentDidMount() {
@@ -109,57 +92,57 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
public render() {
return (
- <div className="clearfix lg-px4 md-px4 sm-px2" style={{minHeight: 600}}>
+ <div className="clearfix lg-px4 md-px4 sm-px2" style={{ minHeight: 600 }}>
<h3>Fill an order</h3>
<Divider />
<div>
- {!this.props.isOrderInUrl &&
+ {!this.props.isOrderInUrl && (
<div>
- <div className="pt2 pb2">
- Paste an order JSON snippet below to begin
- </div>
+ <div className="pt2 pb2">Paste an order JSON snippet below to begin</div>
<div className="pb2">Order JSON</div>
<FillOrderJSON
blockchain={this.props.blockchain}
tokenByAddress={this.props.tokenByAddress}
networkId={this.props.networkId}
orderJSON={this.state.orderJSON}
- onFillOrderJSONChanged={this.onFillOrderJSONChanged.bind(this)}
+ onFillOrderJSONChanged={this._onFillOrderJSONChanged.bind(this)}
/>
- {this.renderOrderJsonNotices()}
+ {this._renderOrderJsonNotices()}
</div>
- }
+ )}
<div>
- {!_.isUndefined(this.state.parsedOrder) && this.state.didOrderValidationRun
- && this.state.areAllInvolvedTokensTracked &&
- this.renderVisualOrder()
- }
+ {!_.isUndefined(this.state.parsedOrder) &&
+ this.state.didOrderValidationRun &&
+ this.state.areAllInvolvedTokensTracked &&
+ this._renderVisualOrder()}
</div>
- {this.props.isOrderInUrl &&
+ {this.props.isOrderInUrl && (
<div className="pt2">
- <Card style={{boxShadow: 'none', backgroundColor: 'none', border: '1px solid #eceaea'}}>
- <CardHeader
- title="Order JSON"
- actAsExpander={true}
- showExpandableButton={true}
- />
+ <Card
+ style={{
+ boxShadow: 'none',
+ backgroundColor: 'none',
+ border: '1px solid #eceaea',
+ }}
+ >
+ <CardHeader title="Order JSON" actAsExpander={true} showExpandableButton={true} />
<CardText expandable={true}>
<FillOrderJSON
blockchain={this.props.blockchain}
tokenByAddress={this.props.tokenByAddress}
networkId={this.props.networkId}
orderJSON={this.state.orderJSON}
- onFillOrderJSONChanged={this.onFillOrderJSONChanged.bind(this)}
+ onFillOrderJSONChanged={this._onFillOrderJSONChanged.bind(this)}
/>
</CardText>
</Card>
- {this.renderOrderJsonNotices()}
+ {this._renderOrderJsonNotices()}
</div>
- }
+ )}
</div>
<FillWarningDialog
isOpen={this.state.isFillWarningDialogOpen}
- onToggleDialog={this.onFillWarningClosed.bind(this)}
+ onToggleDialog={this._onFillWarningClosed.bind(this)}
/>
<TrackTokenConfirmationDialog
userAddress={this.props.userAddress}
@@ -169,29 +152,30 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
dispatcher={this.props.dispatcher}
tokens={this.state.tokensToTrack}
isOpen={this.state.isConfirmingTokenTracking}
- onToggleDialog={this.onToggleTrackConfirmDialog.bind(this)}
+ onToggleDialog={this._onToggleTrackConfirmDialog.bind(this)}
/>
</div>
);
}
- private renderOrderJsonNotices() {
+ private _renderOrderJsonNotices() {
return (
<div>
- {!_.isUndefined(this.props.initialOrder) && !this.state.didOrderValidationRun &&
- <div className="pt2">
- <span className="pr1">
- <i className="zmdi zmdi-spinner zmdi-hc-spin" />
- </span>
- <span>Validating order...</span>
- </div>
- }
- {!_.isEmpty(this.state.orderJSONErrMsg) &&
+ {!_.isUndefined(this.props.initialOrder) &&
+ !this.state.didOrderValidationRun && (
+ <div className="pt2">
+ <span className="pr1">
+ <i className="zmdi zmdi-spinner zmdi-hc-spin" />
+ </span>
+ <span>Validating order...</span>
+ </div>
+ )}
+ {!_.isEmpty(this.state.orderJSONErrMsg) && (
<Alert type={AlertTypes.ERROR} message={this.state.orderJSONErrMsg} />
- }
+ )}
</div>
);
}
- private renderVisualOrder() {
+ private _renderVisualOrder() {
const takerTokenAddress = this.state.parsedOrder.taker.token.address;
const takerToken = this.props.tokenByAddress[takerTokenAddress];
const orderTakerAmount = new BigNumber(this.state.parsedOrder.taker.amount);
@@ -212,32 +196,30 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
amount: this.props.orderFillAmount,
symbol: takerToken.symbol,
};
- const orderTaker = !_.isEmpty(this.state.parsedOrder.taker.address) ? this.state.parsedOrder.taker.address :
- this.props.userAddress;
+ const orderTaker = !_.isEmpty(this.state.parsedOrder.taker.address)
+ ? this.state.parsedOrder.taker.address
+ : this.props.userAddress;
const parsedOrderExpiration = new BigNumber(this.state.parsedOrder.expiration);
const exchangeRate = orderMakerAmount.div(orderTakerAmount);
let orderReceiveAmount = 0;
if (!_.isUndefined(this.props.orderFillAmount)) {
const orderReceiveAmountBigNumber = exchangeRate.mul(this.props.orderFillAmount);
- orderReceiveAmount = this.formatCurrencyAmount(orderReceiveAmountBigNumber, makerToken.decimals);
+ orderReceiveAmount = this._formatCurrencyAmount(orderReceiveAmountBigNumber, makerToken.decimals);
}
- const isUserMaker = !_.isUndefined(this.state.parsedOrder) &&
- this.state.parsedOrder.maker.address === this.props.userAddress;
+ const isUserMaker =
+ !_.isUndefined(this.state.parsedOrder) && this.state.parsedOrder.maker.address === this.props.userAddress;
const expiryDate = utils.convertToReadableDateTimeFromUnixTimestamp(parsedOrderExpiration);
return (
<div className="pt3 pb1">
- <div className="clearfix pb2" style={{width: '100%'}}>
+ <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="inline right" style={{ minWidth: 208 }}>
+ <div className="col col-4 pl2" style={{ color: colors.grey }}>
Maker:
</div>
<div className="col col-2 pr1">
- <Identicon
- address={this.state.parsedOrder.maker.address}
- diameter={23}
- />
+ <Identicon address={this.state.parsedOrder.maker.address} diameter={23} />
</div>
<div className="col col-6">
<EthereumAddress
@@ -261,123 +243,112 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
isMakerTokenAddressInRegistry={this.state.isMakerTokenAddressInRegistry}
isTakerTokenAddressInRegistry={this.state.isTakerTokenAddressInRegistry}
/>
- <div className="center pt3 pb2">
- Expires: {expiryDate} UTC
- </div>
+ <div className="center pt3 pb2">Expires: {expiryDate} UTC</div>
</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="col col-5 pl1"
- style={{color: CUSTOM_LIGHT_GRAY, paddingTop: 39}}
- >
- = {accounting.formatNumber(orderReceiveAmount, 6)} {makerToken.symbol}
- </div>
+ {!isUserMaker && (
+ <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="absolute sm-hide xs-hide"
+ style={{
+ color: colors.grey400,
+ right: -247,
+ top: 39,
+ width: 242,
+ }}
+ >
+ = {accounting.formatNumber(orderReceiveAmount, 6)} {makerToken.symbol}
+ </div>
</div>
- }
+ )}
<div>
- {isUserMaker ?
+ {isUserMaker ? (
<div>
<RaisedButton
- style={{width: '100%'}}
+ style={{ width: '100%' }}
disabled={this.state.isCancelling}
label={this.state.isCancelling ? 'Cancelling order...' : 'Cancel order'}
- onClick={this.onCancelOrderClickFireAndForgetAsync.bind(this)}
+ onClick={this._onCancelOrderClickFireAndForgetAsync.bind(this)}
/>
- {this.state.didCancelOrderSucceed &&
- <Alert
- type={AlertTypes.SUCCESS}
- message={this.renderCancelSuccessMsg()}
- />
- }
- </div> :
+ {this.state.didCancelOrderSucceed && (
+ <Alert type={AlertTypes.SUCCESS} message={this._renderCancelSuccessMsg()} />
+ )}
+ </div>
+ ) : (
<div>
<RaisedButton
- style={{width: '100%'}}
+ style={{ width: '100%' }}
disabled={this.state.isFilling}
label={this.state.isFilling ? 'Filling order...' : 'Fill order'}
- onClick={this.onFillOrderClick.bind(this)}
+ onClick={this._onFillOrderClick.bind(this)}
/>
- {!_.isEmpty(this.state.globalErrMsg) &&
+ {!_.isEmpty(this.state.globalErrMsg) && (
<Alert type={AlertTypes.ERROR} message={this.state.globalErrMsg} />
- }
- {this.state.didFillOrderSucceed &&
- <Alert
- type={AlertTypes.SUCCESS}
- message={this.renderFillSuccessMsg()}
- />
- }
+ )}
+ {this.state.didFillOrderSucceed && (
+ <Alert type={AlertTypes.SUCCESS} message={this._renderFillSuccessMsg()} />
+ )}
</div>
- }
+ )}
</div>
</div>
);
}
- private renderFillSuccessMsg() {
+ private _renderFillSuccessMsg() {
return (
<div>
Order successfully filled. See the trade details in your{' '}
- <Link
- to={`${WebsitePaths.Portal}/trades`}
- style={{color: 'white'}}
- >
+ <Link to={`${WebsitePaths.Portal}/trades`} style={{ color: colors.white }}>
trade history
</Link>
</div>
);
}
- private renderCancelSuccessMsg() {
- return (
- <div>
- Order successfully cancelled.
- </div>
- );
+ private _renderCancelSuccessMsg() {
+ return <div>Order successfully cancelled.</div>;
}
- private onFillOrderClick() {
+ private _onFillOrderClick() {
if (!this.state.isMakerTokenAddressInRegistry || !this.state.isTakerTokenAddressInRegistry) {
this.setState({
isFillWarningDialogOpen: true,
});
} else {
// tslint:disable-next-line:no-floating-promises
- this.onFillOrderClickFireAndForgetAsync();
+ this._onFillOrderClickFireAndForgetAsync();
}
}
- private onFillWarningClosed(didUserCancel: boolean) {
+ private _onFillWarningClosed(didUserCancel: boolean) {
this.setState({
isFillWarningDialogOpen: false,
});
if (!didUserCancel) {
// tslint:disable-next-line:no-floating-promises
- this.onFillOrderClickFireAndForgetAsync();
+ this._onFillOrderClickFireAndForgetAsync();
}
}
- private onFillAmountChange(isValid: boolean, amount?: BigNumber) {
+ private _onFillAmountChange(isValid: boolean, amount?: BigNumber) {
this.props.dispatcher.updateOrderFillAmount(amount);
}
- private onFillOrderJSONChanged(event: any) {
+ private _onFillOrderJSONChanged(event: any) {
const orderJSON = event.target.value;
this.setState({
didOrderValidationRun: _.isEmpty(orderJSON) && _.isEmpty(this.state.orderJSONErrMsg),
didFillOrderSucceed: false,
});
// tslint:disable-next-line:no-floating-promises
- this.validateFillOrderFireAndForgetAsync(orderJSON);
+ this._validateFillOrderFireAndForgetAsync(orderJSON);
}
- private async checkForUntrackedTokensAndAskToAdd() {
+ private async _checkForUntrackedTokensAndAskToAdd() {
if (!_.isEmpty(this.state.orderJSONErrMsg)) {
return;
}
@@ -389,22 +360,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);
}
@@ -419,12 +392,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
});
}
}
- private async validateFillOrderFireAndForgetAsync(orderJSON: string) {
+ private async _validateFillOrderFireAndForgetAsync(orderJSON: string) {
let orderJSONErrMsg = '';
let parsedOrder: Order;
try {
const order = JSON.parse(orderJSON);
- const validationResult = this.validator.validate(order, orderSchema);
+ const validationResult = this._validator.validate(order, orderSchema);
if (validationResult.errors.length > 0) {
orderJSONErrMsg = 'Submitted order JSON is not a valid order';
utils.consoleLog(`Unexpected order JSON validation error: ${validationResult.errors.join(', ')}`);
@@ -517,10 +490,10 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
unavailableTakerAmount,
});
- await this.checkForUntrackedTokensAndAskToAdd();
+ await this._checkForUntrackedTokensAndAskToAdd();
}
- private async onFillOrderClickFireAndForgetAsync(): Promise<void> {
- if (!_.isEmpty(this.props.blockchainErr) || _.isEmpty(this.props.userAddress)) {
+ private async _onFillOrderClickFireAndForgetAsync(): Promise<void> {
+ if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return;
}
@@ -531,8 +504,6 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
});
const parsedOrder = this.state.parsedOrder;
- const orderHash = parsedOrder.signature.hash;
- const unavailableTakerAmount = await this.props.blockchain.getUnavailableTakerAmountAsync(orderHash);
const takerFillAmount = this.props.orderFillAmount;
if (_.isUndefined(this.props.userAddress)) {
@@ -565,11 +536,12 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
if (_.isEmpty(globalErrMsg)) {
try {
await this.props.blockchain.validateFillOrderThrowIfInvalidAsync(
- signedOrder, takerFillAmount, this.props.userAddress);
- } catch (err) {
- globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(
- err.message, parsedOrder.taker.address,
+ signedOrder,
+ takerFillAmount,
+ this.props.userAddress,
);
+ } catch (err) {
+ globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.taker.address);
}
}
if (!_.isEmpty(globalErrMsg)) {
@@ -581,7 +553,8 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
try {
const orderFilledAmount: BigNumber = await this.props.blockchain.fillOrderAsync(
- signedOrder, this.props.orderFillAmount,
+ signedOrder,
+ this.props.orderFillAmount,
);
// After fill completes, let's update the token balances
const makerToken = this.props.tokenByAddress[parsedOrder.maker.token.address];
@@ -605,15 +578,15 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
globalErrMsg = 'Failed to fill order, please refresh and try again';
utils.consoleLog(`${err}`);
- await errorReporter.reportAsync(err);
this.setState({
globalErrMsg,
});
+ await errorReporter.reportAsync(err);
return;
}
}
- private async onCancelOrderClickFireAndForgetAsync(): Promise<void> {
- if (!_.isEmpty(this.props.blockchainErr) || _.isEmpty(this.props.userAddress)) {
+ private async _onCancelOrderClickFireAndForgetAsync(): Promise<void> {
+ if (this.props.blockchainErr !== BlockchainErrs.NoError || _.isEmpty(this.props.userAddress)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return;
}
@@ -655,8 +628,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
const unavailableTakerAmount = await this.props.blockchain.getUnavailableTakerAmountAsync(orderHash);
const availableTakerTokenAmount = takerTokenAmount.minus(unavailableTakerAmount);
try {
- await this.props.blockchain.validateCancelOrderThrowIfInvalidAsync(
- signedOrder, availableTakerTokenAmount);
+ await this.props.blockchain.validateCancelOrderThrowIfInvalidAsync(signedOrder, availableTakerTokenAmount);
} catch (err) {
globalErrMsg = utils.zeroExErrToHumanReadableErrMsg(err.message, parsedOrder.taker.address);
}
@@ -668,9 +640,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
return;
}
try {
- await this.props.blockchain.cancelOrderAsync(
- signedOrder, availableTakerTokenAmount,
- );
+ await this.props.blockchain.cancelOrderAsync(signedOrder, availableTakerTokenAmount);
this.setState({
isCancelling: false,
didCancelOrderSucceed: true,
@@ -688,19 +658,19 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
}
globalErrMsg = 'Failed to cancel order, please refresh and try again';
utils.consoleLog(`${err}`);
- await errorReporter.reportAsync(err);
this.setState({
globalErrMsg,
});
+ await errorReporter.reportAsync(err);
return;
}
}
- private formatCurrencyAmount(amount: BigNumber, decimals: number): number {
+ private _formatCurrencyAmount(amount: BigNumber, decimals: number): number {
const unitAmount = ZeroEx.toUnitAmount(amount, decimals);
const roundedUnitAmount = Math.round(unitAmount.toNumber() * 100000) / 100000;
return roundedUnitAmount;
}
- private onToggleTrackConfirmDialog(didConfirmTokenTracking: boolean) {
+ private _onToggleTrackConfirmDialog(didConfirmTokenTracking: boolean) {
if (!didConfirmTokenTracking) {
this.setState({
orderJSON: '',
diff --git a/packages/website/ts/components/fill_order_json.tsx b/packages/website/ts/components/fill_order_json.tsx
index f4db1f74e..f8e43481a 100644
--- a/packages/website/ts/components/fill_order_json.tsx
+++ b/packages/website/ts/components/fill_order_json.tsx
@@ -1,13 +1,13 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import Paper from 'material-ui/Paper';
import TextField from 'material-ui/TextField';
import * as React from 'react';
-import {Blockchain} from 'ts/blockchain';
-import {Side, TokenByAddress} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+import { Blockchain } from 'ts/blockchain';
+import { Side, TokenByAddress } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { utils } from 'ts/utils/utils';
interface FillOrderJSONProps {
blockchain: Blockchain;
@@ -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,17 +41,28 @@ export class FillOrderJSON extends React.Component<FillOrderJSONProps, FillOrder
v: 27,
};
const hintSalt = ZeroEx.generatePseudoRandomSalt();
- const hintOrder = utils.generateOrder(this.props.networkId, exchangeContract, hintSideToAssetToken,
- hintOrderExpiryTimestamp, '', '', constants.MAKER_FEE,
- constants.TAKER_FEE, constants.FEE_RECIPIENT_ADDRESS,
- hintSignatureData, this.props.tokenByAddress, hintSalt);
+ const feeRecipient = constants.NULL_ADDRESS;
+ const hintOrder = utils.generateOrder(
+ this.props.networkId,
+ exchangeContract,
+ hintSideToAssetToken,
+ hintOrderExpiryTimestamp,
+ '',
+ '',
+ constants.MAKER_FEE,
+ constants.TAKER_FEE,
+ feeRecipient,
+ hintSignatureData,
+ this.props.tokenByAddress,
+ hintSalt,
+ );
const hintOrderJSON = `${JSON.stringify(hintOrder, null, '\t').substring(0, 500)}...`;
return (
<div>
- <Paper className="p1 overflow-hidden" style={{height: 164}}>
+ <Paper className="p1 overflow-hidden" style={{ height: 164 }}>
<TextField
id="orderJSON"
- hintStyle={{bottom: 0, top: 0}}
+ hintStyle={{ bottom: 0, top: 0 }}
fullWidth={true}
value={this.props.orderJSON}
onChange={this.props.onFillOrderJSONChanged.bind(this)}
@@ -59,8 +70,8 @@ export class FillOrderJSON extends React.Component<FillOrderJSONProps, FillOrder
multiLine={true}
rows={6}
rowsMax={6}
- underlineStyle={{display: 'none'}}
- textareaStyle={{marginTop: 0}}
+ underlineStyle={{ display: 'none' }}
+ textareaStyle={{ marginTop: 0 }}
/>
</Paper>
</div>
diff --git a/packages/website/ts/components/fill_warning_dialog.tsx b/packages/website/ts/components/fill_warning_dialog.tsx
index 83e46cc8f..165d21b34 100644
--- a/packages/website/ts/components/fill_warning_dialog.tsx
+++ b/packages/website/ts/components/fill_warning_dialog.tsx
@@ -1,11 +1,11 @@
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;
- onToggleDialog: () => void;
+ onToggleDialog: (didUserCancel: boolean) => void;
}
export function FillWarningDialog(props: FillWarningDialogProps) {
@@ -13,7 +13,7 @@ export function FillWarningDialog(props: FillWarningDialogProps) {
return (
<Dialog
title="Warning"
- titleStyle={{fontWeight: 100, color: colors.red500}}
+ titleStyle={{ fontWeight: 100, color: colors.red500 }}
actions={[
<FlatButton
key="fillWarningCancel"
@@ -31,15 +31,11 @@ export function FillWarningDialog(props: FillWarningDialogProps) {
autoScrollBodyContent={true}
modal={true}
>
- <div className="pt2" style={{color: colors.grey700}}>
+ <div className="pt2" style={{ color: colors.grey700 }}>
<div>
- At least one of the tokens in this order was not found in the
- token registry smart contract and may be counterfeit. It is your
- responsibility to verify the token addresses on Etherscan (
- <a
- href="https://0xproject.com/wiki#Verifying-Custom-Tokens"
- target="_blank"
- >
+ At least one of the tokens in this order was not found in the token registry smart contract and may
+ be counterfeit. It is your responsibility to verify the token addresses on Etherscan (
+ <a href="https://0xproject.com/wiki#Verifying-Custom-Tokens" target="_blank">
See this how-to guide
</a>) before filling an order. <b>This action may result in the loss of funds</b>.
</div>
diff --git a/packages/website/ts/components/flash_messages/token_send_completed.tsx b/packages/website/ts/components/flash_messages/token_send_completed.tsx
index fef7520f6..18f371624 100644
--- a/packages/website/ts/components/flash_messages/token_send_completed.tsx
+++ b/packages/website/ts/components/flash_messages/token_send_completed.tsx
@@ -1,9 +1,10 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
-import {Token} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { Token } from 'ts/types';
+import { colors } from 'ts/utils/colors';
+import { utils } from 'ts/utils/utils';
interface TokenSendCompletedProps {
etherScanLinkIfExists?: string;
@@ -16,16 +17,11 @@ interface TokenSendCompletedState {}
export class TokenSendCompleted extends React.Component<TokenSendCompletedProps, TokenSendCompletedState> {
public render() {
- const etherScanLink = !_.isUndefined(this.props.etherScanLinkIfExists) &&
- (
- <a
- style={{color: 'white'}}
- href={`${this.props.etherScanLinkIfExists}`}
- target="_blank"
- >
- Verify on Etherscan
- </a>
- );
+ const etherScanLink = !_.isUndefined(this.props.etherScanLinkIfExists) && (
+ <a style={{ color: colors.white }} href={`${this.props.etherScanLinkIfExists}`} target="_blank">
+ Verify on Etherscan
+ </a>
+ );
const amountInUnits = ZeroEx.toUnitAmount(this.props.amountInBaseUnits, this.props.token.decimals);
const truncatedAddress = utils.getAddressBeginAndEnd(this.props.toAddress);
return (
diff --git a/packages/website/ts/components/flash_messages/transaction_submitted.tsx b/packages/website/ts/components/flash_messages/transaction_submitted.tsx
index cef3e2b1e..862e382dd 100644
--- a/packages/website/ts/components/flash_messages/transaction_submitted.tsx
+++ b/packages/website/ts/components/flash_messages/transaction_submitted.tsx
@@ -1,5 +1,6 @@
import * as _ from 'lodash';
import * as React from 'react';
+import { colors } from 'ts/utils/colors';
interface TransactionSubmittedProps {
etherScanLinkIfExists?: string;
@@ -15,11 +16,7 @@ export class TransactionSubmitted extends React.Component<TransactionSubmittedPr
return (
<div>
Transaction submitted to the network:{' '}
- <a
- style={{color: 'white'}}
- href={`${this.props.etherScanLinkIfExists}`}
- target="_blank"
- >
+ <a style={{ color: colors.white }} href={`${this.props.etherScanLinkIfExists}`} target="_blank">
Verify on Etherscan
</a>
</div>
diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx
index 5e3c0479a..a0f1a0c96 100644
--- a/packages/website/ts/components/footer.tsx
+++ b/packages/website/ts/components/footer.tsx
@@ -1,14 +1,9 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {
- Link,
-} from 'react-router-dom';
-import {HashLink} from 'react-router-hash-link';
-import {
- Link as ScrollLink,
-} from 'react-scroll';
-import {Styles, WebsitePaths} from 'ts/types';
-import {constants} from 'ts/utils/constants';
+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 {
[sectionName: string]: FooterMenuItem[];
@@ -18,7 +13,6 @@ interface FooterMenuItem {
title: string;
path?: string;
isExternal?: boolean;
- fileName?: string;
}
enum Sections {
@@ -28,9 +22,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: [
{
@@ -63,26 +54,27 @@ const menuItemsBySection: MenuItemsBySection = {
{
title: 'Rocket.chat',
isExternal: true,
- path: constants.ZEROEX_CHAT_URL,
- fileName: 'rocketchat.png',
+ path: constants.URL_ZEROEX_CHAT,
},
{
title: 'Blog',
isExternal: true,
- path: constants.BLOG_URL,
- fileName: 'medium.png',
+ path: constants.URL_BLOG,
},
{
title: 'Twitter',
isExternal: true,
- path: constants.TWITTER_URL,
- fileName: 'twitter.png',
+ path: constants.URL_TWITTER,
},
{
title: 'Reddit',
isExternal: true,
- path: constants.REDDIT_URL,
- fileName: 'reddit.png',
+ path: constants.URL_REDDIT,
+ },
+ {
+ title: 'Forum',
+ isExternal: true,
+ path: constants.URL_DISCOURSE_FORUM,
},
],
Organization: [
@@ -94,7 +86,7 @@ const menuItemsBySection: MenuItemsBySection = {
{
title: 'Careers',
isExternal: true,
- path: constants.ANGELLIST_URL,
+ path: constants.URL_ANGELLIST,
},
{
title: 'Contact',
@@ -104,34 +96,40 @@ const menuItemsBySection: MenuItemsBySection = {
],
};
const linkStyle = {
- color: 'white',
+ color: colors.white,
cursor: 'pointer',
};
-const titleToIcon: {[title: string]: string} = {
+const titleToIcon: { [title: string]: string } = {
'Rocket.chat': 'rocketchat.png',
- 'Blog': 'medium.png',
- 'Twitter': 'twitter.png',
- 'Reddit': 'reddit.png',
+ Blog: 'medium.png',
+ Twitter: 'twitter.png',
+ Reddit: 'reddit.png',
+ Forum: 'discourse.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 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>
@@ -139,20 +137,20 @@ export class Footer extends React.Component<FooterProps, FooterState> {
<div className="col lg-col-8 md-col-8 col-12 lg-pl4 md-pl4">
<div className="col lg-col-4 md-col-4 col-12">
<div className="lg-right md-right sm-center">
- {this.renderHeader(Sections.Documentation)}
- {_.map(menuItemsBySection[Sections.Documentation], this.renderMenuItem.bind(this))}
+ {this._renderHeader(Sections.Documentation)}
+ {_.map(menuItemsBySection[Sections.Documentation], this._renderMenuItem.bind(this))}
</div>
</div>
<div className="col lg-col-4 md-col-4 col-12 lg-pr2 md-pr2">
<div className="lg-right md-right sm-center">
- {this.renderHeader(Sections.Community)}
- {_.map(menuItemsBySection[Sections.Community], this.renderMenuItem.bind(this))}
+ {this._renderHeader(Sections.Community)}
+ {_.map(menuItemsBySection[Sections.Community], this._renderMenuItem.bind(this))}
</div>
</div>
<div className="col lg-col-4 md-col-4 col-12">
<div className="lg-right md-right sm-center">
- {this.renderHeader(Sections.Organization)}
- {_.map(menuItemsBySection[Sections.Organization], this.renderMenuItem.bind(this))}
+ {this._renderHeader(Sections.Organization)}
+ {_.map(menuItemsBySection[Sections.Organization], this._renderMenuItem.bind(this))}
</div>
</div>
</div>
@@ -160,100 +158,55 @@ export class Footer extends React.Component<FooterProps, FooterState> {
</div>
);
}
- private renderIcon(fileName: string) {
+ private _renderIcon(fileName: string) {
return (
- <div style={{height: ICON_DIMENSION, width: ICON_DIMENSION}}>
- <img src={`/images/social/${fileName}`} style={{width: ICON_DIMENSION}} />
+ <div style={{ height: ICON_DIMENSION, width: ICON_DIMENSION }}>
+ <img src={`/images/social/${fileName}`} style={{ width: ICON_DIMENSION }} />
</div>
);
}
- private renderMenuItem(item: FooterMenuItem) {
+ private _renderMenuItem(item: FooterMenuItem) {
const iconIfExists = titleToIcon[item.title];
return (
- <div
- key={item.title}
- className="sm-center"
- style={{fontSize: 13, paddingTop: 25}}
- >
- {item.isExternal ?
- <a
- className="text-decoration-none"
- style={linkStyle}
- target="_blank"
- href={item.path}
- >
- {!_.isUndefined(iconIfExists) ?
- <div className="sm-mx-auto" style={{width: 65}}>
+ <div key={item.title} className="sm-center" style={{ fontSize: 13, paddingTop: 25 }}>
+ {item.isExternal ? (
+ <a className="text-decoration-none" style={linkStyle} target="_blank" href={item.path}>
+ {!_.isUndefined(iconIfExists) ? (
+ <div className="sm-mx-auto" style={{ width: 65 }}>
<div className="flex">
- <div className="pr1">
- {this.renderIcon(iconIfExists)}
- </div>
+ <div className="pr1">{this._renderIcon(iconIfExists)}</div>
<div>{item.title}</div>
</div>
- </div> :
+ </div>
+ ) : (
item.title
- }
- </a> :
- <Link
- to={item.path}
- style={linkStyle}
- className="text-decoration-none"
- >
+ )}
+ </a>
+ ) : (
+ <Link to={item.path} style={linkStyle} className="text-decoration-none">
<div>
- {!_.isUndefined(iconIfExists) &&
- <div className="pr1">
- {this.renderIcon(iconIfExists)}
- </div>
- }
+ {!_.isUndefined(iconIfExists) && (
+ <div className="pr1">{this._renderIcon(iconIfExists)}</div>
+ )}
{item.title}
</div>
</Link>
- }
+ )}
</div>
);
}
- private renderHeader(title: string) {
+ private _renderHeader(title: string) {
const headerStyle = {
textTransform: 'uppercase',
- color: CUSTOM_LIGHT_GRAY,
+ color: colors.grey400,
letterSpacing: 2,
fontFamily: 'Roboto Mono',
fontSize: 13,
};
return (
- <div
- className="lg-pb2 md-pb2 sm-pt4"
- style={headerStyle}
- >
+ <div className="lg-pb2 md-pb2 sm-pt4" style={headerStyle}>
{title}
</div>
);
}
- private renderHomepageLink(title: string) {
- const hash = title.toLowerCase();
- if (this.props.location.pathname === WebsitePaths.Home) {
- return (
- <ScrollLink
- style={linkStyle}
- to={hash}
- smooth={true}
- offset={0}
- duration={constants.HOME_SCROLL_DURATION_MS}
- containerId="home"
- >
- {title}
- </ScrollLink>
- );
- } else {
- return (
- <HashLink
- to={`/#${hash}`}
- className="text-decoration-none"
- style={linkStyle}
- >
- {title}
- </HashLink>
- );
- }
- }
}
diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx
index 633d6a017..df7d87cfd 100644
--- a/packages/website/ts/components/generate_order/asset_picker.tsx
+++ b/packages/website/ts/components/generate_order/asset_picker.tsx
@@ -1,26 +1,14 @@
import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
-import GridList from 'material-ui/GridList/GridList';
-import GridTile from 'material-ui/GridList/GridTile';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {Blockchain} from 'ts/blockchain';
-import {NewTokenForm} from 'ts/components/generate_order/new_token_form';
-import {TrackTokenConfirmation} from 'ts/components/track_token_confirmation';
-import {TokenIcon} from 'ts/components/ui/token_icon';
-import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {
- AssetToken,
- DialogConfigs,
- Styles,
- Token,
- TokenByAddress,
- TokenState,
- TokenVisibility,
-} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { Blockchain } from 'ts/blockchain';
+import { NewTokenForm } from 'ts/components/generate_order/new_token_form';
+import { TrackTokenConfirmation } from 'ts/components/track_token_confirmation';
+import { TokenIcon } from 'ts/components/ui/token_icon';
+import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { DialogConfigs, Token, TokenByAddress, TokenState, TokenVisibility } from 'ts/types';
const TOKEN_ICON_DIMENSION = 100;
const TILE_DIMENSION = 146;
@@ -53,7 +41,7 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
public static defaultProps: Partial<AssetPickerProps> = {
tokenVisibility: TokenVisibility.ALL,
};
- private dialogConfigsByAssetView: {[assetView: string]: DialogConfigs};
+ private _dialogConfigsByAssetView: { [assetView: string]: DialogConfigs };
constructor(props: AssetPickerProps) {
super(props);
this.state = {
@@ -62,7 +50,7 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
chosenTrackTokenAddress: undefined,
isAddingTokenToTracked: false,
};
- this.dialogConfigsByAssetView = {
+ this._dialogConfigsByAssetView = {
[AssetViews.ASSET_PICKER]: {
title: 'Select token',
isModal: false,
@@ -80,45 +68,41 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
<FlatButton
key="noTracking"
label="No"
- onTouchTap={this.onTrackConfirmationRespondedAsync.bind(this, false)}
+ onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, false)}
/>,
<FlatButton
key="yesTrack"
label="Yes"
- onTouchTap={this.onTrackConfirmationRespondedAsync.bind(this, true)}
+ onTouchTap={this._onTrackConfirmationRespondedAsync.bind(this, true)}
/>,
],
},
};
}
public render() {
- const dialogConfigs: DialogConfigs = this.dialogConfigsByAssetView[this.state.assetView];
+ const dialogConfigs: DialogConfigs = this._dialogConfigsByAssetView[this.state.assetView];
return (
<Dialog
title={dialogConfigs.title}
- titleStyle={{fontWeight: 100}}
+ titleStyle={{ fontWeight: 100 }}
modal={dialogConfigs.isModal}
open={this.props.isOpen}
actions={dialogConfigs.actions}
- onRequestClose={this.onCloseDialog.bind(this)}
+ onRequestClose={this._onCloseDialog.bind(this)}
>
- {this.state.assetView === AssetViews.ASSET_PICKER &&
- this.renderAssetPicker()
- }
- {this.state.assetView === AssetViews.NEW_TOKEN_FORM &&
+ {this.state.assetView === AssetViews.ASSET_PICKER && this._renderAssetPicker()}
+ {this.state.assetView === AssetViews.NEW_TOKEN_FORM && (
<NewTokenForm
blockchain={this.props.blockchain}
- onNewTokenSubmitted={this.onNewTokenSubmitted.bind(this)}
+ onNewTokenSubmitted={this._onNewTokenSubmitted.bind(this)}
tokenByAddress={this.props.tokenByAddress}
/>
- }
- {this.state.assetView === AssetViews.CONFIRM_TRACK_TOKEN &&
- this.renderConfirmTrackToken()
- }
+ )}
+ {this.state.assetView === AssetViews.CONFIRM_TRACK_TOKEN && this._renderConfirmTrackToken()}
</Dialog>
);
}
- private renderConfirmTrackToken() {
+ private _renderConfirmTrackToken() {
const token = this.props.tokenByAddress[this.state.chosenTrackTokenAddress];
return (
<TrackTokenConfirmation
@@ -129,22 +113,29 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
/>
);
}
- private renderAssetPicker() {
+ private _renderAssetPicker() {
return (
<div
className="clearfix flex flex-wrap"
- style={{overflowY: 'auto', maxWidth: 720, maxHeight: 356, marginBottom: 10}}
+ style={{
+ overflowY: 'auto',
+ maxWidth: 720,
+ maxHeight: 356,
+ marginBottom: 10,
+ }}
>
- {this.renderGridTiles()}
+ {this._renderGridTiles()}
</div>
);
}
- private renderGridTiles() {
+ private _renderGridTiles() {
let isHovered;
let tileStyles;
const gridTiles = _.map(this.props.tokenByAddress, (token: Token, address: string) => {
- if ((this.props.tokenVisibility === TokenVisibility.TRACKED && !token.isTracked) ||
- (this.props.tokenVisibility === TokenVisibility.UNTRACKED && token.isTracked)) {
+ if (
+ (this.props.tokenVisibility === TokenVisibility.TRACKED && !token.isTracked) ||
+ (this.props.tokenVisibility === TokenVisibility.UNTRACKED && token.isTracked)
+ ) {
return null; // Skip
}
isHovered = this.state.hoveredAddress === address;
@@ -155,11 +146,15 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
return (
<div
key={address}
- style={{width: TILE_DIMENSION, height: TILE_DIMENSION, ...tileStyles}}
+ style={{
+ width: TILE_DIMENSION,
+ height: TILE_DIMENSION,
+ ...tileStyles,
+ }}
className="p2 mx-auto"
- onClick={this.onChooseToken.bind(this, address)}
- onMouseEnter={this.onToggleHover.bind(this, address, true)}
- onMouseLeave={this.onToggleHover.bind(this, address, false)}
+ onClick={this._onChooseToken.bind(this, address)}
+ onMouseEnter={this._onToggleHover.bind(this, address, true)}
+ onMouseLeave={this._onToggleHover.bind(this, address, false)}
>
<div className="p1 center">
<TokenIcon token={token} diameter={TOKEN_ICON_DIMENSION} />
@@ -175,40 +170,44 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
opacity: isHovered ? 0.6 : 1,
};
if (this.props.tokenVisibility !== TokenVisibility.TRACKED) {
- gridTiles.push((
+ gridTiles.push(
<div
key={otherTokenKey}
- style={{width: TILE_DIMENSION, height: TILE_DIMENSION, ...tileStyles}}
+ style={{
+ width: TILE_DIMENSION,
+ height: TILE_DIMENSION,
+ ...tileStyles,
+ }}
className="p2 mx-auto"
- onClick={this.onCustomAssetChosen.bind(this)}
- onMouseEnter={this.onToggleHover.bind(this, otherTokenKey, true)}
- onMouseLeave={this.onToggleHover.bind(this, otherTokenKey, false)}
+ onClick={this._onCustomAssetChosen.bind(this)}
+ onMouseEnter={this._onToggleHover.bind(this, otherTokenKey, true)}
+ onMouseLeave={this._onToggleHover.bind(this, otherTokenKey, false)}
>
<div className="p1 center">
<i
- style={{fontSize: 105, paddingLeft: 1, paddingRight: 1}}
+ style={{ fontSize: 105, paddingLeft: 1, paddingRight: 1 }}
className="zmdi zmdi-plus-circle"
/>
</div>
<div className="center">Other ERC20 Token</div>
- </div>
- ));
+ </div>,
+ );
}
return gridTiles;
}
- private onToggleHover(address: string, isHovered: boolean) {
+ private _onToggleHover(address: string, isHovered: boolean) {
const hoveredAddress = isHovered ? address : undefined;
this.setState({
hoveredAddress,
});
}
- private onCloseDialog() {
+ private _onCloseDialog() {
this.setState({
assetView: AssetViews.ASSET_PICKER,
});
this.props.onTokenChosen(this.props.currentTokenAddress);
}
- private onChooseToken(tokenAddress: string) {
+ private _onChooseToken(tokenAddress: string) {
const token = this.props.tokenByAddress[tokenAddress];
if (token.isTracked) {
this.props.onTokenChosen(tokenAddress);
@@ -219,27 +218,12 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
});
}
}
- private getTitle() {
- switch (this.state.assetView) {
- case AssetViews.ASSET_PICKER:
- return 'Select token';
-
- case AssetViews.NEW_TOKEN_FORM:
- return 'Add an ERC20 token';
-
- case AssetViews.CONFIRM_TRACK_TOKEN:
- return 'Tracking confirmation';
-
- default:
- throw utils.spawnSwitchErr('assetView', this.state.assetView);
- }
- }
- private onCustomAssetChosen() {
+ private _onCustomAssetChosen() {
this.setState({
assetView: AssetViews.NEW_TOKEN_FORM,
});
}
- private onNewTokenSubmitted(newToken: Token, newTokenState: TokenState) {
+ private _onNewTokenSubmitted(newToken: Token, newTokenState: TokenState) {
this.props.dispatcher.updateTokenStateByAddress({
[newToken.address]: newTokenState,
});
@@ -250,14 +234,14 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt
});
this.props.onTokenChosen(newToken.address);
}
- private async onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) {
+ private async _onTrackConfirmationRespondedAsync(didUserAcceptTracking: boolean) {
if (!didUserAcceptTracking) {
this.setState({
isAddingTokenToTracked: false,
assetView: AssetViews.ASSET_PICKER,
chosenTrackTokenAddress: undefined,
});
- this.onCloseDialog();
+ this._onCloseDialog();
return;
}
this.setState({
@@ -265,15 +249,16 @@ 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);
- const [
- balance,
- allowance,
- ] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync(token.address);
+ const [balance, allowance] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync(
+ token.address,
+ );
this.props.dispatcher.updateTokenStateByAddress({
[token.address]: {
balance,
diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx
index 72edf08cf..3ae0d48a7 100644
--- a/packages/website/ts/components/generate_order/generate_order_form.tsx
+++ b/packages/website/ts/components/generate_order/generate_order_form.tsx
@@ -1,24 +1,23 @@
-import {Order, ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { Order, ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
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';
-import {HashInput} from 'ts/components/inputs/hash_input';
-import {IdenticonAddressInput} from 'ts/components/inputs/identicon_address_input';
-import {TokenAmountInput} from 'ts/components/inputs/token_amount_input';
-import {TokenInput} from 'ts/components/inputs/token_input';
-import {OrderJSON} from 'ts/components/order_json';
-import {Alert} from 'ts/components/ui/alert';
-import {HelpTooltip} from 'ts/components/ui/help_tooltip';
-import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button';
-import {SwapIcon} from 'ts/components/ui/swap_icon';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {orderSchema} from 'ts/schemas/order_schema';
-import {SchemaValidator} from 'ts/schemas/validator';
+import { Blockchain } from 'ts/blockchain';
+import { ExpirationInput } from 'ts/components/inputs/expiration_input';
+import { HashInput } from 'ts/components/inputs/hash_input';
+import { IdenticonAddressInput } from 'ts/components/inputs/identicon_address_input';
+import { TokenAmountInput } from 'ts/components/inputs/token_amount_input';
+import { TokenInput } from 'ts/components/inputs/token_input';
+import { OrderJSON } from 'ts/components/order_json';
+import { Alert } from 'ts/components/ui/alert';
+import { HelpTooltip } from 'ts/components/ui/help_tooltip';
+import { LifeCycleRaisedButton } from 'ts/components/ui/lifecycle_raised_button';
+import { SwapIcon } from 'ts/components/ui/swap_icon';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { orderSchema } from 'ts/schemas/order_schema';
+import { SchemaValidator } from 'ts/schemas/validator';
import {
AlertTypes,
BlockchainErrs,
@@ -30,8 +29,9 @@ import {
TokenByAddress,
TokenStateByAddress,
} from 'ts/types';
-import {errorReporter} from 'ts/utils/error_reporter';
-import {utils} from 'ts/utils/utils';
+import { colors } from 'ts/utils/colors';
+import { errorReporter } from 'ts/utils/error_reporter';
+import { utils } from 'ts/utils/utils';
enum SigningState {
UNSIGNED,
@@ -62,17 +62,8 @@ interface GenerateOrderFormState {
signingState: SigningState;
}
-const style = {
- paper: {
- display: 'inline-block',
- position: 'relative',
- textAlign: 'center',
- width: '100%',
- },
-};
-
-export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, any> {
- private validator: SchemaValidator;
+export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, GenerateOrderFormState> {
+ private _validator: SchemaValidator;
constructor(props: GenerateOrderFormProps) {
super(props);
this.state = {
@@ -80,20 +71,21 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
shouldShowIncompleteErrs: false,
signingState: SigningState.UNSIGNED,
};
- this.validator = new SchemaValidator();
+ this._validator = new SchemaValidator();
}
public componentDidMount() {
window.scrollTo(0, 0);
}
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> \
+ const takerExplanation =
+ 'If a taker is specified, only they are<br> \
allowed to fill this order. If no taker is<br> \
specified, anyone is able to fill it.';
const exchangeContractIfExists = this.props.blockchain.getExchangeContractAddressIfExists();
@@ -101,7 +93,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
<div className="clearfix mb2 lg-px4 md-px4 sm-px2">
<h3>Generate an order</h3>
<Divider />
- <div className="mx-auto" style={{maxWidth: 580}}>
+ <div className="mx-auto" style={{ maxWidth: 580 }}>
<div className="pt3">
<div className="mx-auto clearfix">
<div className="lg-col md-col lg-col-5 md-col-5 sm-col sm-col-5 sm-pb2">
@@ -111,9 +103,9 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
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}
/>
@@ -121,8 +113,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
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}
@@ -130,9 +122,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
</div>
<div className="lg-col md-col lg-col-2 md-col-2 sm-col sm-col-2 xs-hide">
<div className="p1">
- <SwapIcon
- swapTokensFn={dispatcher.swapAssetTokenSymbols.bind(dispatcher)}
- />
+ <SwapIcon swapTokensFn={dispatcher.swapAssetTokenSymbols.bind(dispatcher)} />
</div>
</div>
<div className="lg-col md-col lg-col-5 md-col-5 sm-col sm-col-5 sm-pb2">
@@ -142,9 +132,9 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
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}
/>
@@ -152,8 +142,8 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
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}
@@ -163,7 +153,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
</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)}
@@ -174,13 +164,11 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
<IdenticonAddressInput
label="Taker"
initialAddress={this.props.orderTakerAddress}
- updateOrderAddress={this.updateOrderAddress.bind(this)}
+ updateOrderAddress={this._updateOrderAddress.bind(this)}
/>
<div className="pt3">
<div className="pl1">
- <HelpTooltip
- explanation={takerExplanation}
- />
+ <HelpTooltip explanation={takerExplanation} />
</div>
</div>
</div>
@@ -198,20 +186,20 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
labelReady="Sign hash"
labelLoading="Signing..."
labelComplete="Hash signed!"
- onClickAsyncFn={this.onSignClickedAsync.bind(this)}
+ onClickAsyncFn={this._onSignClickedAsync.bind(this)}
/>
</div>
- {this.state.globalErrMsg !== '' &&
+ {this.state.globalErrMsg !== '' && (
<Alert type={AlertTypes.ERROR} message={this.state.globalErrMsg} />
- }
+ )}
</div>
</div>
<Dialog
title="Order JSON"
- titleStyle={{fontWeight: 100}}
+ titleStyle={{ fontWeight: 100 }}
modal={false}
open={this.state.signingState === SigningState.SIGNED}
- onRequestClose={this.onCloseOrderJSONDialog.bind(this)}
+ onRequestClose={this._onCloseOrderJSONDialog.bind(this)}
>
<OrderJSON
exchangeContractIfExists={exchangeContractIfExists}
@@ -231,10 +219,13 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
</div>
);
}
- private onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber) {
- this.props.dispatcher.updateChosenAssetToken(side, {address: token.address, amount});
+ private _onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber) {
+ this.props.dispatcher.updateChosenAssetToken(side, {
+ address: token.address,
+ amount,
+ });
}
- private onCloseOrderJSONDialog() {
+ private _onCloseOrderJSONDialog() {
// Upon closing the order JSON dialog, we update the orderSalt stored in the Redux store
// with a new value so that if a user signs the identical order again, the newly signed
// orderHash will not collide with the previously generated orderHash.
@@ -243,22 +234,27 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
signingState: SigningState.UNSIGNED,
});
}
- private async onSignClickedAsync(): Promise<boolean> {
- if (this.props.blockchainErr !== '') {
+ private async _onSignClickedAsync(): Promise<boolean> {
+ 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;
- if (!_.isUndefined(debitToken.amount) && !_.isUndefined(receiveAmount) &&
- debitToken.amount.gt(0) && receiveAmount.gt(0) &&
+ const receiveAmount = this.props.sideToAssetToken[Side.Receive].amount;
+ if (
+ !_.isUndefined(debitToken.amount) &&
+ !_.isUndefined(receiveAmount) &&
+ debitToken.amount.gt(0) &&
+ receiveAmount.gt(0) &&
this.props.userAddress !== '' &&
- debitBalance.gte(debitToken.amount) && debitAllowance.gte(debitToken.amount)) {
- const didSignSuccessfully = await this.signTransactionAsync();
+ debitBalance.gte(debitToken.amount) &&
+ debitAllowance.gte(debitToken.amount)
+ ) {
+ const didSignSuccessfully = await this._signTransactionAsync();
if (didSignSuccessfully) {
this.setState({
globalErrMsg: '',
@@ -279,7 +275,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
return false;
}
}
- private async signTransactionAsync(): Promise<boolean> {
+ private async _signTransactionAsync(): Promise<boolean> {
this.setState({
signingState: SigningState.SIGNING,
});
@@ -287,7 +283,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
if (_.isUndefined(exchangeContractAddr)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
this.setState({
- isSigning: false,
+ signingState: SigningState.UNSIGNED,
});
return false;
}
@@ -312,19 +308,28 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
let globalErrMsg = '';
try {
const signatureData = await this.props.blockchain.signOrderHashAsync(orderHash);
- const order = utils.generateOrder(this.props.networkId, exchangeContractAddr, this.props.sideToAssetToken,
- hashData.orderExpiryTimestamp, this.props.orderTakerAddress,
- this.props.userAddress, hashData.makerFee, hashData.takerFee,
- hashData.feeRecipientAddress, signatureData, this.props.tokenByAddress,
- hashData.orderSalt);
- const validationResult = this.validator.validate(order, orderSchema);
+ const order = utils.generateOrder(
+ this.props.networkId,
+ exchangeContractAddr,
+ this.props.sideToAssetToken,
+ hashData.orderExpiryTimestamp,
+ this.props.orderTakerAddress,
+ this.props.userAddress,
+ hashData.makerFee,
+ hashData.takerFee,
+ hashData.feeRecipientAddress,
+ signatureData,
+ this.props.tokenByAddress,
+ hashData.orderSalt,
+ );
+ const validationResult = this._validator.validate(order, orderSchema);
if (validationResult.errors.length > 0) {
globalErrMsg = 'Order signing failed. Please refresh and try again';
utils.consoleLog(`Unexpected error occured: Order validation failed:
${validationResult.errors}`);
}
} catch (err) {
- const errMsg = '' + err;
+ const errMsg = `${err}`;
if (utils.didUserDenyWeb3Request(errMsg)) {
globalErrMsg = 'User denied sign request';
} else {
@@ -340,7 +345,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, a
});
return globalErrMsg === '';
}
- private updateOrderAddress(address?: string): void {
+ private _updateOrderAddress(address?: string): void {
if (!_.isUndefined(address)) {
this.props.dispatcher.updateOrderTakerAddress(address);
}
diff --git a/packages/website/ts/components/generate_order/new_token_form.tsx b/packages/website/ts/components/generate_order/new_token_form.tsx
index 7e2c61ae8..63645be9a 100644
--- a/packages/website/ts/components/generate_order/new_token_form.tsx
+++ b/packages/website/ts/components/generate_order/new_token_form.tsx
@@ -1,15 +1,14 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } 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 {Blockchain} from 'ts/blockchain';
-import {AddressInput} from 'ts/components/inputs/address_input';
-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 {constants} from 'ts/utils/constants';
+import { Blockchain } from 'ts/blockchain';
+import { AddressInput } from 'ts/components/inputs/address_input';
+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;
@@ -46,25 +45,25 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
}
public render() {
return (
- <div className="mx-auto pb2" style={{width: 256}}>
+ <div className="mx-auto pb2" style={{ width: 256 }}>
<div>
<TextField
floatingLabelFixed={true}
- floatingLabelStyle={{color: colors.grey500}}
+ floatingLabelStyle={{ color: colors.grey }}
floatingLabelText={<RequiredLabel label="Name" />}
value={this.state.name}
errorText={this.state.nameErrText}
- onChange={this.onTokenNameChanged.bind(this)}
+ onChange={this._onTokenNameChanged.bind(this)}
/>
</div>
<div>
<TextField
floatingLabelFixed={true}
- floatingLabelStyle={{color: colors.grey500}}
+ floatingLabelStyle={{ color: colors.grey }}
floatingLabelText={<RequiredLabel label="Symbol" />}
value={this.state.symbol}
errorText={this.state.symbolErrText}
- onChange={this.onTokenSymbolChanged.bind(this)}
+ onChange={this._onTokenSymbolChanged.bind(this)}
/>
</div>
<div>
@@ -73,38 +72,36 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
label="Contract address"
initialAddress=""
shouldShowIncompleteErrs={this.state.shouldShowAddressIncompleteErr}
- updateAddress={this.onTokenAddressChanged.bind(this)}
+ updateAddress={this._onTokenAddressChanged.bind(this)}
/>
</div>
<div>
<TextField
floatingLabelFixed={true}
- floatingLabelStyle={{color: colors.grey500}}
+ floatingLabelStyle={{ color: colors.grey }}
floatingLabelText={<RequiredLabel label="Decimals" />}
value={this.state.decimals}
errorText={this.state.decimalsErrText}
- onChange={this.onTokenDecimalsChanged.bind(this)}
+ onChange={this._onTokenDecimalsChanged.bind(this)}
/>
</div>
- <div className="pt2 mx-auto" style={{width: 120}}>
+ <div className="pt2 mx-auto" style={{ width: 120 }}>
<LifeCycleRaisedButton
labelReady="Add"
labelLoading="Adding..."
labelComplete="Added!"
- onClickAsyncFn={this.onAddNewTokenClickAsync.bind(this)}
+ onClickAsyncFn={this._onAddNewTokenClickAsync.bind(this)}
/>
</div>
- {this.state.globalErrMsg !== '' &&
- <Alert type={AlertTypes.ERROR} message={this.state.globalErrMsg} />
- }
+ {this.state.globalErrMsg !== '' && <Alert type={AlertTypes.ERROR} message={this.state.globalErrMsg} />}
</div>
);
}
- private async onAddNewTokenClickAsync() {
+ private async _onAddNewTokenClickAsync() {
// Trigger validation of name and symbol
- this.onTokenNameChanged(undefined, this.state.name);
- this.onTokenSymbolChanged(undefined, this.state.symbol);
- this.onTokenDecimalsChanged(undefined, this.state.decimals);
+ this._onTokenNameChanged(undefined, this.state.name);
+ this._onTokenSymbolChanged(undefined, this.state.symbol);
+ this._onTokenDecimalsChanged(undefined, this.state.decimals);
const isAddressIncomplete = this.state.address === '';
let doesContractExist = false;
@@ -117,18 +114,21 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
let allowance = new BigNumber(0);
if (doesContractExist) {
try {
- [
- balance,
- allowance,
- ] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync(this.state.address);
+ [balance, allowance] = await this.props.blockchain.getCurrentUserTokenBalanceAndAllowanceAsync(
+ this.state.address,
+ );
} catch (err) {
hasBalanceAllowanceErr = true;
}
}
let globalErrMsg = '';
- if (this.state.nameErrText !== '' || this.state.symbolErrText !== '' ||
- this.state.decimalsErrText !== '' || isAddressIncomplete) {
+ if (
+ this.state.nameErrText !== '' ||
+ this.state.symbolErrText !== '' ||
+ this.state.decimalsErrText !== '' ||
+ isAddressIncomplete
+ ) {
globalErrMsg = 'Please fix the above issues';
} else if (!doesContractExist) {
globalErrMsg = 'No contract found at supplied address';
@@ -161,15 +161,15 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
};
this.props.onNewTokenSubmitted(newToken, newTokenState);
}
- private onTokenNameChanged(e: any, name: string) {
+ private _onTokenNameChanged(e: any, name: string) {
let nameErrText = '';
const maxLength = 30;
const tokens = _.values(this.props.tokenByAddress);
- const tokenWithNameIfExists = _.find(tokens, {name});
+ const tokenWithNameIfExists = _.find(tokens, { name });
const tokenWithNameExists = !_.isUndefined(tokenWithNameIfExists);
if (name === '') {
nameErrText = 'Name is required';
- } else if (!this.isValidName(name)) {
+ } else if (!this._isValidName(name)) {
nameErrText = 'Name should only contain letters, digits and spaces';
} else if (name.length > maxLength) {
nameErrText = `Max length is ${maxLength}`;
@@ -182,15 +182,15 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
nameErrText,
});
}
- private onTokenSymbolChanged(e: any, symbol: string) {
+ private _onTokenSymbolChanged(e: any, symbol: string) {
let symbolErrText = '';
const maxLength = 5;
const tokens = _.values(this.props.tokenByAddress);
- const tokenWithSymbolExists = !_.isUndefined(_.find(tokens, {symbol}));
+ const tokenWithSymbolExists = !_.isUndefined(_.find(tokens, { symbol }));
if (symbol === '') {
symbolErrText = 'Symbol is required';
- } else if (!this.isLetters(symbol)) {
- symbolErrText = 'Can only include letters';
+ } else if (!this._isAlphanumeric(symbol)) {
+ symbolErrText = 'Can only include alphanumeric characters';
} else if (symbol.length > maxLength) {
symbolErrText = `Max length is ${maxLength}`;
} else if (tokenWithSymbolExists) {
@@ -202,12 +202,12 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
symbolErrText,
});
}
- private onTokenDecimalsChanged(e: any, decimals: string) {
+ private _onTokenDecimalsChanged(e: any, decimals: string) {
let decimalsErrText = '';
const maxLength = 2;
if (decimals === '') {
decimalsErrText = 'Decimals is required';
- } else if (!this.isInteger(decimals)) {
+ } else if (!this._isInteger(decimals)) {
decimalsErrText = 'Must be an integer';
} else if (decimals.length > maxLength) {
decimalsErrText = `Max length is ${maxLength}`;
@@ -218,20 +218,20 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
decimalsErrText,
});
}
- private onTokenAddressChanged(address?: string) {
+ private _onTokenAddressChanged(address?: string) {
if (!_.isUndefined(address)) {
this.setState({
address,
});
}
}
- private isValidName(input: string) {
+ private _isValidName(input: string) {
return /^[a-z0-9 ]+$/i.test(input);
}
- private isInteger(input: string) {
+ private _isInteger(input: string) {
return /^[0-9]+$/i.test(input);
}
- private isLetters(input: string) {
- return /^[a-zA-Z]+$/i.test(input);
+ private _isAlphanumeric(input: string) {
+ return /^[a-zA-Z0-9]+$/i.test(input);
}
}
diff --git a/packages/website/ts/components/inputs/address_input.tsx b/packages/website/ts/components/inputs/address_input.tsx
index 8b03b8d12..dd4131140 100644
--- a/packages/website/ts/components/inputs/address_input.tsx
+++ b/packages/website/ts/components/inputs/address_input.tsx
@@ -1,10 +1,9 @@
-import {isAddress} from 'ethereum-address';
+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 {Blockchain} from 'ts/blockchain';
-import {RequiredLabel} from 'ts/components/ui/required_label';
+import { RequiredLabel } from 'ts/components/ui/required_label';
+import { colors } from 'ts/utils/colors';
interface AddressInputProps {
disabled?: boolean;
@@ -31,16 +30,14 @@ export class AddressInput extends React.Component<AddressInputProps, AddressInpu
};
}
public componentWillReceiveProps(nextProps: AddressInputProps) {
- if (nextProps.shouldShowIncompleteErrs && this.props.isRequired &&
- this.state.address === '') {
- this.setState({
- errMsg: 'Address is required',
- });
+ if (nextProps.shouldShowIncompleteErrs && this.props.isRequired && this.state.address === '') {
+ this.setState({
+ errMsg: 'Address is required',
+ });
}
}
public render() {
- const label = this.props.isRequired ? <RequiredLabel label={this.props.label} /> :
- this.props.label;
+ const label = this.props.isRequired ? <RequiredLabel label={this.props.label} /> : this.props.label;
const labelDisplay = this.props.shouldHideLabel ? 'hidden' : 'block';
const hintText = this.props.hintText ? this.props.hintText : '';
return (
@@ -51,18 +48,18 @@ 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}
- onChange={this.onOrderTakerAddressUpdated.bind(this)}
+ onChange={this._onOrderTakerAddressUpdated.bind(this)}
/>
</div>
);
}
- private onOrderTakerAddressUpdated(e: any) {
+ private _onOrderTakerAddressUpdated(e: any) {
const address = e.target.value.toLowerCase();
- const isValidAddress = isAddress(address) || address === '';
+ const isValidAddress = addressUtils.isAddress(address) || address === '';
const errMsg = isValidAddress ? '' : 'Invalid ethereum address';
this.setState({
address,
diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx
index 4c15ed4a0..da46db4f4 100644
--- a/packages/website/ts/components/inputs/allowance_toggle.tsx
+++ b/packages/website/ts/components/inputs/allowance_toggle.tsx
@@ -1,12 +1,12 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import Toggle from 'material-ui/Toggle';
import * as React from 'react';
-import {Blockchain} from 'ts/blockchain';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {BalanceErrs, Token, TokenState} from 'ts/types';
-import {errorReporter} from 'ts/utils/error_reporter';
-import {utils} from 'ts/utils/utils';
+import { Blockchain } from 'ts/blockchain';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { BalanceErrs, Token, TokenState } from 'ts/types';
+import { errorReporter } from 'ts/utils/error_reporter';
+import { utils } from 'ts/utils/utils';
const DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1);
@@ -46,22 +46,21 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
<div>
<Toggle
disabled={this.state.isSpinnerVisible}
- toggled={this.isAllowanceSet()}
- onToggle={this.onToggleAllowanceAsync.bind(this, this.props.token)}
+ toggled={this._isAllowanceSet()}
+ onToggle={this._onToggleAllowanceAsync.bind(this)}
/>
</div>
- {this.state.isSpinnerVisible &&
- <div className="pl1" style={{paddingTop: 3}}>
+ {this.state.isSpinnerVisible && (
+ <div className="pl1" style={{ paddingTop: 3 }}>
<i className="zmdi zmdi-spinner zmdi-hc-spin" />
</div>
- }
+ )}
</div>
);
}
- private async onToggleAllowanceAsync() {
+ private async _onToggleAllowanceAsync(): Promise<void> {
if (this.props.userAddress === '') {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
- return false;
}
this.setState({
@@ -69,7 +68,7 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
});
let newAllowanceAmountInBaseUnits = new BigNumber(0);
- if (!this.isAllowanceSet()) {
+ if (!this._isAllowanceSet()) {
newAllowanceAmountInBaseUnits = DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS;
}
try {
@@ -78,17 +77,17 @@ export class AllowanceToggle extends React.Component<AllowanceToggleProps, Allow
this.setState({
isSpinnerVisible: false,
});
- const errMsg = '' + err;
+ const errMsg = `${err}`;
if (_.includes(errMsg, 'User denied transaction')) {
- return false;
+ return;
}
utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack);
- await errorReporter.reportAsync(err);
this.props.onErrorOccurred(BalanceErrs.allowanceSettingFailed);
+ await errorReporter.reportAsync(err);
}
}
- private isAllowanceSet() {
+ private _isAllowanceSet() {
return !this.props.tokenState.allowance.eq(0);
}
}
diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx
index 7ddefc3b9..ddc434b51 100644
--- a/packages/website/ts/components/inputs/balance_bounded_input.tsx
+++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx
@@ -1,12 +1,12 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } 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 {Link} from 'react-router-dom';
-import {RequiredLabel} from 'ts/components/ui/required_label';
-import {InputErrMsg, ValidatedBigNumberCallback, WebsitePaths} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+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 {
label?: string;
@@ -25,8 +25,7 @@ interface BalanceBoundedInputState {
amountString: string;
}
-export class BalanceBoundedInput extends
- React.Component<BalanceBoundedInputProps, BalanceBoundedInputState> {
+export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProps, BalanceBoundedInputState> {
public static defaultProps: Partial<BalanceBoundedInputProps> = {
shouldShowIncompleteErrs: false,
shouldHideVisitBalancesLink: false,
@@ -35,7 +34,7 @@ export class BalanceBoundedInput extends
super(props);
const amountString = this.props.amount ? this.props.amount.toString() : '';
this.state = {
- errMsg: this.validate(amountString, props.balance),
+ errMsg: this._validate(amountString, props.balance),
amountString,
};
}
@@ -57,14 +56,14 @@ export class BalanceBoundedInput extends
if (shouldResetState) {
const amountString = nextProps.amount.toString();
this.setState({
- errMsg: this.validate(amountString, nextProps.balance),
+ errMsg: this._validate(amountString, nextProps.balance),
amountString,
});
}
} else if (isCurrentAmountNumeric) {
const amountString = '';
this.setState({
- errMsg: this.validate(amountString, nextProps.balance),
+ errMsg: this._validate(amountString, nextProps.balance),
amountString,
});
}
@@ -74,39 +73,42 @@ export class BalanceBoundedInput extends
if (this.props.shouldShowIncompleteErrs && this.state.amountString === '') {
errorText = 'This field is required';
}
- let label: React.ReactNode|string = '';
+ let label: React.ReactNode | string = '';
if (!_.isUndefined(this.props.label)) {
- label = <RequiredLabel label={this.props.label}/>;
+ label = <RequiredLabel label={this.props.label} />;
}
return (
<TextField
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>}
- onChange={this.onValueChange.bind(this)}
- underlineStyle={{width: 'calc(100% + 50px)'}}
+ hintText={<span style={{ textTransform: 'capitalize' }}>amount</span>}
+ onChange={this._onValueChange.bind(this)}
+ underlineStyle={{ width: 'calc(100% + 50px)' }}
/>
);
}
- private onValueChange(e: any, amountString: string) {
- const errMsg = this.validate(amountString, this.props.balance);
- this.setState({
- amountString,
- errMsg,
- }, () => {
- const isValid = _.isUndefined(errMsg);
- if (utils.isNumeric(amountString)) {
- this.props.onChange(isValid, new BigNumber(amountString));
- } else {
- this.props.onChange(isValid);
- }
- });
+ private _onValueChange(e: any, amountString: string) {
+ const errMsg = this._validate(amountString, this.props.balance);
+ this.setState(
+ {
+ amountString,
+ errMsg,
+ },
+ () => {
+ const isValid = _.isUndefined(errMsg);
+ if (utils.isNumeric(amountString)) {
+ this.props.onChange(isValid, new BigNumber(amountString));
+ } else {
+ this.props.onChange(isValid);
+ }
+ },
+ );
}
- private validate(amountString: string, balance: BigNumber): InputErrMsg {
+ private _validate(amountString: string, balance: BigNumber): InputErrMsg {
if (!utils.isNumeric(amountString)) {
return amountString !== '' ? 'Must be a number' : '';
}
@@ -115,17 +117,12 @@ export class BalanceBoundedInput extends
return 'Cannot be zero';
}
if (this.props.shouldCheckBalance && amount.gt(balance)) {
- return (
- <span>
- Insufficient balance.{' '}
- {this.renderIncreaseBalanceLink()}
- </span>
- );
+ return <span>Insufficient balance. {this._renderIncreaseBalanceLink()}</span>;
}
const errMsg = _.isUndefined(this.props.validate) ? undefined : this.props.validate(amount);
return errMsg;
}
- private renderIncreaseBalanceLink() {
+ private _renderIncreaseBalanceLink() {
if (this.props.shouldHideVisitBalancesLink) {
return null;
}
@@ -133,25 +130,19 @@ export class BalanceBoundedInput extends
const increaseBalanceText = 'Increase balance';
const linkStyle = {
cursor: 'pointer',
- color: colors.grey900,
+ color: colors.darkestGrey,
textDecoration: 'underline',
display: 'inline',
};
if (_.isUndefined(this.props.onVisitBalancesPageClick)) {
return (
- <Link
- to={`${WebsitePaths.Portal}/balances`}
- style={linkStyle}
- >
+ <Link to={`${WebsitePaths.Portal}/balances`} style={linkStyle}>
{increaseBalanceText}
</Link>
);
} else {
return (
- <div
- onClick={this.props.onVisitBalancesPageClick}
- style={linkStyle}
- >
+ <div onClick={this.props.onVisitBalancesPageClick} style={linkStyle}>
{increaseBalanceText}
</div>
);
diff --git a/packages/website/ts/components/inputs/eth_amount_input.tsx b/packages/website/ts/components/inputs/eth_amount_input.tsx
index 5c5e23eef..a66f92c8c 100644
--- a/packages/website/ts/components/inputs/eth_amount_input.tsx
+++ b/packages/website/ts/components/inputs/eth_amount_input.tsx
@@ -1,10 +1,10 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
-import {BalanceBoundedInput} from 'ts/components/inputs/balance_bounded_input';
-import {ValidatedBigNumberCallback} from 'ts/types';
-import {constants} from 'ts/utils/constants';
+import { BalanceBoundedInput } from 'ts/components/inputs/balance_bounded_input';
+import { ValidatedBigNumberCallback } from 'ts/types';
+import { constants } from 'ts/utils/constants';
interface EthAmountInputProps {
label?: string;
@@ -21,31 +21,29 @@ 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) :
- undefined;
+ const amount = this.props.amount
+ ? ZeroEx.toUnitAmount(this.props.amount, constants.DECIMAL_PLACES_ETH)
+ : undefined;
return (
- <div className="flex overflow-hidden" style={{height: 63}}>
+ <div className="flex overflow-hidden" style={{ height: 63 }}>
<BalanceBoundedInput
label={this.props.label}
balance={this.props.balance}
amount={amount}
- onChange={this.onChange.bind(this)}
+ onChange={this._onChange.bind(this)}
shouldCheckBalance={this.props.shouldCheckBalance}
shouldShowIncompleteErrs={this.props.shouldShowIncompleteErrs}
onVisitBalancesPageClick={this.props.onVisitBalancesPageClick}
shouldHideVisitBalancesLink={this.props.shouldHideVisitBalancesLink}
/>
- <div style={{paddingTop: _.isUndefined(this.props.label) ? 15 : 40}}>
- ETH
- </div>
+ <div style={{ paddingTop: _.isUndefined(this.props.label) ? 15 : 40 }}>ETH</div>
</div>
);
}
- private onChange(isValid: boolean, amount?: BigNumber) {
- const baseUnitAmountIfExists = _.isUndefined(amount) ?
- undefined :
- ZeroEx.toBaseUnitAmount(amount, constants.ETH_DECIMAL_PLACES);
+ private _onChange(isValid: boolean, amount?: BigNumber) {
+ const baseUnitAmountIfExists = _.isUndefined(amount)
+ ? undefined
+ : ZeroEx.toBaseUnitAmount(amount, constants.DECIMAL_PLACES_ETH);
this.props.onChange(isValid, baseUnitAmountIfExists);
}
}
diff --git a/packages/website/ts/components/inputs/expiration_input.tsx b/packages/website/ts/components/inputs/expiration_input.tsx
index d3d3d258d..e473648d2 100644
--- a/packages/website/ts/components/inputs/expiration_input.tsx
+++ b/packages/website/ts/components/inputs/expiration_input.tsx
@@ -1,10 +1,10 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import DatePicker from 'material-ui/DatePicker';
import TimePicker from 'material-ui/TimePicker';
import * as moment from 'moment';
import * as React from 'react';
-import {utils} from 'ts/utils/utils';
+import { utils } from 'ts/utils/utils';
interface ExpirationInputProps {
orderExpiryTimestamp: BigNumber;
@@ -17,11 +17,11 @@ interface ExpirationInputState {
}
export class ExpirationInput extends React.Component<ExpirationInputProps, ExpirationInputState> {
- private earliestPickableMoment: moment.Moment;
+ private _earliestPickableMoment: moment.Moment;
constructor(props: ExpirationInputProps) {
super(props);
// Set the earliest pickable date to today at 00:00, so users can only pick the current or later dates
- this.earliestPickableMoment = moment().startOf('day');
+ this._earliestPickableMoment = moment().startOf('day');
const expirationMoment = utils.convertToMomentFromUnixTimestamp(props.orderExpiryTimestamp);
const initialOrderExpiryTimestamp = utils.initialOrderExpiryUnixTimestampSec();
const didUserSetExpiry = !initialOrderExpiryTimestamp.eq(props.orderExpiryTimestamp);
@@ -42,13 +42,10 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
mode="landscape"
autoOk={true}
value={date}
- onChange={this.onDateChanged.bind(this)}
- shouldDisableDate={this.shouldDisableDate.bind(this)}
+ onChange={this._onDateChanged.bind(this)}
+ shouldDisableDate={this._shouldDisableDate.bind(this)}
/>
- <div
- className="absolute"
- style={{fontSize: 20, right: 40, top: 13, pointerEvents: 'none'}}
- >
+ <div className="absolute" style={{ fontSize: 20, right: 40, top: 13, pointerEvents: 'none' }}>
<i className="zmdi zmdi-calendar" />
</div>
</div>
@@ -58,29 +55,24 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
hintText="Time"
autoOk={true}
value={time}
- onChange={this.onTimeChanged.bind(this)}
+ onChange={this._onTimeChanged.bind(this)}
/>
- <div
- className="absolute"
- style={{fontSize: 20, right: 9, top: 13, pointerEvents: 'none'}}
- >
+ <div className="absolute" style={{ fontSize: 20, right: 9, top: 13, pointerEvents: 'none' }}>
<i className="zmdi zmdi-time" />
</div>
</div>
- <div
- onClick={this.clearDates.bind(this)}
- className="col col-1 pt2"
- style={{textAlign: 'right'}}
- >
- <i style={{fontSize: 16, cursor: 'pointer'}} className="zmdi zmdi-close" />
+ <div onClick={this._clearDates.bind(this)} className="col col-1 pt2" style={{ textAlign: 'right' }}>
+ <i style={{ fontSize: 16, cursor: 'pointer' }} className="zmdi zmdi-close" />
</div>
</div>
);
}
- private shouldDisableDate(date: Date): boolean {
- return moment(date).startOf('day').isBefore(this.earliestPickableMoment);
+ private _shouldDisableDate(date: Date): boolean {
+ return moment(date)
+ .startOf('day')
+ .isBefore(this._earliestPickableMoment);
}
- private clearDates() {
+ private _clearDates() {
this.setState({
dateMoment: undefined,
timeMoment: undefined,
@@ -88,7 +80,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
const defaultDateTime = utils.initialOrderExpiryUnixTimestampSec();
this.props.updateOrderExpiry(defaultDateTime);
}
- private onDateChanged(e: any, date: Date) {
+ private _onDateChanged(e: any, date: Date) {
const dateMoment = moment(date);
this.setState({
dateMoment,
@@ -96,12 +88,12 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
const timestamp = utils.convertToUnixTimestampSeconds(dateMoment, this.state.timeMoment);
this.props.updateOrderExpiry(timestamp);
}
- private onTimeChanged(e: any, time: Date) {
+ private _onTimeChanged(e: any, time: Date) {
const timeMoment = moment(time);
this.setState({
timeMoment,
});
- const dateMoment = _.isUndefined(this.state.dateMoment) ? moment() : this.state.dateMoment;
+ const dateMoment = _.isUndefined(this.state.dateMoment) ? moment() : this.state.dateMoment;
const timestamp = utils.convertToUnixTimestampSeconds(dateMoment, timeMoment);
this.props.updateOrderExpiry(timestamp);
}
diff --git a/packages/website/ts/components/inputs/hash_input.tsx b/packages/website/ts/components/inputs/hash_input.tsx
index 25e7b5009..5a3d34fe6 100644
--- a/packages/website/ts/components/inputs/hash_input.tsx
+++ b/packages/website/ts/components/inputs/hash_input.tsx
@@ -1,11 +1,11 @@
-import {Order, ZeroEx} from '0x.js';
+import { Order, ZeroEx } from '0x.js';
import * as _ from 'lodash';
import * as React from 'react';
import ReactTooltip = require('react-tooltip');
-import {Blockchain} from 'ts/blockchain';
-import {FakeTextField} from 'ts/components/ui/fake_text_field';
-import {HashData, Styles} from 'ts/types';
-import {constants} from 'ts/utils/constants';
+import { Blockchain } from 'ts/blockchain';
+import { FakeTextField } from 'ts/components/ui/fake_text_field';
+import { HashData, Styles } from 'ts/types';
+import { constants } from 'ts/utils/constants';
const styles: Styles = {
textField: {
@@ -27,15 +27,11 @@ interface HashInputState {}
export class HashInput extends React.Component<HashInputProps, HashInputState> {
public render() {
- const msgHashHex = this.props.blockchainIsLoaded ? this.generateMessageHashHex() : '';
+ const msgHashHex = this.props.blockchainIsLoaded ? this._generateMessageHashHex() : '';
return (
<div>
<FakeTextField label={this.props.label}>
- <div
- style={styles.textField}
- data-tip={true}
- data-for="hashTooltip"
- >
+ <div style={styles.textField} data-tip={true} data-for="hashTooltip">
{msgHashHex}
</div>
</FakeTextField>
@@ -43,7 +39,7 @@ export class HashInput extends React.Component<HashInputProps, HashInputState> {
</div>
);
}
- private generateMessageHashHex() {
+ private _generateMessageHashHex() {
const exchangeContractAddress = this.props.blockchain.getExchangeContractAddressIfExists();
const hashData = this.props.hashData;
const order: Order = {
diff --git a/packages/website/ts/components/inputs/identicon_address_input.tsx b/packages/website/ts/components/inputs/identicon_address_input.tsx
index 692a092d9..4cf9af64d 100644
--- a/packages/website/ts/components/inputs/identicon_address_input.tsx
+++ b/packages/website/ts/components/inputs/identicon_address_input.tsx
@@ -1,11 +1,9 @@
import * as _ from 'lodash';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {Blockchain} from 'ts/blockchain';
-import {AddressInput} from 'ts/components/inputs/address_input';
-import {Identicon} from 'ts/components/ui/identicon';
-import {InputLabel} from 'ts/components/ui/input_label';
-import {RequiredLabel} from 'ts/components/ui/required_label';
+import { AddressInput } from 'ts/components/inputs/address_input';
+import { Identicon } from 'ts/components/ui/identicon';
+import { InputLabel } from 'ts/components/ui/input_label';
+import { RequiredLabel } from 'ts/components/ui/required_label';
interface IdenticonAddressInputProps {
initialAddress: string;
@@ -26,28 +24,27 @@ export class IdenticonAddressInput extends React.Component<IdenticonAddressInput
};
}
public render() {
- const label = this.props.isRequired ? <RequiredLabel label={this.props.label} /> :
- this.props.label;
+ const label = this.props.isRequired ? <RequiredLabel label={this.props.label} /> : this.props.label;
return (
- <div className="relative" style={{width: '100%'}}>
+ <div className="relative" style={{ width: '100%' }}>
<InputLabel text={label} />
<div className="flex">
- <div className="col col-1 pb1 pr1" style={{paddingTop: 13}}>
+ <div className="col col-1 pb1 pr1" style={{ paddingTop: 13 }}>
<Identicon address={this.state.address} diameter={26} />
</div>
- <div className="col col-11 pb1 pl1" style={{height: 65}}>
+ <div className="col col-11 pb1 pl1" style={{ height: 65 }}>
<AddressInput
hintText="e.g 0x75bE4F78AA3699B3A348c84bDB2a96c3Db..."
shouldHideLabel={true}
initialAddress={this.props.initialAddress}
- updateAddress={this.updateAddress.bind(this)}
+ updateAddress={this._updateAddress.bind(this)}
/>
</div>
</div>
</div>
);
}
- private updateAddress(address?: string): void {
+ private _updateAddress(address?: string): void {
this.setState({
address,
});
diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx
index f39341a4f..63966d759 100644
--- a/packages/website/ts/components/inputs/token_amount_input.tsx
+++ b/packages/website/ts/components/inputs/token_amount_input.tsx
@@ -1,16 +1,16 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
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 { 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 {
- label: string;
token: Token;
tokenState: TokenState;
+ label?: string;
amount?: BigNumber;
shouldShowIncompleteErrs: boolean;
shouldCheckBalance: boolean;
@@ -19,51 +19,52 @@ interface TokenAmountInputProps {
onVisitBalancesPageClick?: () => void;
}
-interface TokenAmountInputState {}
+interface TokenAmountInputState {}
export class TokenAmountInput extends React.Component<TokenAmountInputProps, TokenAmountInputState> {
public render() {
- const amount = this.props.amount ?
- ZeroEx.toUnitAmount(this.props.amount, this.props.token.decimals) :
- undefined;
+ const amount = this.props.amount
+ ? ZeroEx.toUnitAmount(this.props.amount, this.props.token.decimals)
+ : undefined;
+ const hasLabel = !_.isUndefined(this.props.label);
return (
- <div className="flex overflow-hidden" style={{height: 84}}>
+ <div className="flex overflow-hidden" style={{ height: hasLabel ? 84 : 62 }}>
<BalanceBoundedInput
label={this.props.label}
amount={amount}
balance={ZeroEx.toUnitAmount(this.props.tokenState.balance, this.props.token.decimals)}
- onChange={this.onChange.bind(this)}
- validate={this.validate.bind(this)}
+ onChange={this._onChange.bind(this)}
+ validate={this._validate.bind(this)}
shouldCheckBalance={this.props.shouldCheckBalance}
shouldShowIncompleteErrs={this.props.shouldShowIncompleteErrs}
onVisitBalancesPageClick={this.props.onVisitBalancesPageClick}
/>
- <div style={{paddingTop: 39}}>
- {this.props.token.symbol}
- </div>
+ <div style={{ paddingTop: hasLabel ? 39 : 14 }}>{this.props.token.symbol}</div>
</div>
);
}
- private onChange(isValid: boolean, amount?: BigNumber) {
+ private _onChange(isValid: boolean, amount?: BigNumber) {
let baseUnitAmount;
if (!_.isUndefined(amount)) {
baseUnitAmount = ZeroEx.toBaseUnitAmount(amount, this.props.token.decimals);
}
this.props.onChange(isValid, baseUnitAmount);
}
- private validate(amount: BigNumber): InputErrMsg {
+ private _validate(amount: BigNumber): InputErrMsg {
if (this.props.shouldCheckAllowance && amount.gt(this.props.tokenState.allowance)) {
return (
<span>
Insufficient allowance.{' '}
<Link
to={`${WebsitePaths.Portal}/balances`}
- style={{cursor: 'pointer', color: colors.grey900}}
+ style={{ cursor: 'pointer', color: colors.darkestGrey }}
>
- Set allowance
+ Set allowance
</Link>
</span>
);
+ } else {
+ return undefined;
}
}
}
diff --git a/packages/website/ts/components/inputs/token_input.tsx b/packages/website/ts/components/inputs/token_input.tsx
index 8daa84650..5df19b28c 100644
--- a/packages/website/ts/components/inputs/token_input.tsx
+++ b/packages/website/ts/components/inputs/token_input.tsx
@@ -1,13 +1,13 @@
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';
-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, TokenState} from 'ts/types';
+import { Blockchain } from 'ts/blockchain';
+import { AssetPicker } from 'ts/components/generate_order/asset_picker';
+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;
@@ -51,18 +51,15 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState
</div>
<Paper
zDepth={1}
- style={{cursor: 'pointer'}}
- onMouseEnter={this.onToggleHover.bind(this, true)}
- onMouseLeave={this.onToggleHover.bind(this, false)}
- onClick={this.onAssetClicked.bind(this)}
+ style={{ cursor: 'pointer' }}
+ onMouseEnter={this._onToggleHover.bind(this, true)}
+ onMouseLeave={this._onToggleHover.bind(this, false)}
+ onClick={this._onAssetClicked.bind(this)}
>
- <div
- className="mx-auto pt2"
- style={{width: TOKEN_ICON_DIMENSION, ...iconStyles}}
- >
+ <div className="mx-auto pt2" style={{ width: TOKEN_ICON_DIMENSION, ...iconStyles }}>
<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>
@@ -73,13 +70,13 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState
dispatcher={this.props.dispatcher}
isOpen={this.state.isPickerOpen}
currentTokenAddress={this.props.assetToken.address}
- onTokenChosen={this.onTokenChosen.bind(this)}
+ onTokenChosen={this._onTokenChosen.bind(this)}
tokenByAddress={this.props.tokenByAddress}
/>
</div>
);
}
- private onTokenChosen(tokenAddress: string) {
+ private _onTokenChosen(tokenAddress: string) {
const assetToken: AssetToken = {
address: tokenAddress,
amount: this.props.assetToken.amount,
@@ -89,13 +86,13 @@ export class TokenInput extends React.Component<TokenInputProps, TokenInputState
isPickerOpen: false,
});
}
- private onToggleHover(isHoveringIcon: boolean) {
+ private _onToggleHover(isHoveringIcon: boolean) {
this.setState({
isHoveringIcon,
});
}
- private onAssetClicked() {
- if (this.props.blockchainErr !== '') {
+ private _onAssetClicked() {
+ if (this.props.blockchainErr !== BlockchainErrs.NoError) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return;
}
diff --git a/packages/website/ts/components/order_json.tsx b/packages/website/ts/components/order_json.tsx
index 073abe419..1b6b32a04 100644
--- a/packages/website/ts/components/order_json.tsx
+++ b/packages/website/ts/components/order_json.tsx
@@ -1,15 +1,14 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import Paper from 'material-ui/Paper';
-import {colors} from 'material-ui/styles';
import TextField from 'material-ui/TextField';
import * as React from 'react';
-import {CopyIcon} from 'ts/components/ui/copy_icon';
-import {Order, SideToAssetToken, SignatureData, TokenByAddress, WebsitePaths} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
-import {errorReporter} from 'ts/utils/error_reporter';
-import {utils} from 'ts/utils/utils';
+import { CopyIcon } from 'ts/components/ui/copy_icon';
+import { SideToAssetToken, SignatureData, TokenByAddress, WebsitePaths } from 'ts/types';
+import { configs } from 'ts/utils/configs';
+import { constants } from 'ts/utils/constants';
+import { errorReporter } from 'ts/utils/error_reporter';
+import { utils } from 'ts/utils/utils';
interface OrderJSONProps {
exchangeContractIfExists: string;
@@ -37,73 +36,79 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
shareLink: '',
};
// tslint:disable-next-line:no-floating-promises
- this.setShareLinkAsync();
+ this._setShareLinkAsync();
}
public render() {
- const order = utils.generateOrder(this.props.networkId, this.props.exchangeContractIfExists,
- this.props.sideToAssetToken, this.props.orderExpiryTimestamp,
- this.props.orderTakerAddress, this.props.orderMakerAddress,
- this.props.orderMakerFee, this.props.orderTakerFee,
- this.props.orderFeeRecipient, this.props.orderSignatureData,
- this.props.tokenByAddress, this.props.orderSalt);
+ const order = utils.generateOrder(
+ this.props.networkId,
+ this.props.exchangeContractIfExists,
+ this.props.sideToAssetToken,
+ this.props.orderExpiryTimestamp,
+ this.props.orderTakerAddress,
+ this.props.orderMakerAddress,
+ this.props.orderMakerFee,
+ this.props.orderTakerFee,
+ this.props.orderFeeRecipient,
+ this.props.orderSignatureData,
+ this.props.tokenByAddress,
+ this.props.orderSalt,
+ );
const orderJSON = JSON.stringify(order);
return (
<div>
<div className="pb2">
- You have successfully generated and cryptographically signed an order! The{' '}
- following JSON contains the order parameters and cryptographic signature that{' '}
- your counterparty will need to execute a trade with you.
+ You have successfully generated and cryptographically signed an order! The following JSON contains
+ the order parameters and cryptographic signature that your counterparty will need to execute a trade
+ with you.
</div>
<div className="pb2 flex">
- <div
- className="inline-block pl1"
- style={{top: 1}}
- >
+ <div className="inline-block pl1" style={{ top: 1 }}>
<CopyIcon data={orderJSON} callToAction="Copy" />
</div>
</div>
<Paper className="center overflow-hidden">
<TextField
id="orderJSON"
- style={{width: 710}}
+ style={{ width: 710 }}
value={JSON.stringify(order, null, '\t')}
multiLine={true}
rows={2}
rowsMax={8}
- underlineStyle={{display: 'none'}}
+ underlineStyle={{ display: 'none' }}
/>
</Paper>
<div className="pt3 pb2 center">
+ <div>Share your signed order!</div>
<div>
- Share your signed order!
- </div>
- <div>
- <div className="mx-auto overflow-hidden" style={{width: 152}}>
- <TextField
- id={`${this.state.shareLink}-bitly`}
- value={this.state.shareLink}
- />
+ <div className="mx-auto overflow-hidden" style={{ width: 152 }}>
+ <TextField id={`${this.state.shareLink}-bitly`} value={this.state.shareLink} />
</div>
</div>
- <div className="mx-auto pt1 flex" style={{width: 91}}>
+ <div className="mx-auto pt1 flex" style={{ width: 91 }}>
<div>
<i
- style={{cursor: 'pointer', fontSize: 29}}
- onClick={this.shareViaFacebook.bind(this)}
+ style={{ cursor: 'pointer', fontSize: 29 }}
+ onClick={this._shareViaFacebook.bind(this)}
className="zmdi zmdi-facebook-box"
/>
</div>
- <div className="pl1" style={{position: 'relative', width: 28}}>
+ <div className="pl1" style={{ position: 'relative', width: 28 }}>
<i
- style={{cursor: 'pointer', fontSize: 32, position: 'absolute', top: -2, left: 8}}
- onClick={this.shareViaEmailAsync.bind(this)}
+ style={{
+ cursor: 'pointer',
+ fontSize: 32,
+ position: 'absolute',
+ top: -2,
+ left: 8,
+ }}
+ onClick={this._shareViaEmailAsync.bind(this)}
className="zmdi zmdi-email"
/>
</div>
<div className="pl1">
<i
- style={{cursor: 'pointer', fontSize: 29}}
- onClick={this.shareViaTwitterAsync.bind(this)}
+ style={{ cursor: 'pointer', fontSize: 29 }}
+ onClick={this._shareViaTwitterAsync.bind(this)}
className="zmdi zmdi-twitter-box"
/>
</div>
@@ -112,35 +117,38 @@ export class OrderJSON extends React.Component<OrderJSONProps, OrderJSONState> {
</div>
);
}
- private async shareViaTwitterAsync() {
+ private async _shareViaTwitterAsync() {
const tweetText = encodeURIComponent(`Fill my order using the 0x protocol: ${this.state.shareLink}`);
window.open(`https://twitter.com/intent/tweet?text=${tweetText}`, 'Share your order', 'width=500,height=400');
}
- private async shareViaFacebook() {
- (window as any).FB.ui({
- display: 'popup',
- href: this.state.shareLink,
- method: 'share',
- }, _.noop);
+ private async _shareViaFacebook() {
+ (window as any).FB.ui(
+ {
+ display: 'popup',
+ href: this.state.shareLink,
+ method: 'share',
+ },
+ _.noop,
+ );
}
- private async shareViaEmailAsync() {
- const encodedSubject = encodeURIComponent('Let\'s trade using the 0x protocol');
+ private async _shareViaEmailAsync() {
+ const encodedSubject = encodeURIComponent("Let's trade using the 0x protocol");
const encodedBody = encodeURIComponent(`I generated an order with the 0x protocol.
You can see and fill it here: ${this.state.shareLink}`);
const mailToLink = `mailto:mail@example.org?subject=${encodedSubject}&body=${encodedBody}`;
window.open(mailToLink, '_blank');
}
- private async setShareLinkAsync() {
- const shareLink = await this.generateShareLinkAsync();
+ private async _setShareLinkAsync() {
+ const shareLink = await this._generateShareLinkAsync();
this.setState({
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;
+ private async _generateShareLinkAsync(): Promise<string> {
+ const longUrl = encodeURIComponent(this._getOrderUrl());
+ 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);
@@ -150,14 +158,23 @@ You can see and fill it here: ${this.state.shareLink}`);
await errorReporter.reportAsync(new Error(`Bitly returned non-200: ${JSON.stringify(response)}`));
return '';
}
- return (bodyObj).data.url;
+ return bodyObj.data.url;
}
- private getOrderUrl() {
- const order = utils.generateOrder(this.props.networkId, this.props.exchangeContractIfExists,
- this.props.sideToAssetToken, this.props.orderExpiryTimestamp, this.props.orderTakerAddress,
- this.props.orderMakerAddress, this.props.orderMakerFee, this.props.orderTakerFee,
- this.props.orderFeeRecipient, this.props.orderSignatureData, this.props.tokenByAddress,
- this.props.orderSalt);
+ private _getOrderUrl() {
+ const order = utils.generateOrder(
+ this.props.networkId,
+ this.props.exchangeContractIfExists,
+ this.props.sideToAssetToken,
+ this.props.orderExpiryTimestamp,
+ this.props.orderTakerAddress,
+ this.props.orderMakerAddress,
+ this.props.orderMakerFee,
+ this.props.orderTakerFee,
+ this.props.orderFeeRecipient,
+ this.props.orderSignatureData,
+ this.props.tokenByAddress,
+ this.props.orderSalt,
+ );
const orderJSONString = JSON.stringify(order);
const orderUrl = `${configs.BASE_URL}${WebsitePaths.Portal}/fill?order=${orderJSONString}`;
return orderUrl;
diff --git a/packages/website/ts/components/portal.tsx b/packages/website/ts/components/portal.tsx
index 62a5d2eac..e2e28e8b6 100644
--- a/packages/website/ts/components/portal.tsx
+++ b/packages/website/ts/components/portal.tsx
@@ -1,44 +1,41 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import Paper from 'material-ui/Paper';
-import RaisedButton from 'material-ui/RaisedButton';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
-import {Route, Switch} from 'react-router-dom';
-import {Blockchain} from 'ts/blockchain';
-import {BlockchainErrDialog} from 'ts/components/dialogs/blockchain_err_dialog';
-import {PortalDisclaimerDialog} from 'ts/components/dialogs/portal_disclaimer_dialog';
-import {FillOrder} from 'ts/components/fill_order';
-import {Footer} from 'ts/components/footer';
-import {PortalMenu} from 'ts/components/portal_menu';
-import {TokenBalances} from 'ts/components/token_balances';
-import {TopBar} from 'ts/components/top_bar';
-import {TradeHistory} from 'ts/components/trade_history/trade_history';
-import {FlashMessage} from 'ts/components/ui/flash_message';
-import {Loading} from 'ts/components/ui/loading';
-import {GenerateOrderForm} from 'ts/containers/generate_order_form';
-import {localStorage} from 'ts/local_storage/local_storage';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {State} from 'ts/redux/reducer';
-import {orderSchema} from 'ts/schemas/order_schema';
-import {SchemaValidator} from 'ts/schemas/validator';
+import { Route, Switch } from 'react-router-dom';
+import { Blockchain } from 'ts/blockchain';
+import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog';
+import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_dialog';
+import { WrappedEthSectionNoticeDialog } from 'ts/components/dialogs/wrapped_eth_section_notice_dialog';
+import { EthWrappers } from 'ts/components/eth_wrappers';
+import { FillOrder } from 'ts/components/fill_order';
+import { Footer } from 'ts/components/footer';
+import { PortalMenu } from 'ts/components/portal_menu';
+import { TokenBalances } from 'ts/components/token_balances';
+import { TopBar } from 'ts/components/top_bar';
+import { TradeHistory } from 'ts/components/trade_history/trade_history';
+import { FlashMessage } from 'ts/components/ui/flash_message';
+import { Loading } from 'ts/components/ui/loading';
+import { GenerateOrderForm } from 'ts/containers/generate_order_form';
+import { localStorage } from 'ts/local_storage/local_storage';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { orderSchema } from 'ts/schemas/order_schema';
+import { SchemaValidator } from 'ts/schemas/validator';
import {
BlockchainErrs,
- Fill,
HashData,
Order,
ScreenWidths,
- Side,
- Styles,
Token,
TokenByAddress,
TokenStateByAddress,
WebsitePaths,
} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+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 THROTTLE_TIMEOUT = 100;
@@ -60,69 +57,57 @@ export interface PortalAllProps {
shouldBlockchainErrDialogBeOpen: boolean;
userSuppliedOrderCache: Order;
location: Location;
- flashMessage?: string|React.ReactNode;
+ flashMessage?: string | React.ReactNode;
}
interface PortalAllState {
prevNetworkId: number;
prevNodeVersion: string;
prevUserAddress: string;
- hasAcceptedDisclaimer: boolean;
+ prevPathname: string;
+ isDisclaimerDialogOpen: boolean;
+ isWethNoticeDialogOpen: boolean;
}
-const styles: Styles = {
- button: {
- color: 'white',
- },
- headline: {
- fontSize: 20,
- fontWeight: 400,
- marginBottom: 12,
- paddingTop: 16,
- },
- inkBar: {
- background: colors.amber600,
- },
- menuItem: {
- padding: '0px 16px 0px 48px',
- },
- tabItemContainer: {
- background: colors.blueGrey500,
- borderRadius: '4px 4px 0 0',
- },
-};
-
export class Portal extends React.Component<PortalAllProps, PortalAllState> {
- private blockchain: Blockchain;
- private sharedOrderIfExists: Order;
- private throttledScreenWidthUpdate: () => void;
+ private _blockchain: Blockchain;
+ private _sharedOrderIfExists: Order;
+ private _throttledScreenWidthUpdate: () => void;
+ public static hasAlreadyDismissedWethNotice() {
+ const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE);
+ const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) && !_.isEmpty(didDismissWethNotice);
+ return hasAlreadyDismissedWethNotice;
+ }
constructor(props: PortalAllProps) {
super(props);
- this.sharedOrderIfExists = this.getSharedOrderIfExists();
- this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
+ this._sharedOrderIfExists = this._getSharedOrderIfExists();
+ this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
+
+ const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`);
+ const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
+
+ const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER);
+ const hasAcceptedDisclaimer =
+ !_.isUndefined(didAcceptPortalDisclaimer) && !_.isEmpty(didAcceptPortalDisclaimer);
this.state = {
prevNetworkId: this.props.networkId,
prevNodeVersion: this.props.nodeVersion,
prevUserAddress: this.props.userAddress,
- hasAcceptedDisclaimer: false,
+ prevPathname: this.props.location.pathname,
+ isDisclaimerDialogOpen: !hasAcceptedDisclaimer,
+ isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances,
};
}
public componentDidMount() {
- window.addEventListener('resize', this.throttledScreenWidthUpdate);
+ window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0);
}
public componentWillMount() {
- this.blockchain = new Blockchain(this.props.dispatcher);
- const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY);
- const hasAcceptedDisclaimer = !_.isUndefined(didAcceptPortalDisclaimer) &&
- !_.isEmpty(didAcceptPortalDisclaimer);
- this.setState({
- hasAcceptedDisclaimer,
- });
+ this._blockchain = new Blockchain(this.props.dispatcher);
}
public componentWillUnmount() {
- this.blockchain.destroy();
- window.removeEventListener('resize', this.throttledScreenWidthUpdate);
+ this._blockchain.destroy();
+ window.removeEventListener('resize', this._throttledScreenWidthUpdate);
// We re-set the entire redux state when the portal is unmounted so that when it is re-rendered
// the initialization process always occurs from the same base state. This helps avoid
// initialization inconsistencies (i.e While the portal was unrendered, the user might have
@@ -132,19 +117,18 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
public componentWillReceiveProps(nextProps: PortalAllProps) {
if (nextProps.networkId !== this.state.prevNetworkId) {
// tslint:disable-next-line:no-floating-promises
- this.blockchain.networkIdUpdatedFireAndForgetAsync(nextProps.networkId);
+ this._blockchain.networkIdUpdatedFireAndForgetAsync(nextProps.networkId);
this.setState({
prevNetworkId: nextProps.networkId,
});
}
if (nextProps.userAddress !== this.state.prevUserAddress) {
// tslint:disable-next-line:no-floating-promises
- this.blockchain.userAddressUpdatedFireAndForgetAsync(nextProps.userAddress);
- if (!_.isEmpty(nextProps.userAddress) &&
- nextProps.blockchainIsLoaded) {
+ this._blockchain.userAddressUpdatedFireAndForgetAsync(nextProps.userAddress);
+ if (!_.isEmpty(nextProps.userAddress) && nextProps.blockchainIsLoaded) {
const tokens = _.values(nextProps.tokenByAddress);
// tslint:disable-next-line:no-floating-promises
- this.updateBalanceAndAllowanceWithLoadingScreenAsync(tokens);
+ this._updateBalanceAndAllowanceWithLoadingScreenAsync(tokens);
}
this.setState({
prevUserAddress: nextProps.userAddress,
@@ -152,105 +136,128 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
}
if (nextProps.nodeVersion !== this.state.prevNodeVersion) {
// tslint:disable-next-line:no-floating-promises
- this.blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion);
+ this._blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion);
+ }
+ if (nextProps.location.pathname !== this.state.prevPathname) {
+ const isViewingBalances = _.includes(nextProps.location.pathname, `${WebsitePaths.Portal}/balances`);
+ const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
+ this.setState({
+ prevPathname: nextProps.location.pathname,
+ isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances,
+ });
}
}
public render() {
- const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher
- .updateShouldBlockchainErrDialogBeOpen.bind(this.props.dispatcher);
+ const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen.bind(
+ this.props.dispatcher,
+ );
const portalStyle: React.CSSProperties = {
minHeight: '100vh',
display: 'flex',
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"/>
+ <DocumentTitle title="0x Portal DApp" />
<TopBar
userAddress={this.props.userAddress}
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">
- <img
- src="/images/zrx_token.png"
- style={{width: 150}}
- />
+ <img src="/images/zrx_token.png" style={{ width: 150 }} />
</div>
<div>
0x portal is currently unavailable on the Ethereum mainnet.
- <div>
- To try it out, switch to the Kovan test network
- (networkId: 42).
- </div>
- <div className="py2">
- Check back soon!
- </div>
+ <div>To try it out, switch to the Kovan test network (networkId: 42).</div>
+ <div className="py2">Check back soon!</div>
</div>
- </div> :
+ </div>
+ ) : (
<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'}}
- >
- <PortalMenu menuItemStyle={{color: 'white'}} />
+ <div className="col col-2 pr2 pt1 sm-hide xs-hide" style={portalMenuContainerStyle}>
+ <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}}>
- {this.props.blockchainIsLoaded ?
+ <div className="py2" style={{ backgroundColor: colors.grey50 }}>
+ {this.props.blockchainIsLoaded ? (
<Switch>
<Route
+ path={`${WebsitePaths.Portal}/weth`}
+ render={this._renderEthWrapper.bind(this)}
+ />
+ <Route
path={`${WebsitePaths.Portal}/fill`}
- render={this.renderFillOrder.bind(this)}
+ render={this._renderFillOrder.bind(this)}
/>
<Route
path={`${WebsitePaths.Portal}/balances`}
- render={this.renderTokenBalances.bind(this)}
+ render={this._renderTokenBalances.bind(this)}
/>
<Route
path={`${WebsitePaths.Portal}/trades`}
- component={this.renderTradeHistory.bind(this)}
+ component={this._renderTradeHistory.bind(this)}
/>
<Route
path={`${WebsitePaths.Home}`}
- render={this.renderGenerateOrderForm.bind(this)}
+ render={this._renderGenerateOrderForm.bind(this)}
/>
- </Switch> :
+ </Switch>
+ ) : (
<Loading />
- }
+ )}
</div>
</div>
</div>
- }
+ )}
</Paper>
<BlockchainErrDialog
- blockchain={this.blockchain}
+ blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr}
isOpen={this.props.shouldBlockchainErrDialogBeOpen}
userAddress={this.props.userAddress}
toggleDialogFn={updateShouldBlockchainErrDialogBeOpen}
networkId={this.props.networkId}
/>
- <PortalDisclaimerDialog
- isOpen={!this.state.hasAcceptedDisclaimer}
- onToggleDialog={this.onPortalDisclaimerAccepted.bind(this)}
+ <WrappedEthSectionNoticeDialog
+ isOpen={this.state.isWethNoticeDialogOpen}
+ onToggleDialog={this._onWethNoticeAccepted.bind(this)}
/>
- <FlashMessage
- dispatcher={this.props.dispatcher}
- flashMessage={this.props.flashMessage}
+ <PortalDisclaimerDialog
+ isOpen={this.state.isDisclaimerDialogOpen}
+ onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)}
/>
+ <FlashMessage dispatcher={this.props.dispatcher} flashMessage={this.props.flashMessage} />
</div>
- <Footer location={this.props.location} />
+ <Footer />
</div>
);
}
- private renderTradeHistory() {
+ private _renderEthWrapper() {
+ return (
+ <EthWrappers
+ networkId={this.props.networkId}
+ blockchain={this._blockchain}
+ dispatcher={this.props.dispatcher}
+ tokenByAddress={this.props.tokenByAddress}
+ tokenStateByAddress={this.props.tokenStateByAddress}
+ userAddress={this.props.userAddress}
+ userEtherBalance={this.props.userEtherBalance}
+ />
+ );
+ }
+ private _renderTradeHistory() {
return (
<TradeHistory
tokenByAddress={this.props.tokenByAddress}
@@ -259,10 +266,10 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/>
);
}
- private renderTokenBalances() {
+ private _renderTokenBalances() {
return (
<TokenBalances
- blockchain={this.blockchain}
+ blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr}
blockchainIsLoaded={this.props.blockchainIsLoaded}
dispatcher={this.props.dispatcher}
@@ -275,16 +282,16 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/>
);
}
- private renderFillOrder(match: any, location: Location, history: History) {
- const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache) ?
- this.props.userSuppliedOrderCache :
- this.sharedOrderIfExists;
+ private _renderFillOrder(match: any, location: Location, history: History) {
+ const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache)
+ ? this.props.userSuppliedOrderCache
+ : this._sharedOrderIfExists;
return (
<FillOrder
- blockchain={this.blockchain}
+ blockchain={this._blockchain}
blockchainErr={this.props.blockchainErr}
initialOrder={initialFillOrder}
- isOrderInUrl={!_.isUndefined(this.sharedOrderIfExists)}
+ isOrderInUrl={!_.isUndefined(this._sharedOrderIfExists)}
orderFillAmount={this.props.orderFillAmount}
networkId={this.props.networkId}
userAddress={this.props.userAddress}
@@ -294,25 +301,31 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
/>
);
}
- private renderGenerateOrderForm(match: any, location: Location, history: History) {
+ private _renderGenerateOrderForm(match: any, location: Location, history: History) {
return (
<GenerateOrderForm
- blockchain={this.blockchain}
+ blockchain={this._blockchain}
hashData={this.props.hashData}
dispatcher={this.props.dispatcher}
/>
);
}
- private onPortalDisclaimerAccepted() {
- localStorage.setItem(constants.ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY, 'set');
+ private _onPortalDisclaimerAccepted() {
+ localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set');
+ this.setState({
+ isDisclaimerDialogOpen: false,
+ });
+ }
+ private _onWethNoticeAccepted() {
+ localStorage.setItem(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE, 'set');
this.setState({
- hasAcceptedDisclaimer: true,
+ isWethNoticeDialogOpen: false,
});
}
- private getSharedOrderIfExists(): Order {
+ private _getSharedOrderIfExists(): Order | undefined {
const queryString = window.location.search;
if (queryString.length === 0) {
- return;
+ return undefined;
}
const queryParams = queryString.substring(1).split('&');
const orderQueryParam = _.find(queryParams, queryParam => {
@@ -320,11 +333,11 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
return queryPair[0] === 'order';
});
if (_.isUndefined(orderQueryParam)) {
- return;
+ return undefined;
}
const orderPair = orderQueryParam.split('=');
if (orderPair.length !== 2) {
- return;
+ return undefined;
}
const validator = new SchemaValidator();
@@ -332,17 +345,17 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
const validationResult = validator.validate(order, orderSchema);
if (validationResult.errors.length > 0) {
utils.consoleLog(`Invalid shared order: ${validationResult.errors}`);
- return;
+ return undefined;
}
return order;
}
- private updateScreenWidth() {
+ private _updateScreenWidth() {
const newScreenWidth = utils.getScreenWidth();
this.props.dispatcher.updateScreenWidth(newScreenWidth);
}
- private async updateBalanceAndAllowanceWithLoadingScreenAsync(tokens: Token[]) {
+ private async _updateBalanceAndAllowanceWithLoadingScreenAsync(tokens: Token[]) {
this.props.dispatcher.updateBlockchainIsLoaded(false);
- await this.blockchain.updateTokenBalancesAndAllowancesAsync(tokens);
+ await this._blockchain.updateTokenBalancesAndAllowancesAsync(tokens);
this.props.dispatcher.updateBlockchainIsLoaded(true);
}
}
diff --git a/packages/website/ts/components/portal_menu.tsx b/packages/website/ts/components/portal_menu.tsx
index 869df3e71..a2f9340c8 100644
--- a/packages/website/ts/components/portal_menu.tsx
+++ b/packages/website/ts/components/portal_menu.tsx
@@ -1,8 +1,7 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {Link} from 'react-router-dom';
-import {MenuItem} from 'ts/components/ui/menu_item';
-import {WebsitePaths} from 'ts/types';
+import { MenuItem } from 'ts/components/ui/menu_item';
+import { WebsitePaths } from 'ts/types';
export interface PortalMenuProps {
menuItemStyle: React.CSSProperties;
@@ -24,7 +23,7 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}`}
onClick={this.props.onClick.bind(this)}
>
- {this.renderMenuItemWithIcon('Generate order', 'zmdi-arrow-right-top')}
+ {this._renderMenuItemWithIcon('Generate order', 'zmdi-arrow-right-top')}
</MenuItem>
<MenuItem
style={this.props.menuItemStyle}
@@ -32,7 +31,7 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}/fill`}
onClick={this.props.onClick.bind(this)}
>
- {this.renderMenuItemWithIcon('Fill order', 'zmdi-arrow-left-bottom')}
+ {this._renderMenuItemWithIcon('Fill order', 'zmdi-arrow-left-bottom')}
</MenuItem>
<MenuItem
style={this.props.menuItemStyle}
@@ -40,7 +39,7 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}/balances`}
onClick={this.props.onClick.bind(this)}
>
- {this.renderMenuItemWithIcon('Balances', 'zmdi-balance-wallet')}
+ {this._renderMenuItemWithIcon('Balances', 'zmdi-balance-wallet')}
</MenuItem>
<MenuItem
style={this.props.menuItemStyle}
@@ -48,20 +47,26 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
to={`${WebsitePaths.Portal}/trades`}
onClick={this.props.onClick.bind(this)}
>
- {this.renderMenuItemWithIcon('Trade history', 'zmdi-format-list-bulleted')}
+ {this._renderMenuItemWithIcon('Trade history', 'zmdi-format-list-bulleted')}
+ </MenuItem>
+ <MenuItem
+ style={this.props.menuItemStyle}
+ className="py2"
+ to={`${WebsitePaths.Portal}/weth`}
+ onClick={this.props.onClick.bind(this)}
+ >
+ {this._renderMenuItemWithIcon('Wrap ETH', 'zmdi-circle-o')}
</MenuItem>
</div>
);
}
- private renderMenuItemWithIcon(title: string, iconName: string) {
+ private _renderMenuItemWithIcon(title: string, iconName: string) {
return (
- <div className="flex" style={{fontWeight: 100}}>
+ <div className="flex" style={{ fontWeight: 100 }}>
<div className="pr1 pl2">
- <i style={{fontSize: 20}} className={`zmdi ${iconName}`} />
- </div>
- <div className="pl1">
- {title}
+ <i style={{ fontSize: 20 }} className={`zmdi ${iconName}`} />
</div>
+ <div className="pl1">{title}</div>
</div>
);
}
diff --git a/packages/website/ts/components/send_button.tsx b/packages/website/ts/components/send_button.tsx
index da8dd2a9b..f94ec346a 100644
--- a/packages/website/ts/components/send_button.tsx
+++ b/packages/website/ts/components/send_button.tsx
@@ -1,15 +1,13 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
-import {Blockchain} from 'ts/blockchain';
-import {SendDialog} from 'ts/components/dialogs/send_dialog';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {BlockchainCallErrs, Token, TokenState} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {errorReporter} from 'ts/utils/error_reporter';
-import {utils} from 'ts/utils/utils';
+import { Blockchain } from 'ts/blockchain';
+import { SendDialog } from 'ts/components/dialogs/send_dialog';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { BlockchainCallErrs, Token, TokenState } from 'ts/types';
+import { errorReporter } from 'ts/utils/error_reporter';
+import { utils } from 'ts/utils/utils';
interface SendButtonProps {
token: Token;
@@ -33,36 +31,36 @@ export class SendButton extends React.Component<SendButtonProps, SendButtonState
};
}
public render() {
- const labelStyle = this.state.isSending ? {fontSize: 10} : {};
+ const labelStyle = this.state.isSending ? { fontSize: 10 } : {};
return (
<div>
<RaisedButton
- style={{width: '100%'}}
+ style={{ width: '100%' }}
labelStyle={labelStyle}
disabled={this.state.isSending}
label={this.state.isSending ? 'Sending...' : 'Send'}
- onClick={this.toggleSendDialog.bind(this)}
+ onClick={this._toggleSendDialog.bind(this)}
/>
<SendDialog
isOpen={this.state.isSendDialogVisible}
- onComplete={this.onSendAmountSelectedAsync.bind(this)}
- onCancelled={this.toggleSendDialog.bind(this)}
+ onComplete={this._onSendAmountSelectedAsync.bind(this)}
+ onCancelled={this._toggleSendDialog.bind(this)}
token={this.props.token}
tokenState={this.props.tokenState}
/>
</div>
);
}
- private toggleSendDialog() {
+ private _toggleSendDialog() {
this.setState({
isSendDialogVisible: !this.state.isSendDialogVisible,
});
}
- private async onSendAmountSelectedAsync(recipient: string, value: BigNumber) {
+ private async _onSendAmountSelectedAsync(recipient: string, value: BigNumber) {
this.setState({
isSending: true,
});
- this.toggleSendDialog();
+ this._toggleSendDialog();
const token = this.props.token;
const tokenState = this.props.tokenState;
let balance = tokenState.balance;
@@ -72,14 +70,14 @@ export class SendButton extends React.Component<SendButtonProps, SendButtonState
this.props.dispatcher.replaceTokenBalanceByAddress(token.address, balance);
} catch (err) {
const errMsg = `${err}`;
- if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) {
+ if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return;
} else if (!_.includes(errMsg, 'User denied transaction')) {
utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack);
- await errorReporter.reportAsync(err);
this.props.onError();
+ await errorReporter.reportAsync(err);
}
}
this.setState({
diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx
index ae5ef9222..2cef413c7 100644
--- a/packages/website/ts/components/token_balances.tsx
+++ b/packages/website/ts/components/token_balances.tsx
@@ -1,5 +1,5 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
import DharmaLoanFrame from 'dharma-loan-frame';
import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog';
@@ -7,31 +7,21 @@ 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 {
- Table,
- TableBody,
- TableHeader,
- TableHeaderColumn,
- TableRow,
- TableRowColumn,
-} from 'material-ui/Table';
-import QueryString = require('query-string');
+import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
import * as React from 'react';
import ReactTooltip = require('react-tooltip');
import firstBy = require('thenby');
-import {Blockchain} from 'ts/blockchain';
-import {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button';
-import {AssetPicker} from 'ts/components/generate_order/asset_picker';
-import {AllowanceToggle} from 'ts/components/inputs/allowance_toggle';
-import {SendButton} from 'ts/components/send_button';
-import {HelpTooltip} from 'ts/components/ui/help_tooltip';
-import {LifeCycleRaisedButton} from 'ts/components/ui/lifecycle_raised_button';
-import {TokenIcon} from 'ts/components/ui/token_icon';
-import {trackedTokenStorage} from 'ts/local_storage/tracked_token_storage';
-import {Dispatcher} from 'ts/redux/dispatcher';
+import { Blockchain } from 'ts/blockchain';
+import { AssetPicker } from 'ts/components/generate_order/asset_picker';
+import { AllowanceToggle } from 'ts/components/inputs/allowance_toggle';
+import { SendButton } from 'ts/components/send_button';
+import { HelpTooltip } from 'ts/components/ui/help_tooltip';
+import { LifeCycleRaisedButton } from 'ts/components/ui/lifecycle_raised_button';
+import { TokenIcon } from 'ts/components/ui/token_icon';
+import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
+import { Dispatcher } from 'ts/redux/dispatcher';
import {
BalanceErrs,
BlockchainCallErrs,
@@ -44,10 +34,11 @@ import {
TokenStateByAddress,
TokenVisibility,
} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
-import {errorReporter} from 'ts/utils/error_reporter';
-import {utils} from 'ts/utils/utils';
+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';
+import { utils } from 'ts/utils/utils';
const ETHER_ICON_PATH = '/images/ether.png';
const ETHER_TOKEN_SYMBOL = 'WETH';
@@ -117,7 +108,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({
@@ -135,7 +126,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
key="errorOkBtn"
label="Ok"
primary={true}
- onTouchTap={this.onErrorDialogToggle.bind(this, false)}
+ onTouchTap={this._onErrorDialogToggle.bind(this, false)}
/>,
];
const dharmaDialogActions = [
@@ -143,10 +134,10 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
key="dharmaCloseBtn"
label="Close"
primary={true}
- onTouchTap={this.onDharmaDialogToggle.bind(this, false)}
+ onTouchTap={this._onDharmaDialogToggle.bind(this, false)}
/>,
];
- const isTestNetwork = this.props.networkId === constants.TESTNET_NETWORK_ID;
+ const isTestNetwork = this.props.networkId === constants.NETWORK_ID_TESTNET;
const dharmaButtonColumnStyle = {
paddingLeft: 3,
display: isTestNetwork ? 'table-cell' : 'none',
@@ -155,194 +146,141 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
display: isTestNetwork ? 'none' : 'table-cell',
};
const allTokenRowHeight = _.size(this.props.tokenByAddress) * TOKEN_TABLE_ROW_HEIGHT;
- const tokenTableHeight = allTokenRowHeight < MAX_TOKEN_TABLE_HEIGHT ?
- allTokenRowHeight :
- MAX_TOKEN_TABLE_HEIGHT;
- const isSmallScreen = this.props.screenWidth === ScreenWidths.SM;
+ const tokenTableHeight =
+ allTokenRowHeight < MAX_TOKEN_TABLE_HEIGHT ? allTokenRowHeight : MAX_TOKEN_TABLE_HEIGHT;
+ 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> \
+ const dharmaLoanExplanation =
+ 'If you need access to larger amounts of ether,<br> \
you can request a loan from the Dharma Loan<br> \
network. Your loan should be funded in 5<br> \
minutes or less.';
- const allowanceExplanation = '0x smart contracts require access to your<br> \
+ const allowanceExplanation =
+ '0x smart contracts require access to your<br> \
token balances in order to execute trades.<br> \
- 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">
<h3>{isTestNetwork ? 'Test ether' : 'Ether'}</h3>
<Divider />
<div className="pt2 pb2">
- {isTestNetwork ?
- 'In order to try out the 0x Portal Dapp, request some test ether to pay for \
- gas costs. It might take a bit of time for the test ether to show up.' :
- 'Ether must be converted to Ether Tokens in order to be tradable via 0x. \
- You can convert between Ether and Ether Tokens by clicking the "convert" button below.'
- }
+ {isTestNetwork
+ ? 'In order to try out the 0x Portal Dapp, request some test ether to pay for \
+ gas costs. It might take a bit of time for the test ether to show up.'
+ : 'Ether must be converted to Ether Tokens in order to be tradable via 0x. \
+ You can convert between Ether and Ether Tokens from the "Wrap ETH" tab.'}
</div>
- <Table
- selectable={false}
- style={styles.bgColor}
- >
+ <Table selectable={false} style={styles.bgColor}>
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
<TableRow>
<TableHeaderColumn>Currency</TableHeaderColumn>
<TableHeaderColumn>Balance</TableHeaderColumn>
- <TableRowColumn
- className="sm-hide xs-hide"
- style={stubColumnStyle}
- />
- {
- isTestNetwork &&
- <TableHeaderColumn
- style={{paddingLeft: 3}}
- >
+ <TableRowColumn className="sm-hide xs-hide" style={stubColumnStyle} />
+ {isTestNetwork && (
+ <TableHeaderColumn style={{ paddingLeft: 3 }}>
{isSmallScreen ? 'Faucet' : 'Request from faucet'}
</TableHeaderColumn>
- }
- {
- isTestNetwork &&
- <TableHeaderColumn
- style={dharmaButtonColumnStyle}
- >
+ )}
+ {isTestNetwork && (
+ <TableHeaderColumn style={dharmaButtonColumnStyle}>
{isSmallScreen ? 'Loan' : 'Request Dharma loan'}
- <HelpTooltip
- style={{paddingLeft: 4}}
- explanation={dharmaLoanExplanation}
- />
+ <HelpTooltip style={{ paddingLeft: 4 }} explanation={dharmaLoanExplanation} />
</TableHeaderColumn>
- }
+ )}
</TableRow>
</TableHeader>
<TableBody displayRowCheckbox={false}>
<TableRow key="ETH">
<TableRowColumn className="py1">
- <img
- style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
- src={ETHER_ICON_PATH}
- />
+ <img style={{ width: ICON_DIMENSION, height: ICON_DIMENSION }} src={ETHER_ICON_PATH} />
</TableRowColumn>
<TableRowColumn>
{this.props.userEtherBalance.toFixed(PRECISION)} ETH
- {this.state.isBalanceSpinnerVisible &&
+ {this.state.isBalanceSpinnerVisible && (
<span className="pl1">
<i className="zmdi zmdi-spinner zmdi-hc-spin" />
</span>
- }
+ )}
</TableRowColumn>
- <TableRowColumn
- className="sm-hide xs-hide"
- style={stubColumnStyle}
- />
- {
- isTestNetwork &&
- <TableRowColumn style={{paddingLeft: 3}}>
+ <TableRowColumn className="sm-hide xs-hide" style={stubColumnStyle} />
+ {isTestNetwork && (
+ <TableRowColumn style={{ paddingLeft: 3 }}>
<LifeCycleRaisedButton
labelReady="Request"
labelLoading="Sending..."
labelComplete="Sent!"
- onClickAsyncFn={this.faucetRequestAsync.bind(this, true)}
+ onClickAsyncFn={this._faucetRequestAsync.bind(this, true)}
/>
</TableRowColumn>
- }
- {
- isTestNetwork &&
+ )}
+ {isTestNetwork && (
<TableRowColumn style={dharmaButtonColumnStyle}>
<RaisedButton
label="Request"
- style={{width: '100%'}}
- onTouchTap={this.onDharmaDialogToggle.bind(this)}
+ style={{ width: '100%' }}
+ onTouchTap={this._onDharmaDialogToggle.bind(this)}
/>
</TableRowColumn>
- }
+ )}
</TableRow>
</TableBody>
</Table>
- <div className="clearfix" style={{paddingBottom: 1}}>
+ <div className="clearfix" style={{ paddingBottom: 1 }}>
<div className="col col-10">
- <h3 className="pt2">
- {isTestNetwork ? 'Test tokens' : 'Tokens'}
- </h3>
+ <h3 className="pt2">{isTestNetwork ? 'Test tokens' : 'Tokens'}</h3>
</div>
<div className="col col-1 pt3 align-right">
- <FloatingActionButton
- mini={true}
- zDepth={0}
- onClick={this.onAddTokenClicked.bind(this)}
- >
+ <FloatingActionButton mini={true} zDepth={0} onClick={this._onAddTokenClicked.bind(this)}>
<ContentAdd />
</FloatingActionButton>
</div>
<div className="col col-1 pt3 align-right">
- <FloatingActionButton
- mini={true}
- zDepth={0}
- onClick={this.onRemoveTokenClicked.bind(this)}
- >
+ <FloatingActionButton mini={true} zDepth={0} onClick={this._onRemoveTokenClicked.bind(this)}>
<ContentRemove />
</FloatingActionButton>
</div>
</div>
<Divider />
<div className="pt2 pb2">
- {isTestNetwork ?
- 'Mint some test tokens you\'d like to use to generate or fill an order using 0x.' :
- 'Set trading permissions for a token you\'d like to start trading.'
- }
+ {isTestNetwork
+ ? "Mint some test tokens you'd like to use to generate or fill an order using 0x."
+ : "Set trading permissions for a token you'd like to start trading."}
</div>
- <Table
- selectable={false}
- bodyStyle={{height: tokenTableHeight}}
- style={styles.bgColor}
- >
+ <Table selectable={false} bodyStyle={{ height: tokenTableHeight }} style={styles.bgColor}>
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
<TableRow>
- <TableHeaderColumn
- colSpan={tokenColSpan}
- >
- Token
- </TableHeaderColumn>
- <TableHeaderColumn style={{paddingLeft: 3}}>Balance</TableHeaderColumn>
- <TableHeaderColumn>
- <div className="inline-block">{!isSmallScreen && 'Trade '}Permissions</div>
- <HelpTooltip
- style={{paddingLeft: 4}}
- explanation={allowanceExplanation}
- />
- </TableHeaderColumn>
+ <TableHeaderColumn colSpan={tokenColSpan}>Token</TableHeaderColumn>
+ <TableHeaderColumn style={{ paddingLeft: 3 }}>Balance</TableHeaderColumn>
<TableHeaderColumn>
- Action
+ <div className="inline-block">Allowance</div>
+ <HelpTooltip style={{ paddingLeft: 4 }} explanation={allowanceExplanation} />
</TableHeaderColumn>
- {this.props.screenWidth !== ScreenWidths.SM &&
- <TableHeaderColumn>
- Send
- </TableHeaderColumn>
- }
+ <TableHeaderColumn>Action</TableHeaderColumn>
+ {this.props.screenWidth !== ScreenWidths.Sm && <TableHeaderColumn>Send</TableHeaderColumn>}
</TableRow>
</TableHeader>
- <TableBody displayRowCheckbox={false}>
- {this.renderTokenTableRows()}
- </TableBody>
+ <TableBody displayRowCheckbox={false}>{this._renderTokenTableRows()}</TableBody>
</Table>
<Dialog
title="Oh oh"
- titleStyle={{fontWeight: 100}}
+ titleStyle={{ fontWeight: 100 }}
actions={errorDialogActions}
open={!_.isUndefined(this.state.errorType)}
- onRequestClose={this.onErrorDialogToggle.bind(this, false)}
+ onRequestClose={this._onErrorDialogToggle.bind(this, false)}
>
- {this.renderErrorDialogBody()}
+ {this._renderErrorDialogBody()}
</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}
>
- {this.renderDharmaLoanFrame()}
+ {this._renderDharmaLoanFrame()}
</Dialog>
<AssetPicker
userAddress={this.props.userAddress}
@@ -351,58 +289,62 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
dispatcher={this.props.dispatcher}
isOpen={this.state.isTokenPickerOpen}
currentTokenAddress={''}
- onTokenChosen={this.onAssetTokenPicked.bind(this)}
+ onTokenChosen={this._onAssetTokenPicked.bind(this)}
tokenByAddress={this.props.tokenByAddress}
tokenVisibility={this.state.isAddingToken ? TokenVisibility.UNTRACKED : TokenVisibility.TRACKED}
/>
</div>
);
}
- private renderTokenTableRows() {
- if (!this.props.blockchainIsLoaded || this.props.blockchainErr !== '') {
+ private _renderTokenTableRows() {
+ 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);
const trackedTokens = _.filter(allTokens, t => t.isTracked);
const trackedTokensStartingWithEtherToken = trackedTokens.sort(
- firstBy((t: Token) => (t.symbol !== ETHER_TOKEN_SYMBOL))
- .thenBy((t: Token) => (t.symbol !== ZRX_TOKEN_SYMBOL))
- .thenBy('address'),
+ firstBy((t: Token) => t.symbol !== ETHER_TOKEN_SYMBOL)
+ .thenBy((t: Token) => t.symbol !== ZRX_TOKEN_SYMBOL)
+ .thenBy('address'),
);
const tableRows = _.map(
trackedTokensStartingWithEtherToken,
- this.renderTokenRow.bind(this, tokenColSpan, actionPaddingX),
+ this._renderTokenRow.bind(this, tokenColSpan, actionPaddingX),
);
return tableRows;
}
- private renderTokenRow(tokenColSpan: number, actionPaddingX: number, token: Token) {
+ 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;
+ const tokenLink = utils.getEtherScanLinkIfExists(
+ token.address,
+ this.props.networkId,
+ 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
- colSpan={tokenColSpan}
- >
- {_.isUndefined(tokenLink) ?
- this.renderTokenName(token) :
- <a href={tokenLink} target="_blank" style={{textDecoration: 'none'}}>
- {this.renderTokenName(token)}
+ <TableRow key={token.address} style={{ height: TOKEN_TABLE_ROW_HEIGHT }}>
+ <TableRowColumn colSpan={tokenColSpan}>
+ {_.isUndefined(tokenLink) ? (
+ this._renderTokenName(token)
+ ) : (
+ <a href={tokenLink} target="_blank" style={{ textDecoration: 'none' }}>
+ {this._renderTokenName(token)}
</a>
- }
+ )}
</TableRowColumn>
- <TableRowColumn style={{paddingRight: 3, paddingLeft: 3}}>
- {this.renderAmount(tokenState.balance, token.decimals)} {token.symbol}
- {this.state.isZRXSpinnerVisible && token.symbol === ZRX_TOKEN_SYMBOL &&
- <span className="pl1">
- <i className="zmdi zmdi-spinner zmdi-hc-spin" />
- </span>
- }
+ <TableRowColumn style={{ paddingRight: 3, paddingLeft: 3 }}>
+ {this._renderAmount(tokenState.balance, token.decimals)} {token.symbol}
+ {this.state.isZRXSpinnerVisible &&
+ token.symbol === ZRX_TOKEN_SYMBOL && (
+ <span className="pl1">
+ <i className="zmdi zmdi-spinner zmdi-hc-spin" />
+ </span>
+ )}
</TableRowColumn>
<TableRowColumn>
<AllowanceToggle
@@ -410,57 +352,49 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
dispatcher={this.props.dispatcher}
token={token}
tokenState={tokenState}
- onErrorOccurred={this.onErrorOccurred.bind(this)}
+ onErrorOccurred={this._onErrorOccurred.bind(this)}
userAddress={this.props.userAddress}
/>
</TableRowColumn>
- <TableRowColumn
- style={{paddingLeft: actionPaddingX, paddingRight: actionPaddingX}}
- >
- {isMintable &&
+ <TableRowColumn style={{ paddingLeft: actionPaddingX, paddingRight: actionPaddingX }}>
+ {isMintable && (
<LifeCycleRaisedButton
labelReady="Mint"
- labelLoading={<span style={{fontSize: 12}}>Minting...</span>}
+ labelLoading={<span style={{ fontSize: 12 }}>Minting...</span>}
labelComplete="Minted!"
- onClickAsyncFn={this.onMintTestTokensAsync.bind(this, token)}
+ onClickAsyncFn={this._onMintTestTokensAsync.bind(this, token)}
/>
- }
- {token.symbol === ETHER_TOKEN_SYMBOL &&
- <EthWethConversionButton
- blockchain={this.props.blockchain}
- dispatcher={this.props.dispatcher}
- ethToken={this.getWrappedEthToken()}
- ethTokenState={tokenState}
- userEtherBalance={this.props.userEtherBalance}
- onError={this.onEthWethConversionFailed.bind(this)}
- />
- }
- {token.symbol === ZRX_TOKEN_SYMBOL && this.props.networkId === constants.TESTNET_NETWORK_ID &&
- <LifeCycleRaisedButton
- labelReady="Request"
- labelLoading="Sending..."
- labelComplete="Sent!"
- onClickAsyncFn={this.faucetRequestAsync.bind(this, false)}
- />
- }
+ )}
+ {token.symbol === ZRX_TOKEN_SYMBOL &&
+ this.props.networkId === constants.NETWORK_ID_TESTNET && (
+ <LifeCycleRaisedButton
+ labelReady="Request"
+ labelLoading="Sending..."
+ labelComplete="Sent!"
+ onClickAsyncFn={this._faucetRequestAsync.bind(this, false)}
+ />
+ )}
</TableRowColumn>
- {this.props.screenWidth !== ScreenWidths.SM &&
+ {this.props.screenWidth !== ScreenWidths.Sm && (
<TableRowColumn
- style={{paddingLeft: actionPaddingX, paddingRight: actionPaddingX}}
+ style={{
+ paddingLeft: actionPaddingX,
+ paddingRight: actionPaddingX,
+ }}
>
<SendButton
blockchain={this.props.blockchain}
dispatcher={this.props.dispatcher}
token={token}
tokenState={tokenState}
- onError={this.onSendFailed.bind(this)}
+ onError={this._onSendFailed.bind(this)}
/>
</TableRowColumn>
- }
+ )}
</TableRow>
);
}
- private onAssetTokenPicked(tokenAddress: string) {
+ private _onAssetTokenPicked(tokenAddress: string) {
if (_.isEmpty(tokenAddress)) {
this.setState({
isTokenPickerOpen: false,
@@ -468,13 +402,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);
@@ -488,82 +423,57 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
isTokenPickerOpen: false,
});
}
- private onEthWethConversionFailed() {
- this.setState({
- errorType: BalanceErrs.wethConversionFailed,
- });
- }
- private onSendFailed() {
+ private _onSendFailed() {
this.setState({
errorType: BalanceErrs.sendFailed,
});
}
- private renderAmount(amount: BigNumber, decimals: number) {
+ private _renderAmount(amount: BigNumber, decimals: number) {
const unitAmount = ZeroEx.toUnitAmount(amount, decimals);
return unitAmount.toNumber().toFixed(PRECISION);
}
- private renderTokenName(token: Token) {
+ private _renderTokenName(token: Token) {
const tooltipId = `tooltip-${token.address}`;
return (
<div className="flex">
<TokenIcon token={token} diameter={ICON_DIMENSION} />
- <div
- data-tip={true}
- data-for={tooltipId}
- className="mt2 ml2 sm-hide xs-hide"
- >
+ <div data-tip={true} data-for={tooltipId} className="mt2 ml2 sm-hide xs-hide">
{token.name}
</div>
<ReactTooltip id={tooltipId}>{token.address}</ReactTooltip>
</div>
);
}
- private renderErrorDialogBody() {
+ private _renderErrorDialogBody() {
switch (this.state.errorType) {
case BalanceErrs.incorrectNetworkForFaucet:
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
- {' '}connected to the {constants.TESTNET_NAME} testnet and try requesting ether again.
+ Our faucet can only send test Ether to addresses on the {constants.TESTNET_NAME} testnet
+ (networkId {constants.NETWORK_ID_TESTNET}). Please make sure you are connected to the{' '}
+ {constants.TESTNET_NAME} testnet and try requesting ether again.
</div>
);
case BalanceErrs.faucetRequestFailed:
return (
<div>
- An unexpected error occurred while trying to request test Ether from our faucet.
- {' '}Please refresh the page and try again.
+ An unexpected error occurred while trying to request test Ether from our faucet. Please refresh
+ the page and try again.
</div>
);
case BalanceErrs.faucetQueueIsFull:
- return (
- <div>
- Our test Ether faucet queue is full. Please try requesting test Ether again later.
- </div>
- );
+ return <div>Our test Ether faucet queue is full. Please try requesting test Ether again later.</div>;
case BalanceErrs.mintingFailed:
- return (
- <div>
- Minting your test tokens failed unexpectedly. Please refresh the page and try again.
- </div>
- );
-
- case BalanceErrs.wethConversionFailed:
- return (
- <div>
- Converting between Ether and Ether Tokens failed unexpectedly.
- Please refresh the page and try again.
- </div>
- );
+ return <div>Minting your test tokens failed unexpectedly. Please refresh the page and try again.</div>;
case BalanceErrs.allowanceSettingFailed:
return (
<div>
- An unexpected error occurred while trying to set your test token allowance.
- {' '}Please refresh the page and try again.
+ An unexpected error occurred while trying to set your test token allowance. Please refresh the
+ page and try again.
</div>
);
@@ -574,12 +484,12 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
throw utils.spawnSwitchErr('errorType', this.state.errorType);
}
}
- private renderDharmaLoanFrame() {
+ private _renderDharmaLoanFrame() {
if (utils.isUserOnMobile()) {
return (
<h4 style={{ textAlign: 'center' }}>
- We apologize -- Dharma loan requests are not available on
- mobile yet. Please try again through your desktop browser.
+ We apologize -- Dharma loan requests are not available on mobile yet. Please try again through your
+ desktop browser.
</h4>
);
} else {
@@ -592,20 +502,20 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
);
}
}
- private onErrorOccurred(errorType: BalanceErrs) {
+ private _onErrorOccurred(errorType: BalanceErrs) {
this.setState({
errorType,
});
}
- private async onMintTestTokensAsync(token: Token): Promise<boolean> {
+ private async _onMintTestTokensAsync(token: Token): Promise<boolean> {
try {
await this.props.blockchain.mintTestTokensAsync(token);
const amount = ZeroEx.toUnitAmount(constants.MINT_AMOUNT, token.decimals);
this.props.dispatcher.showFlashMessage(`Successfully minted ${amount.toString(10)} ${token.symbol}`);
return true;
} catch (err) {
- const errMsg = '' + err;
- if (_.includes(errMsg, BlockchainCallErrs.USER_HAS_NO_ASSOCIATED_ADDRESSES)) {
+ const errMsg = `${err}`;
+ if (_.includes(errMsg, BlockchainCallErrs.UserHasNoAssociatedAddresses)) {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return false;
}
@@ -614,14 +524,14 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
}
utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack);
- await errorReporter.reportAsync(err);
this.setState({
errorType: BalanceErrs.mintingFailed,
});
+ await errorReporter.reportAsync(err);
return false;
}
}
- private async faucetRequestAsync(isEtherRequest: boolean): Promise<boolean> {
+ private async _faucetRequestAsync(isEtherRequest: boolean): Promise<boolean> {
if (this.props.userAddress === '') {
this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true);
return false;
@@ -629,7 +539,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,
});
@@ -639,17 +549,18 @@ 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}`);
- await errorReporter.reportAsync(new Error(`Faucet returned non-200: ${JSON.stringify(response)}`));
- const errorType = response.status === constants.UNAVAILABLE_STATUS ?
- BalanceErrs.faucetQueueIsFull :
- BalanceErrs.faucetRequestFailed;
+ const errorType =
+ response.status === constants.UNAVAILABLE_STATUS
+ ? BalanceErrs.faucetQueueIsFull
+ : BalanceErrs.faucetRequestFailed;
this.setState({
errorType,
});
+ await errorReporter.reportAsync(new Error(`Faucet returned non-200: ${JSON.stringify(response)}`));
return false;
}
@@ -670,28 +581,23 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
}
return true;
}
- private onErrorDialogToggle(isOpen: boolean) {
+ private _onErrorDialogToggle(isOpen: boolean) {
this.setState({
errorType: undefined,
});
}
- private onDharmaDialogToggle() {
+ private _onDharmaDialogToggle() {
this.setState({
isDharmaDialogVisible: !this.state.isDharmaDialogVisible,
});
}
- private getWrappedEthToken() {
- const tokens = _.values(this.props.tokenByAddress);
- const wrappedEthToken = _.find(tokens, {symbol: ETHER_TOKEN_SYMBOL});
- return wrappedEthToken;
- }
- private onAddTokenClicked() {
+ private _onAddTokenClicked() {
this.setState({
isTokenPickerOpen: true,
isAddingToken: true,
});
}
- private onRemoveTokenClicked() {
+ private _onRemoveTokenClicked() {
this.setState({
isTokenPickerOpen: true,
isAddingToken: false,
diff --git a/packages/website/ts/components/top_bar.tsx b/packages/website/ts/components/top_bar.tsx
index 4398fe667..11d3e7cc2 100644
--- a/packages/website/ts/components/top_bar.tsx
+++ b/packages/website/ts/components/top_bar.tsx
@@ -1,29 +1,18 @@
import * as _ from 'lodash';
-import AppBar from 'material-ui/AppBar';
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 {HashLink} from 'react-router-hash-link';
-import {
- animateScroll,
- Link as ScrollLink,
-} from 'react-scroll';
+import { Link } from 'react-router-dom';
import ReactTooltip = require('react-tooltip');
-import {PortalMenu} from 'ts/components/portal_menu';
-import {TopBarMenuItem} from 'ts/components/top_bar_menu_item';
-import {DropDownMenuItem} from 'ts/components/ui/drop_down_menu_item';
-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, TypeDocNode, WebsitePaths} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
-import {typeDocUtils} from 'ts/utils/typedoc_utils';
-
-const CUSTOM_DARK_GRAY = '#231F20';
-const SECTION_HEADER_COLOR = 'rgb(234, 234, 234)';
+import { PortalMenu } from 'ts/components/portal_menu';
+import { TopBarMenuItem } from 'ts/components/top_bar_menu_item';
+import { DropDownMenuItem } from 'ts/components/ui/drop_down_menu_item';
+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';
interface TopBarProps {
userAddress?: string;
@@ -52,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,
@@ -71,7 +55,7 @@ const styles: Styles = {
},
menuItem: {
fontSize: 14,
- color: CUSTOM_DARK_GRAY,
+ color: colors.darkestGrey,
paddingTop: 6,
paddingBottom: 6,
marginTop: 17,
@@ -97,40 +81,28 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
const isFullWidthPage = this.props.shouldFullWidth;
const parentClassNames = `flex mx-auto ${isFullWidthPage ? 'pl2' : 'max-width-4'}`;
const developerSectionMenuItems = [
- <Link
- key="subMenuItem-zeroEx"
- to={WebsitePaths.ZeroExJs}
- className="text-decoration-none"
- >
- <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="0x.js" />
+ <Link key="subMenuItem-zeroEx" to={WebsitePaths.ZeroExJs} className="text-decoration-none">
+ <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="0x.js" />
</Link>,
- <Link
- key="subMenuItem-smartContracts"
- to={WebsitePaths.SmartContracts}
- className="text-decoration-none"
- >
- <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Smart Contracts" />
+ <Link key="subMenuItem-smartContracts" to={WebsitePaths.SmartContracts} className="text-decoration-none">
+ <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="Smart Contracts" />
</Link>,
- <Link
- key="subMenuItem-0xconnect"
- to={WebsitePaths.Connect}
- className="text-decoration-none"
- >
- <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="0x Connect" />
+ <Link key="subMenuItem-0xconnect" to={WebsitePaths.Connect} className="text-decoration-none">
+ <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="0x Connect" />
</Link>,
<a
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" />
+ <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="Standard Relayer API" />
</a>,
<a
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>,
@@ -140,10 +112,10 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
className="text-decoration-none"
href={`${WebsitePaths.Whitepaper}`}
>
- <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Whitepaper" />
+ <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="Whitepaper" />
</a>,
];
- const bottomBorderStyle = this.shouldDisplayBottomBar() ? styles.bottomBar : {};
+ const bottomBorderStyle = this._shouldDisplayBottomBar() ? styles.bottomBar : {};
const fullWidthClasses = isFullWidthPage ? 'pr4' : '';
const logoUrl = isNightVersion ? '/images/protocol_logo_white.png' : '/images/protocol_logo_black.png';
const menuClasses = `col col-${isFullWidthPage ? '4' : '5'} ${fullWidthClasses} lg-pr0 md-pr2 sm-hide xs-hide`;
@@ -154,19 +126,17 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
paddingTop: 16,
};
return (
- <div style={{...styles.topBar, ...bottomBorderStyle, ...this.props.style}} className="pb1">
+ <div style={{ ...styles.topBar, ...bottomBorderStyle, ...this.props.style }} className="pb1">
<div className={parentClassNames}>
- <div className="col col-2 sm-pl2 md-pl2 lg-pl0" style={{paddingTop: 15}}>
+ <div className="col col-2 sm-pl2 md-pl2 lg-pl0" style={{ paddingTop: 15 }}>
<Link to={`${WebsitePaths.Home}`} className="text-decoration-none">
<img src={logoUrl} height="30" />
</Link>
</div>
<div className={`col col-${isFullWidthPage ? '8' : '9'} lg-hide md-hide`} />
<div className={`col col-${isFullWidthPage ? '6' : '5'} sm-hide xs-hide`} />
- {!this.isViewingPortal() &&
- <div
- className={menuClasses}
- >
+ {!this._isViewingPortal() && (
+ <div className={menuClasses}>
<div className="flex justify-between">
<DropDownMenuItem
title="Developers"
@@ -196,110 +166,97 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
/>
</div>
</div>
- }
- {this.props.blockchainIsLoaded && !_.isEmpty(this.props.userAddress) &&
- <div className="col col-5">
- {this.renderUser()}
- </div>
- }
- {!this.isViewingPortal() &&
- <div
- className={`col ${isFullWidthPage ? 'col-2 pl2' : 'col-1'} md-hide lg-hide`}
- >
- <div style={menuIconStyle}>
- <i
- className="zmdi zmdi-menu"
- onClick={this.onMenuButtonClick.bind(this)}
- />
- </div>
+ )}
+ {this.props.blockchainIsLoaded &&
+ !_.isEmpty(this.props.userAddress) && (
+ <div className="col col-5 sm-hide xs-hide">{this._renderUser()}</div>
+ )}
+ <div className={`col ${isFullWidthPage ? 'col-2 pl2' : 'col-1'} md-hide lg-hide`}>
+ <div style={menuIconStyle}>
+ <i className="zmdi zmdi-menu" onClick={this._onMenuButtonClick.bind(this)} />
</div>
- }
+ </div>
</div>
- {this.renderDrawer()}
+ {this._renderDrawer()}
</div>
);
}
- private renderDrawer() {
+ private _renderDrawer() {
return (
<Drawer
open={this.state.isDrawerOpen}
docked={false}
openSecondary={true}
- onRequestChange={this.onMenuButtonClick.bind(this)}
+ onRequestChange={this._onMenuButtonClick.bind(this)}
>
- {this.renderPortalMenu()}
- {this.renderDocsMenu()}
- {this.renderWiki()}
- <div className="pl1 py1 mt3" style={{backgroundColor: SECTION_HEADER_COLOR}}>Website</div>
+ {this._renderPortalMenu()}
+ {this._renderDocsMenu()}
+ {this._renderWiki()}
+ <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>
<Link to={`${WebsitePaths.Wiki}`} className="text-decoration-none">
<MenuItem className="py2">Wiki</MenuItem>
</Link>
- {!this.isViewing0xjsDocs() &&
+ {!this._isViewing0xjsDocs() && (
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
<MenuItem className="py2">0x.js Docs</MenuItem>
</Link>
- }
- {!this.isViewingConnectDocs() &&
+ )}
+ {!this._isViewingConnectDocs() && (
<Link to={WebsitePaths.Connect} className="text-decoration-none">
<MenuItem className="py2">0x Connect Docs</MenuItem>
</Link>
- }
- {!this.isViewingSmartContractsDocs() &&
+ )}
+ {!this._isViewingSmartContractsDocs() && (
<Link to={WebsitePaths.SmartContracts} className="text-decoration-none">
<MenuItem className="py2">Smart Contract Docs</MenuItem>
</Link>
- }
- {!this.isViewingPortal() &&
+ )}
+ {!this._isViewingPortal() && (
<Link to={`${WebsitePaths.Portal}`} className="text-decoration-none">
<MenuItem className="py2">Portal DApp</MenuItem>
</Link>
- }
- <a
- className="text-decoration-none"
- target="_blank"
- href={`${WebsitePaths.Whitepaper}`}
- >
+ )}
+ <a className="text-decoration-none" target="_blank" href={`${WebsitePaths.Whitepaper}`}>
<MenuItem className="py2">Whitepaper</MenuItem>
</a>
<Link to={`${WebsitePaths.About}`} className="text-decoration-none">
<MenuItem className="py2">About</MenuItem>
</Link>
- <a
- className="text-decoration-none"
- target="_blank"
- href={constants.BLOG_URL}
- >
+ <a className="text-decoration-none" target="_blank" href={constants.URL_BLOG}>
<MenuItem className="py2">Blog</MenuItem>
</a>
<Link to={`${WebsitePaths.FAQ}`} className="text-decoration-none">
- <MenuItem
- className="py2"
- onTouchTap={this.onMenuButtonClick.bind(this)}
- >
+ <MenuItem className="py2" onTouchTap={this._onMenuButtonClick.bind(this)}>
FAQ
</MenuItem>
</Link>
</Drawer>
);
}
- private renderDocsMenu() {
- if (!this.isViewing0xjsDocs() && !this.isViewingSmartContractsDocs() && !this.isViewingConnectDocs()
- || _.isUndefined(this.props.menu)) {
- return;
+ private _renderDocsMenu(): React.ReactNode {
+ if (
+ (!this._isViewing0xjsDocs() && !this._isViewingSmartContractsDocs() && !this._isViewingConnectDocs()) ||
+ _.isUndefined(this.props.menu)
+ ) {
+ return undefined;
}
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}
shouldDisplaySectionHeaders={false}
- onMenuItemClick={this.onMenuButtonClick.bind(this)}
+ onMenuItemClick={this._onMenuButtonClick.bind(this)}
selectedVersion={this.props.docsVersion}
docPath={this.props.docsInfo.websitePath}
versions={this.props.availableDocVersions}
@@ -307,51 +264,45 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</div>
);
}
- private renderWiki() {
- if (!this.isViewingWiki()) {
- return;
+ private _renderWiki(): React.ReactNode {
+ if (!this._isViewingWiki()) {
+ return undefined;
}
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}
shouldDisplaySectionHeaders={false}
- onMenuItemClick={this.onMenuButtonClick.bind(this)}
+ onMenuItemClick={this._onMenuButtonClick.bind(this)}
/>
</div>
);
}
- private renderPortalMenu() {
- if (!this.isViewingPortal()) {
- return;
+ private _renderPortalMenu(): React.ReactNode {
+ if (!this._isViewingPortal()) {
+ return undefined;
}
return (
<div className="lg-hide md-hide">
- <div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>Portal DApp</div>
- <PortalMenu
- menuItemStyle={{color: 'black'}}
- onClick={this.onMenuButtonClick.bind(this)}
- />
+ <div className="pl1 py1" style={{ backgroundColor: colors.lightGrey }}>
+ Portal DApp
+ </div>
+ <PortalMenu menuItemStyle={{ color: 'black' }} onClick={this._onMenuButtonClick.bind(this)} />
</div>
);
}
- private renderUser() {
+ private _renderUser() {
const userAddress = this.props.userAddress;
const identiconDiameter = 26;
return (
- <div
- className="flex right lg-pr0 md-pr2 sm-pr2"
- style={{paddingTop: 16}}
- >
- <div
- style={styles.address}
- data-tip={true}
- data-for="userAddressTooltip"
- >
+ <div className="flex right lg-pr0 md-pr2 sm-pr2" style={{ paddingTop: 16 }}>
+ <div style={styles.address} data-tip={true} data-for="userAddressTooltip">
{!_.isEmpty(userAddress) ? userAddress : ''}
</div>
<ReactTooltip id="userAddressTooltip">{userAddress}</ReactTooltip>
@@ -361,31 +312,36 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</div>
);
}
- private onMenuButtonClick() {
+ private _onMenuButtonClick() {
this.setState({
isDrawerOpen: !this.state.isDrawerOpen,
});
}
- private isViewingPortal() {
+ private _isViewingPortal() {
return _.includes(this.props.location.pathname, WebsitePaths.Portal);
}
- private isViewingFAQ() {
+ private _isViewingFAQ() {
return _.includes(this.props.location.pathname, WebsitePaths.FAQ);
}
- private isViewing0xjsDocs() {
+ private _isViewing0xjsDocs() {
return _.includes(this.props.location.pathname, WebsitePaths.ZeroExJs);
}
- private isViewingConnectDocs() {
+ private _isViewingConnectDocs() {
return _.includes(this.props.location.pathname, WebsitePaths.Connect);
}
- private isViewingSmartContractsDocs() {
+ private _isViewingSmartContractsDocs() {
return _.includes(this.props.location.pathname, WebsitePaths.SmartContracts);
}
- private isViewingWiki() {
+ private _isViewingWiki() {
return _.includes(this.props.location.pathname, WebsitePaths.Wiki);
}
- private shouldDisplayBottomBar() {
- return this.isViewingWiki() || this.isViewing0xjsDocs() || this.isViewingFAQ() ||
- this.isViewingSmartContractsDocs() || this.isViewingConnectDocs();
+ private _shouldDisplayBottomBar() {
+ return (
+ this._isViewingWiki() ||
+ this._isViewing0xjsDocs() ||
+ this._isViewingFAQ() ||
+ this._isViewingSmartContractsDocs() ||
+ this._isViewingConnectDocs()
+ );
}
}
diff --git a/packages/website/ts/components/top_bar_menu_item.tsx b/packages/website/ts/components/top_bar_menu_item.tsx
index de429fba6..96ee86142 100644
--- a/packages/website/ts/components/top_bar_menu_item.tsx
+++ b/packages/website/ts/components/top_bar_menu_item.tsx
@@ -1,11 +1,10 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {Link} from 'react-router-dom';
-import {Styles} from 'ts/types';
+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 {
@@ -27,24 +26,24 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM
isNightVersion: false,
};
public render() {
- const primaryStyles = this.props.isPrimary ? {
- borderRadius: 4,
- border: `1px solid ${this.props.isNightVersion ? '#979797' : 'rgb(230, 229, 229)'}`,
- marginTop: 15,
- paddingLeft: 9,
- paddingRight: 9,
- width: 77,
- } : {};
+ const primaryStyles = this.props.isPrimary
+ ? {
+ borderRadius: 4,
+ border: `1px solid ${this.props.isNightVersion ? colors.grey : colors.greyishPink}`,
+ marginTop: 15,
+ paddingLeft: 9,
+ paddingRight: 9,
+ width: 77,
+ }
+ : {};
const menuItemColor = this.props.isNightVersion ? 'white' : this.props.style.color;
- const linkColor = _.isUndefined(menuItemColor) ?
- CUSTOM_DARK_GRAY :
- menuItemColor;
+ const linkColor = _.isUndefined(menuItemColor) ? colors.darkestGrey : menuItemColor;
return (
<div
className={`center ${this.props.className}`}
- style={{...this.props.style, ...primaryStyles, color: menuItemColor}}
+ style={{ ...this.props.style, ...primaryStyles, color: menuItemColor }}
>
- <Link to={this.props.path} className="text-decoration-none" style={{color: linkColor}}>
+ <Link to={this.props.path} className="text-decoration-none" style={{ color: linkColor }}>
{this.props.title}
</Link>
</div>
diff --git a/packages/website/ts/components/track_token_confirmation.tsx b/packages/website/ts/components/track_token_confirmation.tsx
index b9b2ef18a..76971aefa 100644
--- a/packages/website/ts/components/track_token_confirmation.tsx
+++ b/packages/website/ts/components/track_token_confirmation.tsx
@@ -1,11 +1,9 @@
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 {Party} from 'ts/components/ui/party';
-import {Token, TokenByAddress} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+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 {
tokens: Token[];
@@ -16,25 +14,23 @@ interface TrackTokenConfirmationProps {
interface TrackTokenConfirmationState {}
-export class TrackTokenConfirmation extends
- React.Component<TrackTokenConfirmationProps, TrackTokenConfirmationState> {
+export class TrackTokenConfirmation extends React.Component<TrackTokenConfirmationProps, TrackTokenConfirmationState> {
public render() {
const isMultipleTokens = this.props.tokens.length > 1;
const allTokens = _.values(this.props.tokenByAddress);
return (
- <div style={{color: colors.grey700}}>
- {this.props.isAddingTokenToTracked ?
+ <div style={{ color: colors.grey700 }}>
+ {this.props.isAddingTokenToTracked ? (
<div className="py4 my4 center">
<span className="pr1">
<i className="zmdi zmdi-spinner zmdi-hc-spin" />
</span>
<span>Adding token{isMultipleTokens && 's'}...</span>
- </div> :
+ </div>
+ ) : (
<div>
- <div>
- You do not currently track the following token{isMultipleTokens && 's'}:
- </div>
- <div className="py2 clearfix mx-auto center" style={{width: 355}}>
+ <div>You do not currently track the following token{isMultipleTokens && 's'}:</div>
+ <div className="py2 clearfix mx-auto center" style={{ width: 355 }}>
{_.map(this.props.tokens, (token: Token) => (
<div
key={`token-profile-${token.name}`}
@@ -52,13 +48,13 @@ export class TrackTokenConfirmation extends
))}
</div>
<div>
- Tracking a token adds it to the balances section of 0x Portal and
- allows you to generate/fill orders involving the token
+ Tracking a token adds it to the balances section of 0x Portal and allows you to
+ generate/fill orders involving the token
{isMultipleTokens && 's'}. Would you like to start tracking{' '}
- {isMultipleTokens ? 'these' : 'this'}{' '}token?
+ {isMultipleTokens ? 'these' : 'this'} token?
</div>
</div>
- }
+ )}
</div>
);
}
diff --git a/packages/website/ts/components/trade_history/trade_history.tsx b/packages/website/ts/components/trade_history/trade_history.tsx
index 59f85a03d..635358627 100644
--- a/packages/website/ts/components/trade_history/trade_history.tsx
+++ b/packages/website/ts/components/trade_history/trade_history.tsx
@@ -2,10 +2,10 @@ import * as _ from 'lodash';
import Divider from 'material-ui/Divider';
import Paper from 'material-ui/Paper';
import * as React from 'react';
-import {TradeHistoryItem} from 'ts/components/trade_history/trade_history_item';
-import {tradeHistoryStorage} from 'ts/local_storage/trade_history_storage';
-import {Fill, TokenByAddress} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { TradeHistoryItem } from 'ts/components/trade_history/trade_history_item';
+import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage';
+import { Fill, TokenByAddress } from 'ts/types';
+import { utils } from 'ts/utils/utils';
const FILL_POLLING_INTERVAL = 1000;
@@ -20,19 +20,19 @@ interface TradeHistoryState {
}
export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistoryState> {
- private fillPollingIntervalId: number;
+ private _fillPollingIntervalId: number;
public constructor(props: TradeHistoryProps) {
super(props);
- const sortedFills = this.getSortedFills();
+ const sortedFills = this._getSortedFills();
this.state = {
sortedFills,
};
}
public componentWillMount() {
- this.startPollingForFills();
+ this._startPollingForFills();
}
public componentWillUnmount() {
- this.stopPollingForFills();
+ this._stopPollingForFills();
}
public componentDidMount() {
window.scrollTo(0, 0);
@@ -42,16 +42,16 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
<div className="lg-px4 md-px4 sm-px2">
<h3>Trade history</h3>
<Divider />
- <div className="pt2" style={{height: 608, overflow: 'scroll'}}>
- {this.renderTrades()}
+ <div className="pt2" style={{ height: 608, overflow: 'scroll' }}>
+ {this._renderTrades()}
</div>
</div>
);
}
- private renderTrades() {
- const numNonCustomFills = this.numFillsWithoutCustomERC20Tokens();
+ private _renderTrades() {
+ const numNonCustomFills = this._numFillsWithoutCustomERC20Tokens();
if (numNonCustomFills === 0) {
- return this.renderEmptyNotice();
+ return this._renderEmptyNotice();
}
return _.map(this.state.sortedFills, (fill, index) => {
@@ -66,14 +66,14 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
);
});
}
- private renderEmptyNotice() {
+ private _renderEmptyNotice() {
return (
- <Paper className="mt1 p2 mx-auto center" style={{width: '80%'}}>
+ <Paper className="mt1 p2 mx-auto center" style={{ width: '80%' }}>
No filled orders yet.
</Paper>
);
}
- private numFillsWithoutCustomERC20Tokens() {
+ private _numFillsWithoutCustomERC20Tokens() {
let numNonCustomFills = 0;
const tokens = _.values(this.props.tokenByAddress);
_.each(this.state.sortedFills, fill => {
@@ -93,9 +93,9 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
});
return numNonCustomFills;
}
- private startPollingForFills() {
- this.fillPollingIntervalId = window.setInterval(() => {
- const sortedFills = this.getSortedFills();
+ private _startPollingForFills() {
+ this._fillPollingIntervalId = window.setInterval(() => {
+ const sortedFills = this._getSortedFills();
if (!utils.deepEqual(sortedFills, this.state.sortedFills)) {
this.setState({
sortedFills,
@@ -103,10 +103,10 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
}
}, FILL_POLLING_INTERVAL);
}
- private stopPollingForFills() {
- clearInterval(this.fillPollingIntervalId);
+ private _stopPollingForFills() {
+ clearInterval(this._fillPollingIntervalId);
}
- private getSortedFills() {
+ private _getSortedFills() {
const fillsByHash = tradeHistoryStorage.getUserFillsByHash(this.props.userAddress, this.props.networkId);
const fills = _.values(fillsByHash);
const sortedFills = _.sortBy(fills, [(fill: Fill) => fill.blockTimestamp * -1]);
diff --git a/packages/website/ts/components/trade_history/trade_history_item.tsx b/packages/website/ts/components/trade_history/trade_history_item.tsx
index 4dcceadb7..7e42e64e6 100644
--- a/packages/website/ts/components/trade_history/trade_history_item.tsx
+++ b/packages/website/ts/components/trade_history/trade_history_item.tsx
@@ -1,14 +1,14 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
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 { 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;
@@ -44,30 +44,26 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
fontWeight: 100,
display: 'inline-block',
};
- const amountColClassNames = 'col col-12 lg-col-4 md-col-4 lg-py2 md-py2 sm-py1 lg-pr2 md-pr2 \
+ const amountColClassNames =
+ 'col col-12 lg-col-4 md-col-4 lg-py2 md-py2 sm-py1 lg-pr2 md-pr2 \
lg-right-align md-right-align sm-center';
return (
- <Paper
- className="py1"
- style={{margin: '3px 3px 15px 3px'}}
- >
+ <Paper className="py1" style={{ margin: '3px 3px 15px 3px' }}>
<div className="clearfix">
- <div className="col col-12 lg-col-1 md-col-1 pt2 lg-pl3 md-pl3">
- {this.renderDate()}
- </div>
+ <div className="col col-12 lg-col-1 md-col-1 pt2 lg-pl3 md-pl3">{this._renderDate()}</div>
<div
className="col col-12 lg-col-6 md-col-6 lg-pl3 md-pl3"
- style={{fontSize: 12, fontWeight: 100}}
+ style={{ fontSize: 12, fontWeight: 100 }}
>
- <div className="flex sm-mx-auto xs-mx-auto" style={{paddingTop: 4, width: 224}}>
+ <div className="flex sm-mx-auto xs-mx-auto" style={{ paddingTop: 4, width: 224 }}>
<Party
label="Maker"
address={fill.maker}
identiconDiameter={IDENTICON_DIAMETER}
networkId={this.props.networkId}
/>
- <i style={{fontSize: 30}} className="zmdi zmdi-swap py3" />
+ <i style={{ fontSize: 30 }} className="zmdi zmdi-swap py3" />
<Party
label="Taker"
address={fill.taker}
@@ -76,18 +72,15 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
/>
</div>
</div>
- <div
- className={amountColClassNames}
- style={amountColStyle}
- >
- {this.renderAmounts(makerToken, takerToken)}
+ <div className={amountColClassNames} style={amountColStyle}>
+ {this._renderAmounts(makerToken, takerToken)}
</div>
<div className="col col-12 lg-col-1 md-col-1 lg-pr3 md-pr3 lg-py3 md-py3 sm-pb1 sm-center">
- <div className="pt1 lg-right md-right sm-mx-auto" style={{width: 13}}>
+ <div className="pt1 lg-right md-right sm-mx-auto" style={{ width: 13 }}>
<EtherScanIcon
addressOrTxHash={fill.transactionHash}
networkId={this.props.networkId}
- etherscanLinkSuffixes={EtherscanLinkSuffixes.tx}
+ etherscanLinkSuffixes={EtherscanLinkSuffixes.Tx}
/>
</div>
</div>
@@ -95,7 +88,7 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
</Paper>
);
}
- private renderAmounts(makerToken: Token, takerToken: Token) {
+ private _renderAmounts(makerToken: Token, takerToken: Token) {
const fill = this.props.fill;
const filledTakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledTakerTokenAmount, takerToken.decimals);
const filledMakerTokenAmountInUnits = ZeroEx.toUnitAmount(fill.filledMakerTokenAmount, takerToken.decimals);
@@ -124,31 +117,26 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
givenToken = takerToken;
} else {
// This condition should never be hit
- throw new Error('Found Fill that wasn\'t performed by this user');
+ throw new Error("Found Fill that wasn't performed by this user");
}
return (
<div>
- <div
- style={{color: colors.green400, fontSize: 16}}
- >
- <span>+{' '}</span>
- {this.renderAmount(receiveAmount, receiveToken.symbol, receiveToken.decimals)}
+ <div style={{ color: colors.green400, fontSize: 16 }}>
+ <span>+ </span>
+ {this._renderAmount(receiveAmount, receiveToken.symbol, receiveToken.decimals)}
</div>
- <div
- className="pb1 inline-block"
- style={{color: colors.red200, fontSize: 16}}
- >
- <span>-{' '}</span>
- {this.renderAmount(givenAmount, givenToken.symbol, givenToken.decimals)}
+ <div className="pb1 inline-block" style={{ color: colors.red200, fontSize: 16 }}>
+ <span>- </span>
+ {this._renderAmount(givenAmount, givenToken.symbol, givenToken.decimals)}
</div>
- <div style={{color: colors.grey400, fontSize: 14}}>
+ <div style={{ color: colors.grey400, fontSize: 14 }}>
{exchangeRate.toFixed(PRECISION)} {givenToken.symbol}/{receiveToken.symbol}
</div>
</div>
);
}
- private renderDate() {
+ private _renderDate() {
const blockMoment = moment.unix(this.props.fill.blockTimestamp);
if (!blockMoment.isValid()) {
return null;
@@ -160,17 +148,18 @@ export class TradeHistoryItem extends React.Component<TradeHistoryItemProps, Tra
const dateTooltipId = `${this.props.fill.transactionHash}-date`;
return (
- <div
- data-tip={true}
- data-for={dateTooltipId}
- >
- <div className="center pt1" style={{fontSize: 13}}>{monthAbreviation}</div>
- <div className="center" style={{fontSize: 24, fontWeight: 100}}>{dayOfMonth}</div>
+ <div data-tip={true} data-for={dateTooltipId}>
+ <div className="center pt1" style={{ fontSize: 13 }}>
+ {monthAbreviation}
+ </div>
+ <div className="center" style={{ fontSize: 24, fontWeight: 100 }}>
+ {dayOfMonth}
+ </div>
<ReactTooltip id={dateTooltipId}>{formattedBlockDate}</ReactTooltip>
</div>
);
}
- private renderAmount(amount: BigNumber, symbol: string, decimals: number) {
+ private _renderAmount(amount: BigNumber, symbol: string, decimals: number) {
const unitAmount = ZeroEx.toUnitAmount(amount, decimals);
return (
<span>
diff --git a/packages/website/ts/components/ui/alert.tsx b/packages/website/ts/components/ui/alert.tsx
index 71d2388f2..54881b499 100644
--- a/packages/website/ts/components/ui/alert.tsx
+++ b/packages/website/ts/components/ui/alert.tsx
@@ -1,19 +1,17 @@
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {AlertTypes} from 'ts/types';
-
-const CUSTOM_GREEN = 'rgb(137, 199, 116)';
+import { AlertTypes } from 'ts/types';
+import { colors } from 'ts/utils/colors';
interface AlertProps {
type: AlertTypes;
- message: string|React.ReactNode;
+ message: string | React.ReactNode;
}
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,
diff --git a/packages/website/ts/components/ui/badge.tsx b/packages/website/ts/components/ui/badge.tsx
index 15d5ea227..7f7ea006e 100644
--- a/packages/website/ts/components/ui/badge.tsx
+++ b/packages/website/ts/components/ui/badge.tsx
@@ -1,7 +1,6 @@
import * as _ from 'lodash';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {Styles} from 'ts/types';
+import { Styles } from 'ts/types';
const styles: Styles = {
badge: {
@@ -43,14 +42,14 @@ export class Badge extends React.Component<BadgeProps, BadgeState> {
<div
className="p1 center"
style={badgeStyle}
- onMouseOver={this.setHoverState.bind(this, true)}
- onMouseOut={this.setHoverState.bind(this, false)}
+ onMouseOver={this._setHoverState.bind(this, true)}
+ onMouseOut={this._setHoverState.bind(this, false)}
>
{this.props.title}
</div>
);
}
- private setHoverState(isHovering: boolean) {
+ private _setHoverState(isHovering: boolean) {
this.setState({
isHovering,
});
diff --git a/packages/website/ts/components/ui/copy_icon.tsx b/packages/website/ts/components/ui/copy_icon.tsx
index 5f8e6a060..df55e0922 100644
--- a/packages/website/ts/components/ui/copy_icon.tsx
+++ b/packages/website/ts/components/ui/copy_icon.tsx
@@ -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;
@@ -15,8 +15,8 @@ interface CopyIconState {
}
export class CopyIcon extends React.Component<CopyIconProps, CopyIconState> {
- private copyTooltipTimeoutId: number;
- private copyable: HTMLInputElement;
+ private _copyTooltipTimeoutId: number;
+ private _copyable: HTMLInputElement;
constructor(props: CopyIconProps) {
super(props);
this.state = {
@@ -25,57 +25,55 @@ export class CopyIcon extends React.Component<CopyIconProps, CopyIconState> {
}
public componentDidUpdate() {
// Remove tooltip if hover away
- if (!this.state.isHovering && this.copyTooltipTimeoutId) {
- clearInterval(this.copyTooltipTimeoutId);
- this.hideTooltip();
+ if (!this.state.isHovering && this._copyTooltipTimeoutId) {
+ clearInterval(this._copyTooltipTimeoutId);
+ this._hideTooltip();
}
}
public render() {
return (
<div className="inline-block">
- <CopyToClipboard text={this.props.data} onCopy={this.onCopy.bind(this)}>
- <div
- className="inline flex"
- style={{cursor: 'pointer', color: colors.amber600}}
- ref={this.setRefToProperty.bind(this)}
- data-tip={true}
- data-for="copy"
- data-event="click"
- data-iscapture={true} // This let's the click event continue to propogate
- onMouseOver={this.setHoverState.bind(this, true)}
- onMouseOut={this.setHoverState.bind(this, false)}
- >
- <div>
- <i style={{fontSize: 15}} className="zmdi zmdi-copy" />
- </div>
- {this.props.callToAction &&
- <div className="pl1">{this.props.callToAction}</div>
- }
+ <CopyToClipboard text={this.props.data} onCopy={this._onCopy.bind(this)}>
+ <div
+ className="inline flex"
+ style={{ cursor: 'pointer', color: colors.amber600 }}
+ ref={this._setRefToProperty.bind(this)}
+ data-tip={true}
+ data-for="copy"
+ data-event="click"
+ data-iscapture={true} // This let's the click event continue to propogate
+ onMouseOver={this._setHoverState.bind(this, true)}
+ onMouseOut={this._setHoverState.bind(this, false)}
+ >
+ <div>
+ <i style={{ fontSize: 15 }} className="zmdi zmdi-copy" />
</div>
- </CopyToClipboard>
+ {this.props.callToAction && <div className="pl1">{this.props.callToAction}</div>}
+ </div>
+ </CopyToClipboard>
<ReactTooltip id="copy">Copied!</ReactTooltip>
</div>
);
}
- private setRefToProperty(el: HTMLInputElement) {
- this.copyable = el;
+ private _setRefToProperty(el: HTMLInputElement) {
+ this._copyable = el;
}
- private setHoverState(isHovering: boolean) {
+ private _setHoverState(isHovering: boolean) {
this.setState({
isHovering,
});
}
- private onCopy() {
- if (this.copyTooltipTimeoutId) {
- clearInterval(this.copyTooltipTimeoutId);
+ private _onCopy() {
+ if (this._copyTooltipTimeoutId) {
+ clearInterval(this._copyTooltipTimeoutId);
}
const tooltipLifespanMs = 1000;
- this.copyTooltipTimeoutId = window.setTimeout(() => {
- this.hideTooltip();
+ this._copyTooltipTimeoutId = window.setTimeout(() => {
+ this._hideTooltip();
}, tooltipLifespanMs);
}
- private hideTooltip() {
- ReactTooltip.hide(ReactDOM.findDOMNode(this.copyable));
+ private _hideTooltip() {
+ ReactTooltip.hide(ReactDOM.findDOMNode(this._copyable));
}
}
diff --git a/packages/website/ts/components/ui/drop_down_menu_item.tsx b/packages/website/ts/components/ui/drop_down_menu_item.tsx
index 05b88f7ce..a578fb4f9 100644
--- a/packages/website/ts/components/ui/drop_down_menu_item.tsx
+++ b/packages/website/ts/components/ui/drop_down_menu_item.tsx
@@ -1,16 +1,10 @@
import * as _ from 'lodash';
import Menu from 'material-ui/Menu';
-import MenuItem from 'material-ui/MenuItem';
import Popover from 'material-ui/Popover';
import * as React from 'react';
-import {Link} from 'react-router-dom';
-import {
- Link as ScrollLink,
-} from 'react-scroll';
-import {Styles, WebsitePaths} from 'ts/types';
+import { colors } from 'ts/utils/colors';
const CHECK_CLOSE_POPOVER_INTERVAL_MS = 300;
-const CUSTOM_LIGHT_GRAY = '#848484';
const DEFAULT_STYLE = {
fontSize: 14,
};
@@ -34,8 +28,8 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro
menuItemStyle: DEFAULT_STYLE,
isNightVersion: false,
};
- private isHovering: boolean;
- private popoverCloseCheckIntervalId: number;
+ private _isHovering: boolean;
+ private _popoverCloseCheckIntervalId: number;
constructor(props: DropDownMenuItemProps) {
super(props);
this.state = {
@@ -43,73 +37,66 @@ export class DropDownMenuItem extends React.Component<DropDownMenuItemProps, Dro
};
}
public componentDidMount() {
- this.popoverCloseCheckIntervalId = window.setInterval(() => {
- this.checkIfShouldClosePopover();
+ this._popoverCloseCheckIntervalId = window.setInterval(() => {
+ this._checkIfShouldClosePopover();
}, CHECK_CLOSE_POPOVER_INTERVAL_MS);
}
public componentWillUnmount() {
- window.clearInterval(this.popoverCloseCheckIntervalId);
+ window.clearInterval(this._popoverCloseCheckIntervalId);
}
public render() {
const colorStyle = this.props.isNightVersion ? 'white' : this.props.style.color;
return (
<div
- style={{...this.props.style, color: colorStyle}}
- onMouseEnter={this.onHover.bind(this)}
- onMouseLeave={this.onHoverOff.bind(this)}
+ style={{ ...this.props.style, color: colorStyle }}
+ onMouseEnter={this._onHover.bind(this)}
+ onMouseLeave={this._onHoverOff.bind(this)}
>
<div className="flex relative">
- <div style={{paddingRight: 10}}>
- {this.props.title}
- </div>
- <div className="absolute" style={{paddingLeft: 3, right: 3, top: -2}}>
- <i className="zmdi zmdi-caret-right" style={{fontSize: 22}} />
+ <div style={{ paddingRight: 10 }}>{this.props.title}</div>
+ <div className="absolute" style={{ paddingLeft: 3, right: 3, top: -2 }}>
+ <i className="zmdi zmdi-caret-right" style={{ fontSize: 22 }} />
</div>
</div>
<Popover
open={this.state.isDropDownOpen}
anchorEl={this.state.anchorEl}
- anchorOrigin={{horizontal: 'middle', vertical: 'bottom'}}
- targetOrigin={{horizontal: 'middle', vertical: 'top'}}
- onRequestClose={this.closePopover.bind(this)}
+ anchorOrigin={{ horizontal: 'middle', vertical: 'bottom' }}
+ targetOrigin={{ horizontal: 'middle', vertical: 'top' }}
+ onRequestClose={this._closePopover.bind(this)}
useLayerForClickAway={false}
>
- <div
- onMouseEnter={this.onHover.bind(this)}
- onMouseLeave={this.onHoverOff.bind(this)}
- >
- <Menu style={{color: CUSTOM_LIGHT_GRAY}}>
- {this.props.subMenuItems}
- </Menu>
+ <div onMouseEnter={this._onHover.bind(this)} onMouseLeave={this._onHoverOff.bind(this)}>
+ <Menu style={{ color: colors.grey }}>{this.props.subMenuItems}</Menu>
</div>
</Popover>
</div>
);
}
- private onHover(event: React.FormEvent<HTMLInputElement>) {
- this.isHovering = true;
- this.checkIfShouldOpenPopover(event);
+ private _onHover(event: React.FormEvent<HTMLInputElement>) {
+ this._isHovering = true;
+ this._checkIfShouldOpenPopover(event);
}
- private checkIfShouldOpenPopover(event: React.FormEvent<HTMLInputElement>) {
+ private _checkIfShouldOpenPopover(event: React.FormEvent<HTMLInputElement>) {
if (this.state.isDropDownOpen) {
return; // noop
}
this.setState({
- isDropDownOpen: true,
- anchorEl: event.currentTarget,
+ isDropDownOpen: true,
+ anchorEl: event.currentTarget,
});
}
- private onHoverOff(event: React.FormEvent<HTMLInputElement>) {
- this.isHovering = false;
+ private _onHoverOff(event: React.FormEvent<HTMLInputElement>) {
+ this._isHovering = false;
}
- private checkIfShouldClosePopover() {
- if (!this.state.isDropDownOpen || this.isHovering) {
+ private _checkIfShouldClosePopover() {
+ if (!this.state.isDropDownOpen || this._isHovering) {
return; // noop
}
- this.closePopover();
+ this._closePopover();
}
- private closePopover() {
+ private _closePopover() {
this.setState({
isDropDownOpen: false,
});
diff --git a/packages/website/ts/components/ui/ethereum_address.tsx b/packages/website/ts/components/ui/ethereum_address.tsx
index b3bc0bc59..b75d97e39 100644
--- a/packages/website/ts/components/ui/ethereum_address.tsx
+++ b/packages/website/ts/components/ui/ethereum_address.tsx
@@ -1,8 +1,8 @@
import * as React from 'react';
import ReactTooltip = require('react-tooltip');
-import {EtherScanIcon} from 'ts/components/ui/etherscan_icon';
-import {EtherscanLinkSuffixes} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { EtherScanIcon } from 'ts/components/ui/etherscan_icon';
+import { EtherscanLinkSuffixes } from 'ts/types';
+import { utils } from 'ts/utils/utils';
interface EthereumAddressProps {
address: string;
@@ -14,19 +14,14 @@ export const EthereumAddress = (props: EthereumAddressProps) => {
const truncatedAddress = utils.getAddressBeginAndEnd(props.address);
return (
<div>
- <div
- className="inline"
- style={{fontSize: 13}}
- data-tip={true}
- data-for={tooltipId}
- >
+ <div className="inline" style={{ fontSize: 13 }} data-tip={true} data-for={tooltipId}>
{truncatedAddress}
</div>
<div className="pl1 inline">
<EtherScanIcon
addressOrTxHash={props.address}
networkId={props.networkId}
- etherscanLinkSuffixes={EtherscanLinkSuffixes.address}
+ etherscanLinkSuffixes={EtherscanLinkSuffixes.Address}
/>
</div>
<ReactTooltip id={tooltipId}>{props.address}</ReactTooltip>
diff --git a/packages/website/ts/components/ui/etherscan_icon.tsx b/packages/website/ts/components/ui/etherscan_icon.tsx
index 9b4d172f1..3b17bd0fa 100644
--- a/packages/website/ts/components/ui/etherscan_icon.tsx
+++ b/packages/website/ts/components/ui/etherscan_icon.tsx
@@ -1,9 +1,9 @@
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 {utils} from 'ts/utils/utils';
+import { EtherscanLinkSuffixes } from 'ts/types';
+import { colors } from 'ts/utils/colors';
+import { utils } from 'ts/utils/utils';
interface EtherScanIconProps {
addressOrTxHash: string;
@@ -13,38 +13,29 @@ 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 (
<div className="inline">
- {!_.isUndefined(etherscanLinkIfExists) ?
- <a
- href={etherscanLinkIfExists}
- target="_blank"
- >
+ {!_.isUndefined(etherscanLinkIfExists) ? (
+ <a href={etherscanLinkIfExists} target="_blank">
{renderIcon()}
- </a> :
- <div
- className="inline"
- data-tip={true}
- data-for={transactionTooltipId}
- >
+ </a>
+ ) : (
+ <div className="inline" data-tip={true} data-for={transactionTooltipId}>
{renderIcon()}
<ReactTooltip id={transactionTooltipId}>
Your network (id: {props.networkId}) is not supported by Etherscan
</ReactTooltip>
</div>
- }
+ )}
</div>
);
};
function renderIcon() {
- return (
- <i
- style={{color: colors.amber600}}
- className="zmdi zmdi-open-in-new"
- />
- );
+ return <i style={{ color: colors.amber600 }} className="zmdi zmdi-open-in-new" />;
}
diff --git a/packages/website/ts/components/ui/fake_text_field.tsx b/packages/website/ts/components/ui/fake_text_field.tsx
index 90bc47f01..f3d9410f6 100644
--- a/packages/website/ts/components/ui/fake_text_field.tsx
+++ b/packages/website/ts/components/ui/fake_text_field.tsx
@@ -1,7 +1,6 @@
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {InputLabel} from 'ts/components/ui/input_label';
-import {Styles} from 'ts/types';
+import { InputLabel } from 'ts/components/ui/input_label';
+import { Styles } from 'ts/types';
const styles: Styles = {
hr: {
@@ -26,7 +25,7 @@ export function FakeTextField(props: FakeTextFieldProps) {
return (
<div className="relative">
{props.label !== '' && <InputLabel text={props.label} />}
- <div className="pb2" style={{height: 23}}>
+ <div className="pb2" style={{ height: 23 }}>
{props.children}
</div>
<hr style={styles.hr} />
diff --git a/packages/website/ts/components/ui/flash_message.tsx b/packages/website/ts/components/ui/flash_message.tsx
index ab4edbbb0..2cb1fc764 100644
--- a/packages/website/ts/components/ui/flash_message.tsx
+++ b/packages/website/ts/components/ui/flash_message.tsx
@@ -1,13 +1,13 @@
import * as _ from 'lodash';
import Snackbar from 'material-ui/Snackbar';
import * as React from 'react';
-import {Dispatcher} from 'ts/redux/dispatcher';
+import { Dispatcher } from 'ts/redux/dispatcher';
const SHOW_DURATION_MS = 4000;
interface FlashMessageProps {
dispatcher: Dispatcher;
- flashMessage?: string|React.ReactNode;
+ flashMessage?: string | React.ReactNode;
showDurationMs?: number;
bodyStyle?: React.CSSProperties;
}
@@ -26,7 +26,7 @@ export class FlashMessage extends React.Component<FlashMessageProps, FlashMessag
open={true}
message={this.props.flashMessage}
autoHideDuration={this.props.showDurationMs}
- onRequestClose={this.onClose.bind(this)}
+ onRequestClose={this._onClose.bind(this)}
bodyStyle={this.props.bodyStyle}
/>
);
@@ -34,7 +34,7 @@ export class FlashMessage extends React.Component<FlashMessageProps, FlashMessag
return null;
}
}
- private onClose() {
+ private _onClose() {
this.props.dispatcher.hideFlashMessage();
}
}
diff --git a/packages/website/ts/components/ui/help_tooltip.tsx b/packages/website/ts/components/ui/help_tooltip.tsx
index 003b795ef..d827eebb9 100644
--- a/packages/website/ts/components/ui/help_tooltip.tsx
+++ b/packages/website/ts/components/ui/help_tooltip.tsx
@@ -9,13 +9,13 @@ interface HelpTooltipProps {
export const HelpTooltip = (props: HelpTooltipProps) => {
return (
<div
- style={{...props.style}}
+ style={{ ...props.style }}
className="inline-block"
data-tip={props.explanation}
data-for="helpTooltip"
data-multiline={true}
>
- <i style={{fontSize: 16}} className="zmdi zmdi-help" />
+ <i style={{ fontSize: 16 }} className="zmdi zmdi-help" />
<ReactTooltip id="helpTooltip" />
</div>
);
diff --git a/packages/website/ts/components/ui/identicon.tsx b/packages/website/ts/components/ui/identicon.tsx
index a741ae43b..bad6c2a78 100644
--- a/packages/website/ts/components/ui/identicon.tsx
+++ b/packages/website/ts/components/ui/identicon.tsx
@@ -1,7 +1,7 @@
import blockies = require('blockies');
import * as _ from 'lodash';
import * as React from 'react';
-import {constants} from 'ts/utils/constants';
+import { constants } from 'ts/utils/constants';
interface IdenticonProps {
address: string;
@@ -27,9 +27,21 @@ export class Identicon extends React.Component<IdenticonProps, IdenticonState> {
return (
<div
className="circle mx-auto relative transitionFix"
- style={{width: diameter, height: diameter, overflow: 'hidden', ...this.props.style}}
+ style={{
+ width: diameter,
+ height: diameter,
+ overflow: 'hidden',
+ ...this.props.style,
+ }}
>
- <img src={icon.toDataURL()} style={{width: diameter, height: diameter, imageRendering: 'pixelated'}}/>
+ <img
+ src={icon.toDataURL()}
+ style={{
+ width: diameter,
+ height: diameter,
+ imageRendering: 'pixelated',
+ }}
+ />
</div>
);
}
diff --git a/packages/website/ts/components/ui/input_label.tsx b/packages/website/ts/components/ui/input_label.tsx
index 852097519..e2009ad20 100644
--- a/packages/website/ts/components/ui/input_label.tsx
+++ b/packages/website/ts/components/ui/input_label.tsx
@@ -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',
@@ -21,7 +21,5 @@ const styles = {
};
export const InputLabel = (props: InputLabelProps) => {
- return (
- <label style={styles.label}>{props.text}</label>
- );
+ return <label style={styles.label}>{props.text}</label>;
};
diff --git a/packages/website/ts/components/ui/labeled_switcher.tsx b/packages/website/ts/components/ui/labeled_switcher.tsx
deleted file mode 100644
index 80a8fbe94..000000000
--- a/packages/website/ts/components/ui/labeled_switcher.tsx
+++ /dev/null
@@ -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,
- });
- }
- }
-}
diff --git a/packages/website/ts/components/ui/lifecycle_raised_button.tsx b/packages/website/ts/components/ui/lifecycle_raised_button.tsx
index cba94ca8c..8ff856a75 100644
--- a/packages/website/ts/components/ui/lifecycle_raised_button.tsx
+++ b/packages/website/ts/components/ui/lifecycle_raised_button.tsx
@@ -1,25 +1,24 @@
import * as _ from 'lodash';
import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
-import {Blockchain} from 'ts/blockchain';
-import {Token} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { colors } from 'ts/utils/colors';
+import { utils } from 'ts/utils/utils';
const COMPLETE_STATE_SHOW_LENGTH_MS = 2000;
enum ButtonState {
- READY,
- LOADING,
- COMPLETE,
+ READY,
+ LOADING,
+ COMPLETE,
}
interface LifeCycleRaisedButtonProps {
isHidden?: boolean;
isDisabled?: boolean;
isPrimary?: boolean;
- labelReady: React.ReactNode|string;
- labelLoading: React.ReactNode|string;
- labelComplete: React.ReactNode|string;
+ labelReady: React.ReactNode | string;
+ labelLoading: React.ReactNode | string;
+ labelComplete: React.ReactNode | string;
onClickAsyncFn: () => Promise<boolean>;
backgroundColor?: string;
labelColor?: string;
@@ -29,15 +28,14 @@ interface LifeCycleRaisedButtonState {
buttonState: ButtonState;
}
-export class LifeCycleRaisedButton extends
- React.Component<LifeCycleRaisedButtonProps, LifeCycleRaisedButtonState> {
+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;
+ private _buttonTimeoutId: number;
+ private _didUnmount: boolean;
constructor(props: LifeCycleRaisedButtonProps) {
super(props);
this.state = {
@@ -45,8 +43,8 @@ export class LifeCycleRaisedButton extends
};
}
public componentWillUnmount() {
- clearTimeout(this.buttonTimeoutId);
- this.didUnmount = true;
+ clearTimeout(this._buttonTimeoutId);
+ this._didUnmount = true;
}
public render() {
if (this.props.isHidden) {
@@ -71,7 +69,7 @@ export class LifeCycleRaisedButton extends
<RaisedButton
primary={this.props.isPrimary}
label={label}
- style={{width: '100%'}}
+ style={{ width: '100%' }}
backgroundColor={this.props.backgroundColor}
labelColor={this.props.labelColor}
onTouchTap={this.onClickAsync.bind(this)}
@@ -84,14 +82,14 @@ export class LifeCycleRaisedButton extends
buttonState: ButtonState.LOADING,
});
const didSucceed = await this.props.onClickAsyncFn();
- if (this.didUnmount) {
+ if (this._didUnmount) {
return; // noop since unmount called before async callback returned.
}
if (didSucceed) {
this.setState({
buttonState: ButtonState.COMPLETE,
});
- this.buttonTimeoutId = window.setTimeout(() => {
+ this._buttonTimeoutId = window.setTimeout(() => {
this.setState({
buttonState: ButtonState.READY,
});
diff --git a/packages/website/ts/components/ui/loading.tsx b/packages/website/ts/components/ui/loading.tsx
index 83636b5ff..aa319e9e9 100644
--- a/packages/website/ts/components/ui/loading.tsx
+++ b/packages/website/ts/components/ui/loading.tsx
@@ -1,9 +1,9 @@
import * as _ from 'lodash';
import Paper from 'material-ui/Paper';
import * as React from 'react';
-import {DefaultPlayer as Video} from 'react-html5video';
+import { DefaultPlayer as Video } from 'react-html5video';
import 'react-html5video/dist/styles.css';
-import {utils} from 'ts/utils/utils';
+import { utils } from 'ts/utils/utils';
interface LoadingProps {}
@@ -12,11 +12,12 @@ interface LoadingState {}
export class Loading extends React.Component<LoadingProps, LoadingState> {
public render() {
return (
- <div className="pt4 sm-px2 sm-pt2 sm-m1" style={{height: 500}}>
- <Paper className="mx-auto" style={{maxWidth: 400}}>
- {utils.isUserOnMobile() ?
- <img className="p1" src="/gifs/0xAnimation.gif" width="96%" /> :
- <div style={{pointerEvents: 'none'}}>
+ <div className="pt4 sm-px2 sm-pt2 sm-m1" style={{ height: 500 }}>
+ <Paper className="mx-auto" style={{ maxWidth: 400 }}>
+ {utils.isUserOnMobile() ? (
+ <img className="p1" src="/gifs/0xAnimation.gif" width="96%" />
+ ) : (
+ <div style={{ pointerEvents: 'none' }}>
<Video
autoPlay={true}
loop={true}
@@ -27,8 +28,10 @@ export class Loading extends React.Component<LoadingProps, LoadingState> {
<source src="/videos/0xAnimation.mp4" type="video/mp4" />
</Video>
</div>
- }
- <div className="center pt2" style={{paddingBottom: 11}}>Connecting to the blockchain...</div>
+ )}
+ <div className="center pt2" style={{ paddingBottom: 11 }}>
+ Connecting to the blockchain...
+ </div>
</Paper>
</div>
);
diff --git a/packages/website/ts/components/ui/menu_item.tsx b/packages/website/ts/components/ui/menu_item.tsx
index 862f28457..3482f436c 100644
--- a/packages/website/ts/components/ui/menu_item.tsx
+++ b/packages/website/ts/components/ui/menu_item.tsx
@@ -1,9 +1,6 @@
import * as _ from 'lodash';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {Link} from 'react-router-dom';
-import {Styles} from 'ts/types';
-import {constants} from 'ts/utils/constants';
+import { Link } from 'react-router-dom';
interface MenuItemProps {
to: string;
@@ -33,20 +30,20 @@ export class MenuItem extends React.Component<MenuItemProps, MenuItemState> {
opacity: this.state.isHovering ? 0.5 : 1,
};
return (
- <Link to={this.props.to} style={{textDecoration: 'none', ...this.props.style}}>
+ <Link to={this.props.to} style={{ textDecoration: 'none', ...this.props.style }}>
<div
onClick={this.props.onClick.bind(this)}
className={`mx-auto ${this.props.className}`}
style={menuItemStyles}
- onMouseEnter={this.onToggleHover.bind(this, true)}
- onMouseLeave={this.onToggleHover.bind(this, false)}
+ onMouseEnter={this._onToggleHover.bind(this, true)}
+ onMouseLeave={this._onToggleHover.bind(this, false)}
>
{this.props.children}
</div>
</Link>
);
}
- private onToggleHover(isHovering: boolean) {
+ private _onToggleHover(isHovering: boolean) {
this.setState({
isHovering,
});
diff --git a/packages/website/ts/components/ui/party.tsx b/packages/website/ts/components/ui/party.tsx
index 5bafa6071..ca2577b61 100644
--- a/packages/website/ts/components/ui/party.tsx
+++ b/packages/website/ts/components/ui/party.tsx
@@ -1,16 +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 {utils} from 'ts/utils/utils';
+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 MIN_ADDRESS_WIDTH = 60;
const IMAGE_DIMENSION = 100;
const IDENTICON_DIAMETER = 95;
-const CHECK_MARK_GREEN = 'rgb(0, 195, 62)';
interface PartyProps {
label: string;
@@ -33,10 +31,7 @@ export class Party extends React.Component<PartyProps, PartyState> {
public render() {
const label = this.props.label;
const address = this.props.address;
- const tooltipId = `${label}-${address}-tooltip`;
const identiconDiameter = this.props.identiconDiameter;
- const addressWidth = identiconDiameter > MIN_ADDRESS_WIDTH ?
- identiconDiameter : MIN_ADDRESS_WIDTH;
const emptyIdenticonStyles = {
width: identiconDiameter,
height: identiconDiameter,
@@ -49,100 +44,94 @@ 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`;
const uniqueNameAndSymbolTooltipId = `${this.props.address}-${isRegistered}-uniqueTooltip`;
return (
- <div style={{overflow: 'hidden'}}>
+ <div style={{ overflow: 'hidden' }}>
<div className="pb1 center">{label}</div>
- {_.isEmpty(address) ?
- <div
- className="circle mx-auto"
- style={emptyIdenticonStyles}
- /> :
- <a
- href={etherscanLinkIfExists}
- target="_blank"
- >
- {isRegistered && !_.isUndefined(this.props.alternativeImage) ?
- <img
- style={tokenImageStyle}
- src={this.props.alternativeImage}
- /> :
- <div
- className="mx-auto"
- style={{height: identiconDiameter, width: identiconDiameter}}
- >
- <Identicon
- address={this.props.address}
- diameter={identiconDiameter}
- style={this.props.identiconStyle}
- />
- </div>
- }
- </a>
- }
- <div
- className="mx-auto center pt1"
- >
- <div style={{height: 25}}>
+ {_.isEmpty(address) ? (
+ <div className="circle mx-auto" style={emptyIdenticonStyles} />
+ ) : (
+ <a href={etherscanLinkIfExists} target="_blank">
+ {isRegistered && !_.isUndefined(this.props.alternativeImage) ? (
+ <img style={tokenImageStyle} src={this.props.alternativeImage} />
+ ) : (
+ <div className="mx-auto" style={{ height: identiconDiameter, width: identiconDiameter }}>
+ <Identicon
+ address={this.props.address}
+ diameter={identiconDiameter}
+ style={this.props.identiconStyle}
+ />
+ </div>
+ )}
+ </a>
+ )}
+ <div className="mx-auto center pt1">
+ <div style={{ height: 25 }}>
<EthereumAddress address={address} networkId={this.props.networkId} />
</div>
- {!_.isUndefined(this.props.isInTokenRegistry) &&
+ {!_.isUndefined(this.props.isInTokenRegistry) && (
<div>
<div
data-tip={true}
data-for={registeredTooltipId}
className="mx-auto"
- style={{fontSize: 13, width: 127}}
+ style={{ fontSize: 13, width: 127 }}
>
- <span style={{color: isRegistered ? CHECK_MARK_GREEN : colors.red500}}>
+ <span
+ style={{
+ color: isRegistered ? colors.brightGreen : colors.red500,
+ }}
+ >
<i
className={`zmdi ${isRegistered ? 'zmdi-check-circle' : 'zmdi-alert-triangle'}`}
/>
</span>{' '}
<span>{isRegistered ? 'Registered' : 'Unregistered'} token</span>
<ReactTooltip id={registeredTooltipId}>
- {isRegistered ?
+ {isRegistered ? (
<div>
This token address was found in the token registry<br />
smart contract and is therefore believed to be a<br />
legitimate token.
- </div> :
+ </div>
+ ) : (
<div>
This token is not included in the token registry<br />
smart contract. We cannot guarantee the legitimacy<br />
of this token. Make sure to verify its address on Etherscan.
</div>
- }
+ )}
</ReactTooltip>
</div>
</div>
- }
- {!_.isUndefined(this.props.hasUniqueNameAndSymbol) && !this.props.hasUniqueNameAndSymbol &&
- <div>
- <div
- data-tip={true}
- data-for={uniqueNameAndSymbolTooltipId}
- className="mx-auto"
- style={{fontSize: 13, width: 127}}
- >
- <span style={{color: colors.red500}}>
- <i
- className="zmdi zmdi-alert-octagon"
- />
- </span>{' '}
- <span>Suspicious token</span>
- <ReactTooltip id={uniqueNameAndSymbolTooltipId}>
- This token shares it's name, symbol or both with<br />
- a token in the 0x Token Registry but it has a different<br />
- smart contract address. This is most likely a scam token!
- </ReactTooltip>
+ )}
+ {!_.isUndefined(this.props.hasUniqueNameAndSymbol) &&
+ !this.props.hasUniqueNameAndSymbol && (
+ <div>
+ <div
+ data-tip={true}
+ data-for={uniqueNameAndSymbolTooltipId}
+ className="mx-auto"
+ style={{ fontSize: 13, width: 127 }}
+ >
+ <span style={{ color: colors.red500 }}>
+ <i className="zmdi zmdi-alert-octagon" />
+ </span>{' '}
+ <span>Suspicious token</span>
+ <ReactTooltip id={uniqueNameAndSymbolTooltipId}>
+ This token shares it's name, symbol or both with<br />
+ a token in the 0x Token Registry but it has a different<br />
+ smart contract address. This is most likely a scam token!
+ </ReactTooltip>
+ </div>
</div>
- </div>
- }
+ )}
</div>
</div>
);
diff --git a/packages/website/ts/components/ui/required_label.tsx b/packages/website/ts/components/ui/required_label.tsx
index db69d7278..a5e7a22ce 100644
--- a/packages/website/ts/components/ui/required_label.tsx
+++ b/packages/website/ts/components/ui/required_label.tsx
@@ -1,15 +1,15 @@
-import {colors} from 'material-ui/styles';
import * as React from 'react';
+import { colors } from 'ts/utils/colors';
export interface RequiredLabelProps {
- label: string|React.ReactNode;
+ label: string | React.ReactNode;
}
export const RequiredLabel = (props: RequiredLabelProps) => {
return (
<span>
{props.label}
- <span style={{color: colors.red600}}>*</span>
+ <span style={{ color: colors.red600 }}>*</span>
</span>
);
};
diff --git a/packages/website/ts/components/ui/simple_loading.tsx b/packages/website/ts/components/ui/simple_loading.tsx
index d55d7851d..81744196d 100644
--- a/packages/website/ts/components/ui/simple_loading.tsx
+++ b/packages/website/ts/components/ui/simple_loading.tsx
@@ -1,5 +1,4 @@
import CircularProgress from 'material-ui/CircularProgress';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
export interface SimpleLoadingProps {
@@ -8,15 +7,10 @@ export interface SimpleLoadingProps {
export const SimpleLoading = (props: SimpleLoadingProps) => {
return (
- <div className="mx-auto pt3" style={{maxWidth: 400, height: 409}}>
- <div
- className="relative"
- style={{top: '50%', transform: 'translateY(-50%)', height: 95}}
- >
+ <div className="mx-auto pt3" style={{ maxWidth: 400, height: 409 }}>
+ <div className="relative" style={{ top: '50%', transform: 'translateY(-50%)', height: 95 }}>
<CircularProgress />
- <div className="pt3 pb3">
- {props.message}
- </div>
+ <div className="pt3 pb3">{props.message}</div>
</div>
</div>
);
diff --git a/packages/website/ts/components/ui/swap_icon.tsx b/packages/website/ts/components/ui/swap_icon.tsx
index 2e6ae89bb..c41592287 100644
--- a/packages/website/ts/components/ui/swap_icon.tsx
+++ b/packages/website/ts/components/ui/swap_icon.tsx
@@ -1,7 +1,6 @@
import * as _ from 'lodash';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {constants} from 'ts/utils/constants';
+import { colors } from 'ts/utils/colors';
interface SwapIconProps {
swapTokensFn: () => void;
@@ -26,19 +25,16 @@ export class SwapIcon extends React.Component<SwapIconProps, SwapIconState> {
return (
<div
className="mx-auto pt4"
- style={{cursor: 'pointer', height: 50, width: 37.5}}
+ style={{ cursor: 'pointer', height: 50, width: 37.5 }}
onClick={this.props.swapTokensFn}
- onMouseEnter={this.onToggleHover.bind(this, true)}
- onMouseLeave={this.onToggleHover.bind(this, false)}
+ onMouseEnter={this._onToggleHover.bind(this, true)}
+ onMouseLeave={this._onToggleHover.bind(this, false)}
>
- <i
- style={swapStyles}
- className="zmdi zmdi-swap"
- />
+ <i style={swapStyles} className="zmdi zmdi-swap" />
</div>
);
}
- private onToggleHover(isHovering: boolean) {
+ private _onToggleHover(isHovering: boolean) {
this.setState({
isHovering,
});
diff --git a/packages/website/ts/components/ui/token_icon.tsx b/packages/website/ts/components/ui/token_icon.tsx
index d3a7c9a8c..ff57a96de 100644
--- a/packages/website/ts/components/ui/token_icon.tsx
+++ b/packages/website/ts/components/ui/token_icon.tsx
@@ -1,7 +1,7 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {Identicon} from 'ts/components/ui/identicon';
-import {Token} from 'ts/types';
+import { Identicon } from 'ts/components/ui/identicon';
+import { Token } from 'ts/types';
interface TokenIconProps {
token: Token;
@@ -16,13 +16,11 @@ export class TokenIcon extends React.Component<TokenIconProps, TokenIconState> {
const diameter = this.props.diameter;
return (
<div>
- {(token.isRegistered && !_.isUndefined(token.iconUrl)) ?
- <img
- style={{width: diameter, height: diameter}}
- src={token.iconUrl}
- /> :
+ {token.isRegistered && !_.isUndefined(token.iconUrl) ? (
+ <img style={{ width: diameter, height: diameter }} src={token.iconUrl} />
+ ) : (
<Identicon address={token.address} diameter={diameter} />
- }
+ )}
</div>
);
}
diff --git a/packages/website/ts/components/visual_order.tsx b/packages/website/ts/components/visual_order.tsx
index 037a321ff..092954086 100644
--- a/packages/website/ts/components/visual_order.tsx
+++ b/packages/website/ts/components/visual_order.tsx
@@ -1,10 +1,9 @@
-import {ZeroEx} from '0x.js';
+import { ZeroEx } from '0x.js';
import * as _ from 'lodash';
import * as React from 'react';
-import {Party} from 'ts/components/ui/party';
-import {AssetToken, Token, TokenByAddress} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+import { Party } from 'ts/components/ui/party';
+import { AssetToken, Token, TokenByAddress } from 'ts/types';
+import { utils } from 'ts/utils/utils';
const PRECISION = 5;
@@ -43,13 +42,13 @@ export class VisualOrder extends React.Component<VisualOrderProps, VisualOrderSt
</div>
<div className="col col-2 center pt1">
<div className="pb1">
- {this.renderAmount(this.props.takerAssetToken, this.props.takerToken)}
+ {this._renderAmount(this.props.takerAssetToken, this.props.takerToken)}
</div>
<div className="lg-p2 md-p2 sm-p1">
- <img src="/images/trade_arrows.png" style={{width: 47}} />
+ <img src="/images/trade_arrows.png" style={{ width: 47 }} />
</div>
<div className="pt1">
- {this.renderAmount(this.props.makerAssetToken, this.props.makerToken)}
+ {this._renderAmount(this.props.makerAssetToken, this.props.makerToken)}
</div>
</div>
<div className="col col-5 center">
@@ -66,10 +65,10 @@ export class VisualOrder extends React.Component<VisualOrderProps, VisualOrderSt
</div>
);
}
- private renderAmount(assetToken: AssetToken, token: Token) {
+ private _renderAmount(assetToken: AssetToken, token: Token) {
const unitAmount = ZeroEx.toUnitAmount(assetToken.amount, token.decimals);
return (
- <div style={{fontSize: 13}}>
+ <div style={{ fontSize: 13 }}>
{unitAmount.toNumber().toFixed(PRECISION)} {token.symbol}
</div>
);
diff --git a/packages/website/ts/containers/connect_documentation.tsx b/packages/website/ts/containers/connect_documentation.tsx
index b074d955b..3e02a7d05 100644
--- a/packages/website/ts/containers/connect_documentation.tsx
+++ b/packages/website/ts/containers/connect_documentation.tsx
@@ -1,18 +1,14 @@
-import BigNumber from 'bignumber.js';
import * as _ from 'lodash';
import * as React from 'react';
-import {connect} from 'react-redux';
-import {Dispatch, Store as ReduxStore} from 'redux';
-import {Blockchain} from 'ts/blockchain';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
-import {
- Documentation as DocumentationComponent,
- DocumentationAllProps,
-} from 'ts/pages/documentation/documentation';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {State} from 'ts/redux/reducer';
-import {DocsInfoConfig, WebsitePaths} from 'ts/types';
-import {typeDocUtils} from 'ts/utils/typedoc_utils';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
+import { Documentation as DocumentationComponent, DocumentationAllProps } 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 { typeDocUtils } from 'ts/utils/typedoc_utils';
/* tslint:disable:no-var-requires */
const IntroMarkdown = require('md/docs/connect/introduction');
@@ -23,7 +19,8 @@ const connectDocSections = {
introduction: 'introduction',
installation: 'installation',
httpClient: 'httpClient',
- types: 'types',
+ webSocketOrderbookChannel: 'webSocketOrderbookChannel',
+ types: constants.TYPES_SECTION_NAME,
};
const docsInfoConfig: DocsInfoConfig = {
@@ -33,18 +30,11 @@ const docsInfoConfig: DocsInfoConfig = {
websitePath: WebsitePaths.Connect,
docsJsonRoot: 'https://s3.amazonaws.com/connect-docs-jsons',
menu: {
- introduction: [
- connectDocSections.introduction,
- ],
- install: [
- connectDocSections.installation,
- ],
- httpClient: [
- connectDocSections.httpClient,
- ],
- types: [
- connectDocSections.types,
- ],
+ introduction: [connectDocSections.introduction],
+ install: [connectDocSections.installation],
+ httpClient: [connectDocSections.httpClient],
+ webSocketOrderbookChannel: [connectDocSections.webSocketOrderbookChannel],
+ types: [connectDocSections.types],
},
sectionNameToMarkdown: {
[connectDocSections.introduction]: IntroMarkdown,
@@ -56,6 +46,9 @@ const docsInfoConfig: DocsInfoConfig = {
'Client',
'FeesRequest',
'FeesResponse',
+ 'OrderbookChannel',
+ 'OrderbookChannelHandler',
+ 'OrderbookChannelSubscriptionOpts',
'OrderbookRequest',
'OrderbookResponse',
'OrdersRequest',
@@ -64,14 +57,16 @@ const docsInfoConfig: DocsInfoConfig = {
'TokenTradeInfo',
'Order',
'SignedOrder',
+ 'ECSignature',
],
sectionNameToModulePath: {
[connectDocSections.httpClient]: ['"src/http_client"'],
+ [connectDocSections.webSocketOrderbookChannel]: ['"src/ws_orderbook_channel"'],
[connectDocSections.types]: ['"src/types"'],
},
menuSubsectionToVersionWhenIntroduced: {},
sections: connectDocSections,
- visibleConstructors: [connectDocSections.httpClient],
+ visibleConstructors: [connectDocSections.httpClient, connectDocSections.webSocketOrderbookChannel],
convertToDocAgnosticFormatFn: typeDocUtils.convertToDocAgnosticFormat.bind(typeDocUtils),
};
const docsInfo = new DocsInfo(docsInfoConfig);
@@ -96,5 +91,6 @@ const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
dispatcher: new Dispatcher(dispatch),
});
-export const Documentation: React.ComponentClass<DocumentationAllProps> =
- connect(mapStateToProps, mapDispatchToProps)(DocumentationComponent);
+export const Documentation: React.ComponentClass<DocumentationAllProps> = connect(mapStateToProps, mapDispatchToProps)(
+ DocumentationComponent,
+);
diff --git a/packages/website/ts/containers/generate_order_form.tsx b/packages/website/ts/containers/generate_order_form.tsx
index 864d2702e..3fd31087f 100644
--- a/packages/website/ts/containers/generate_order_form.tsx
+++ b/packages/website/ts/containers/generate_order_form.tsx
@@ -1,12 +1,11 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
-import {connect} from 'react-redux';
-import {Dispatch, Store as ReduxStore} from 'redux';
-import {Blockchain} from 'ts/blockchain';
-import {GenerateOrderForm as GenerateOrderFormComponent} from 'ts/components/generate_order/generate_order_form';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {State} from 'ts/redux/reducer';
+import { connect } from 'react-redux';
+import { Blockchain } from 'ts/blockchain';
+import { GenerateOrderForm as GenerateOrderFormComponent } from 'ts/components/generate_order/generate_order_form';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { State } from 'ts/redux/reducer';
import {
BlockchainErrs,
HashData,
@@ -50,5 +49,6 @@ const mapStateToProps = (state: State, ownProps: GenerateOrderFormProps): Connec
userAddress: state.userAddress,
});
-export const GenerateOrderForm: React.ComponentClass<GenerateOrderFormProps> =
- connect(mapStateToProps)(GenerateOrderFormComponent);
+export const GenerateOrderForm: React.ComponentClass<GenerateOrderFormProps> = connect(mapStateToProps)(
+ GenerateOrderFormComponent,
+);
diff --git a/packages/website/ts/containers/portal.tsx b/packages/website/ts/containers/portal.tsx
index 2987764f4..f0247935b 100644
--- a/packages/website/ts/containers/portal.tsx
+++ b/packages/website/ts/containers/portal.tsx
@@ -1,64 +1,50 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
-import {connect} from 'react-redux';
-import {Dispatch, Store as ReduxStore} from 'redux';
-import {
- Portal as PortalComponent,
- PortalAllProps as PortalComponentAllProps,
- PortalPassedProps as PortalComponentPassedProps,
-} from 'ts/components/portal';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {State} from 'ts/redux/reducer';
-import {
- BlockchainErrs,
- Fill,
- HashData,
- Order,
- ScreenWidths,
- Side,
- TokenByAddress,
- TokenStateByAddress,
-} from 'ts/types';
-import {constants} from 'ts/utils/constants';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { Portal as PortalComponent, PortalAllProps as PortalComponentAllProps } from 'ts/components/portal';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { State } from 'ts/redux/reducer';
+import { BlockchainErrs, HashData, Order, ScreenWidths, Side, TokenByAddress, TokenStateByAddress } from 'ts/types';
+import { constants } from 'ts/utils/constants';
-interface MapStateToProps {
+interface ConnectedState {
blockchainErr: BlockchainErrs;
blockchainIsLoaded: boolean;
hashData: HashData;
networkId: number;
nodeVersion: string;
- orderFillAmount: number;
+ orderFillAmount: BigNumber;
tokenByAddress: TokenByAddress;
tokenStateByAddress: TokenStateByAddress;
- userEtherBalance: number;
+ userEtherBalance: BigNumber;
screenWidth: ScreenWidths;
shouldBlockchainErrDialogBeOpen: boolean;
userAddress: string;
userSuppliedOrderCache: Order;
+ flashMessage?: string | React.ReactNode;
}
-interface ConnectedState {}
-
interface ConnectedDispatch {
dispatcher: Dispatcher;
}
const mapStateToProps = (state: State, ownProps: PortalComponentAllProps): ConnectedState => {
- 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) ?
- depositAssetToken.address : constants.NULL_ADDRESS;
- const receiveAmount = !_.isUndefined(receiveAssetToken.amount) ?
- receiveAssetToken.amount : new BigNumber(0);
- const depositAmount = !_.isUndefined(depositAssetToken.amount) ?
- depositAssetToken.amount : new BigNumber(0);
+ 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)
+ ? depositAssetToken.address
+ : constants.NULL_ADDRESS;
+ const receiveAmount = !_.isUndefined(receiveAssetToken.amount) ? receiveAssetToken.amount : new BigNumber(0);
+ const depositAmount = !_.isUndefined(depositAssetToken.amount) ? depositAssetToken.amount : new BigNumber(0);
const hashData = {
depositAmount,
depositTokenContractAddr: depositAddress,
- feeRecipientAddress: constants.FEE_RECIPIENT_ADDRESS,
+ feeRecipientAddress: constants.NULL_ADDRESS,
makerFee: constants.MAKER_FEE,
orderExpiryTimestamp: state.orderExpiryTimestamp,
orderMakerAddress: state.userAddress,
@@ -90,5 +76,6 @@ const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
dispatcher: new Dispatcher(dispatch),
});
-export const Portal: React.ComponentClass<PortalComponentPassedProps> =
- connect(mapStateToProps, mapDispatchToProps)(PortalComponent);
+export const Portal: React.ComponentClass<PortalComponentAllProps> = connect(mapStateToProps, mapDispatchToProps)(
+ PortalComponent,
+);
diff --git a/packages/website/ts/containers/smart_contracts_documentation.tsx b/packages/website/ts/containers/smart_contracts_documentation.tsx
index ea2b19b8c..8be33b546 100644
--- a/packages/website/ts/containers/smart_contracts_documentation.tsx
+++ b/packages/website/ts/containers/smart_contracts_documentation.tsx
@@ -1,52 +1,38 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {connect} from 'react-redux';
-import {Dispatch, Store as ReduxStore} from 'redux';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
-import {
- Documentation as DocumentationComponent,
- DocumentationAllProps,
-} 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 {doxityUtils} from 'ts/utils/doxity_utils';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
+import { Documentation as DocumentationComponent, DocumentationAllProps } from 'ts/pages/documentation/documentation';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { State } from 'ts/redux/reducer';
+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',
websitePath: WebsitePaths.SmartContracts,
docsJsonRoot: 'https://s3.amazonaws.com/smart-contracts-docs-json',
menu: {
- introduction: [
- sections.Introduction,
- ],
- contracts: [
- sections.Exchange,
- sections.TokenRegistry,
- sections.ZRXToken,
- sections.EtherToken,
- sections.TokenTransferProxy,
- ],
+ introduction: [Sections.Introduction],
+ contracts: [Sections.Exchange, Sections.TokenRegistry, Sections.ZRXToken, Sections.TokenTransferProxy],
},
sectionNameToMarkdown: {
- [sections.Introduction]: IntroMarkdown,
+ [Sections.Introduction]: IntroMarkdown,
+ },
+ sections: {
+ Introduction: Sections.Introduction,
+ Exchange: Sections.Exchange,
+ TokenTransferProxy: Sections.TokenTransferProxy,
+ TokenRegistry: Sections.TokenRegistry,
+ ZRXToken: Sections.ZRXToken,
},
- sections,
- visibleConstructors: [
- sections.Exchange,
- sections.TokenRegistry,
- sections.ZRXToken,
- sections.EtherToken,
- sections.TokenTransferProxy,
- ],
+ visibleConstructors: [Sections.Exchange, Sections.TokenRegistry, Sections.ZRXToken, Sections.TokenTransferProxy],
convertToDocAgnosticFormatFn: doxityUtils.convertToDocAgnosticFormat.bind(doxityUtils),
};
const docsInfo = new DocsInfo(docsInfoConfig);
@@ -71,5 +57,6 @@ const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
docsInfo,
});
-export const Documentation: React.ComponentClass<DocumentationAllProps> =
- connect(mapStateToProps, mapDispatchToProps)(DocumentationComponent);
+export const Documentation: React.ComponentClass<DocumentationAllProps> = connect(mapStateToProps, mapDispatchToProps)(
+ DocumentationComponent,
+);
diff --git a/packages/website/ts/containers/zero_ex_js_documentation.tsx b/packages/website/ts/containers/zero_ex_js_documentation.tsx
index 58c0ee186..8ae6a7b73 100644
--- a/packages/website/ts/containers/zero_ex_js_documentation.tsx
+++ b/packages/website/ts/containers/zero_ex_js_documentation.tsx
@@ -1,18 +1,14 @@
-import BigNumber from 'bignumber.js';
import * as _ from 'lodash';
import * as React from 'react';
-import {connect} from 'react-redux';
-import {Dispatch, Store as ReduxStore} from 'redux';
-import {Blockchain} from 'ts/blockchain';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
-import {
- Documentation as DocumentationComponent,
- DocumentationAllProps,
-} from 'ts/pages/documentation/documentation';
-import {Dispatcher} from 'ts/redux/dispatcher';
-import {State} from 'ts/redux/reducer';
-import {DocsInfoConfig, WebsitePaths} from 'ts/types';
-import {typeDocUtils} from 'ts/utils/typedoc_utils';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
+import { Documentation as DocumentationComponent, DocumentationAllProps } 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 { typeDocUtils } from 'ts/utils/typedoc_utils';
/* tslint:disable:no-var-requires */
const IntroMarkdown = require('md/docs/0xjs/introduction');
@@ -36,7 +32,7 @@ const zeroExJsDocSections = {
etherToken: 'etherToken',
proxy: 'proxy',
orderWatcher: 'orderWatcher',
- types: 'types',
+ types: constants.TYPES_SECTION_NAME,
};
const docsInfoConfig: DocsInfoConfig = {
@@ -46,20 +42,10 @@ const docsInfoConfig: DocsInfoConfig = {
websitePath: WebsitePaths.ZeroExJs,
docsJsonRoot: 'https://s3.amazonaws.com/0xjs-docs-jsons',
menu: {
- introduction: [
- zeroExJsDocSections.introduction,
- ],
- install: [
- zeroExJsDocSections.installation,
- ],
- topics: [
- zeroExJsDocSections.async,
- zeroExJsDocSections.errors,
- zeroExJsDocSections.versioning,
- ],
- zeroEx: [
- zeroExJsDocSections.zeroEx,
- ],
+ introduction: [zeroExJsDocSections.introduction],
+ install: [zeroExJsDocSections.installation],
+ topics: [zeroExJsDocSections.async, zeroExJsDocSections.errors, zeroExJsDocSections.versioning],
+ zeroEx: [zeroExJsDocSections.zeroEx],
contracts: [
zeroExJsDocSections.exchange,
zeroExJsDocSections.token,
@@ -67,12 +53,8 @@ const docsInfoConfig: DocsInfoConfig = {
zeroExJsDocSections.etherToken,
zeroExJsDocSections.proxy,
],
- orderWatcher: [
- zeroExJsDocSections.orderWatcher,
- ],
- types: [
- zeroExJsDocSections.types,
- ],
+ orderWatcher: [zeroExJsDocSections.orderWatcher],
+ types: [zeroExJsDocSections.types],
},
sectionNameToMarkdown: {
[zeroExJsDocSections.introduction]: IntroMarkdown,
@@ -97,6 +79,7 @@ const docsInfoConfig: DocsInfoConfig = {
'ExchangeEvents',
'IndexedFilterValues',
'SubscriptionOpts',
+ 'BlockRange',
'BlockParam',
'OrderFillOrKillRequest',
'OrderCancellationRequest',
@@ -109,6 +92,9 @@ const docsInfoConfig: DocsInfoConfig = {
'LogErrorContractEventArgs',
'LogFillContractEventArgs',
'LogCancelContractEventArgs',
+ 'EtherTokenContractEventArgs',
+ 'WithdrawalContractEventArgs',
+ 'DepositContractEventArgs',
'TokenEvents',
'ExchangeContractEventArgs',
'TransferContractEventArgs',
@@ -117,6 +103,8 @@ const docsInfoConfig: DocsInfoConfig = {
'ZeroExConfig',
'TransactionReceiptWithDecodedLogs',
'LogWithDecodedArgs',
+ 'EtherTokenEvents',
+ 'BlockParamLiteral',
'DecodedLogArgs',
'MethodOpts',
'ValidateOrderFillableOpts',
@@ -177,5 +165,6 @@ const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
dispatcher: new Dispatcher(dispatch),
});
-export const Documentation: React.ComponentClass<DocumentationAllProps> =
- connect(mapStateToProps, mapDispatchToProps)(DocumentationComponent);
+export const Documentation: React.ComponentClass<DocumentationAllProps> = connect(mapStateToProps, mapDispatchToProps)(
+ DocumentationComponent,
+);
diff --git a/packages/website/ts/globals.d.ts b/packages/website/ts/globals.d.ts
index b4611f583..383e5cbe0 100644
--- a/packages/website/ts/globals.d.ts
+++ b/packages/website/ts/globals.d.ts
@@ -55,11 +55,6 @@ interface System {
}
declare var System: System;
-// ethereum-address declarations
-declare module 'ethereum-address' {
- export const isAddress: (address: string) => boolean;
-}
-
// jsonschema declarations
// Source: https://github.com/tdegrunt/jsonschema/blob/master/lib/index.d.ts
declare interface Schema {
@@ -96,7 +91,7 @@ declare interface Schema {
dependencies?: {
[name: string]: Schema | string[];
};
- 'enum'?: any[];
+ enum?: any[];
type?: string | string[];
allOf?: Schema[];
anyOf?: Schema[];
@@ -135,23 +130,25 @@ declare module 'web3-provider-engine/subproviders/subprovider' {
declare module 'web3-provider-engine/subproviders/rpc' {
import * as Web3 from 'web3';
class RpcSubprovider {
- constructor(options: {rpcUrl: string});
+ constructor(options: { rpcUrl: string });
public handleRequest(
- payload: Web3.JSONRPCRequestPayload, next: () => void, end: (err: Error|null, data?: any) => void,
+ payload: Web3.JSONRPCRequestPayload,
+ next: () => void,
+ end: (err: Error | null, data?: any) => void,
): void;
}
export = RpcSubprovider;
}
declare module 'web3-provider-engine' {
- class Web3ProviderEngine {
- public on(event: string, handler: () => void): void;
- public send(payload: any): void;
- public sendAsync(payload: any, callback: (error: any, response: any) => void): void;
- public addProvider(provider: any): void;
- public start(): void;
- public stop(): void;
- }
- export = Web3ProviderEngine;
+ class Web3ProviderEngine {
+ public on(event: string, handler: () => void): void;
+ public send(payload: any): void;
+ public sendAsync(payload: any, callback: (error: any, response: any) => void): void;
+ public addProvider(provider: any): void;
+ public start(): void;
+ public stop(): void;
+ }
+ export = Web3ProviderEngine;
}
declare interface Artifact {
diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx
index 922102d96..ffb551561 100644
--- a/packages/website/ts/index.tsx
+++ b/packages/website/ts/index.tsx
@@ -1,97 +1,47 @@
// Polyfills
-import 'whatwg-fetch';
-
-import BigNumber from 'bignumber.js';
-import {colors, getMuiTheme, MuiThemeProvider} from 'material-ui/styles';
+import { MuiThemeProvider } from 'material-ui/styles';
import * as React from 'react';
-import {render} from 'react-dom';
-import {Provider} from 'react-redux';
-import {BrowserRouter as Router, Link, Redirect, Route, Switch} from 'react-router-dom';
+import { render } from 'react-dom';
+import { Provider } from 'react-redux';
+import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
import * as injectTapEventPlugin from 'react-tap-event-plugin';
-import {createStore, Store as ReduxStore} from 'redux';
-import {createLazyComponent} from 'ts/lazy_component';
-import {tradeHistoryStorage} from 'ts/local_storage/trade_history_storage';
-import {About} from 'ts/pages/about/about';
-import {FAQ} from 'ts/pages/faq/faq';
-import {Landing} from 'ts/pages/landing/landing';
-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 { createStore, Store as ReduxStore } from 'redux';
+import { createLazyComponent } from 'ts/lazy_component';
+import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
+import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage';
+import { About } from 'ts/pages/about/about';
+import { FAQ } from 'ts/pages/faq/faq';
+import { Landing } from 'ts/pages/landing/landing';
+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 { muiTheme } from 'ts/utils/mui_theme';
+import 'whatwg-fetch';
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,
-});
-
// Check if we've introduced an update that requires us to clear the tradeHistory local storage entries
tradeHistoryStorage.clearIfRequired();
-
-const CUSTOM_GREY = 'rgb(39, 39, 39)';
-const CUSTOM_GREEN = 'rgb(102, 222, 117)';
-const CUSTOM_DARKER_GREEN = 'rgb(77, 197, 92)';
+trackedTokenStorage.clearIfRequired();
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
// so each lazy import needs it's own `System.import()` declaration.
-const LazyPortal = createLazyComponent(
- 'Portal', async () => System.import<any>(/* webpackChunkName: "portal" */'ts/containers/portal'),
+const LazyPortal = createLazyComponent('Portal', async () =>
+ System.import<any>(/* webpackChunkName: "portal" */ 'ts/containers/portal'),
);
-const LazyZeroExJSDocumentation = createLazyComponent(
- 'Documentation',
- async () => System.import<any>(/* webpackChunkName: "zeroExDocs" */'ts/containers/zero_ex_js_documentation'),
+const LazyZeroExJSDocumentation = createLazyComponent('Documentation', async () =>
+ System.import<any>(/* webpackChunkName: "zeroExDocs" */ 'ts/containers/zero_ex_js_documentation'),
);
-const LazySmartContractsDocumentation = createLazyComponent(
- 'Documentation',
- async () => System.import<any>(
- /* webpackChunkName: "smartContractDocs" */'ts/containers/smart_contracts_documentation',
- ),
+const LazySmartContractsDocumentation = createLazyComponent('Documentation', async () =>
+ System.import<any>(/* webpackChunkName: "smartContractDocs" */ 'ts/containers/smart_contracts_documentation'),
);
-const LazyConnectDocumentation = createLazyComponent(
- 'Documentation',
- async () => System.import<any>(
- /* webpackChunkName: "connectDocs" */'ts/containers/connect_documentation',
- ),
+const LazyConnectDocumentation = createLazyComponent('Documentation', async () =>
+ System.import<any>(/* webpackChunkName: "connectDocs" */ 'ts/containers/connect_documentation'),
);
const store: ReduxStore<State> = createStore(reducer);
@@ -103,7 +53,7 @@ render(
<div>
<Switch>
<Route exact={true} path="/" component={Landing as any} />
- <Redirect from="/otc" to={`${WebsitePaths.Portal}`}/>
+ <Redirect from="/otc" to={`${WebsitePaths.Portal}`} />
<Route path={`${WebsitePaths.Portal}`} component={LazyPortal} />
<Route path={`${WebsitePaths.FAQ}`} component={FAQ as any} />
<Route path={`${WebsitePaths.About}`} component={About as any} />
@@ -120,6 +70,6 @@ render(
</Provider>
</MuiThemeProvider>
</div>
- </Router>,
+ </Router>,
document.getElementById('app'),
);
diff --git a/packages/website/ts/lazy_component.tsx b/packages/website/ts/lazy_component.tsx
index 359a1fe65..48800c2dd 100644
--- a/packages/website/ts/lazy_component.tsx
+++ b/packages/website/ts/lazy_component.tsx
@@ -23,20 +23,20 @@ export class LazyComponent extends React.Component<LazyComponentProps, LazyCompo
}
public componentWillMount() {
// tslint:disable-next-line:no-floating-promises
- this.loadComponentFireAndForgetAsync(this.props);
+ this._loadComponentFireAndForgetAsync(this.props);
}
public componentWillReceiveProps(nextProps: LazyComponentProps) {
if (nextProps.reactComponentPromise !== this.props.reactComponentPromise) {
// tslint:disable-next-line:no-floating-promises
- this.loadComponentFireAndForgetAsync(nextProps);
+ this._loadComponentFireAndForgetAsync(nextProps);
}
}
public render() {
- return _.isUndefined(this.state.component) ?
- null :
- React.createElement(this.state.component, this.props.reactComponentProps);
+ return _.isUndefined(this.state.component)
+ ? null
+ : React.createElement(this.state.component, this.props.reactComponentProps);
}
- private async loadComponentFireAndForgetAsync(props: LazyComponentProps) {
+ private async _loadComponentFireAndForgetAsync(props: LazyComponentProps) {
const component = await props.reactComponentPromise;
this.setState({
component,
@@ -61,11 +61,6 @@ export const createLazyComponent = (componentName: string, lazyImport: () => Pro
}
return component;
})();
- return (
- <LazyComponent
- reactComponentPromise={reactComponentPromise}
- reactComponentProps={props}
- />
- );
+ return <LazyComponent reactComponentPromise={reactComponentPromise} reactComponentProps={props} />;
};
};
diff --git a/packages/website/ts/local_storage/tracked_token_storage.ts b/packages/website/ts/local_storage/tracked_token_storage.ts
index 051a78ae1..7733e8436 100644
--- a/packages/website/ts/local_storage/tracked_token_storage.ts
+++ b/packages/website/ts/local_storage/tracked_token_storage.ts
@@ -1,26 +1,37 @@
import * as _ from 'lodash';
-import {localStorage} from 'ts/local_storage/local_storage';
-import {Token, TrackedTokensByNetworkId} from 'ts/types';
+import { localStorage } from 'ts/local_storage/local_storage';
+import { Token, TrackedTokensByUserAddress } from 'ts/types';
+import { configs } from 'ts/utils/configs';
const TRACKED_TOKENS_KEY = 'trackedTokens';
+const TRACKED_TOKENS_CLEAR_KEY = 'lastClearTrackedTokensDate';
export const trackedTokenStorage = {
- addTrackedTokenToUser(userAddress: string, networkId: number, token: Token) {
+ // Clear trackedTokens localStorage if we've updated the config variable in an update
+ // that introduced a backward incompatible change requiring the tracked tokens to be re-set
+ clearIfRequired(): void {
+ const lastClearFillDate = localStorage.getItemIfExists(TRACKED_TOKENS_CLEAR_KEY);
+ if (lastClearFillDate !== configs.LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE) {
+ localStorage.removeItem(TRACKED_TOKENS_KEY);
+ }
+ localStorage.setItem(TRACKED_TOKENS_CLEAR_KEY, configs.LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE);
+ },
+ addTrackedTokenToUser(userAddress: string, networkId: number, token: Token): void {
const trackedTokensByUserAddress = this.getTrackedTokensByUserAddress();
let trackedTokensByNetworkId = trackedTokensByUserAddress[userAddress];
if (_.isUndefined(trackedTokensByNetworkId)) {
trackedTokensByNetworkId = {};
}
- const trackedTokens = !_.isUndefined(trackedTokensByNetworkId[networkId]) ?
- trackedTokensByNetworkId[networkId] :
- [];
+ const trackedTokens = !_.isUndefined(trackedTokensByNetworkId[networkId])
+ ? trackedTokensByNetworkId[networkId]
+ : [];
trackedTokens.push(token);
trackedTokensByNetworkId[networkId] = trackedTokens;
trackedTokensByUserAddress[userAddress] = trackedTokensByNetworkId;
const trackedTokensByUserAddressJSONString = JSON.stringify(trackedTokensByUserAddress);
localStorage.setItem(TRACKED_TOKENS_KEY, trackedTokensByUserAddressJSONString);
},
- getTrackedTokensByUserAddress(): TrackedTokensByNetworkId {
+ getTrackedTokensByUserAddress(): TrackedTokensByUserAddress {
const trackedTokensJSONString = localStorage.getItemIfExists(TRACKED_TOKENS_KEY);
if (_.isEmpty(trackedTokensJSONString)) {
return {};
@@ -41,7 +52,7 @@ export const trackedTokenStorage = {
const trackedTokens = trackedTokensByNetworkId[networkId];
return trackedTokens;
},
- removeTrackedToken(userAddress: string, networkId: number, tokenAddress: string) {
+ removeTrackedToken(userAddress: string, networkId: number, tokenAddress: string): void {
const trackedTokensByUserAddress = this.getTrackedTokensByUserAddress();
const trackedTokensByNetworkId = trackedTokensByUserAddress[userAddress];
const trackedTokens = trackedTokensByNetworkId[networkId];
diff --git a/packages/website/ts/local_storage/trade_history_storage.tsx b/packages/website/ts/local_storage/trade_history_storage.tsx
index 0d627e000..df731236e 100644
--- a/packages/website/ts/local_storage/trade_history_storage.tsx
+++ b/packages/website/ts/local_storage/trade_history_storage.tsx
@@ -1,10 +1,10 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
-import {localStorage} from 'ts/local_storage/local_storage';
-import {Fill} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
+import { localStorage } from 'ts/local_storage/local_storage';
+import { Fill } from 'ts/types';
+import { configs } from 'ts/utils/configs';
+import { constants } from 'ts/utils/constants';
const FILLS_KEY = 'fills';
const FILLS_LATEST_BLOCK = 'fillsLatestBlock';
@@ -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);
@@ -50,7 +50,7 @@ export const tradeHistoryStorage = {
const userFillsKey = this._getUserFillsKey(userAddress, networkId);
localStorage.setItem(userFillsKey, userFillsJSONString);
},
- getUserFillsByHash(userAddress: string, networkId: number): {[fillHash: string]: Fill} {
+ getUserFillsByHash(userAddress: string, networkId: number): { [fillHash: string]: Fill } {
const userFillsKey = this._getUserFillsKey(userAddress, networkId);
const userFillsJSONString = localStorage.getItemIfExists(userFillsKey);
if (_.isEmpty(userFillsJSONString)) {
@@ -58,10 +58,10 @@ export const tradeHistoryStorage = {
}
const userFillsByHash = JSON.parse(userFillsJSONString);
_.each(userFillsByHash, (fill, hash) => {
- fill.paidMakerFee = new BigNumber(fill.paidMakerFee);
- fill.paidTakerFee = new BigNumber(fill.paidTakerFee);
- fill.filledTakerTokenAmount = new BigNumber(fill.filledTakerTokenAmount);
- fill.filledMakerTokenAmount = new BigNumber(fill.filledMakerTokenAmount);
+ fill.paidMakerFee = new BigNumber(fill.paidMakerFee);
+ fill.paidTakerFee = new BigNumber(fill.paidTakerFee);
+ fill.filledTakerTokenAmount = new BigNumber(fill.filledTakerTokenAmount);
+ fill.filledMakerTokenAmount = new BigNumber(fill.filledMakerTokenAmount);
});
return userFillsByHash;
},
diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx
index 3af05e8a4..c929673f5 100644
--- a/packages/website/ts/pages/about/about.tsx
+++ b/packages/website/ts/pages/about/about.tsx
@@ -1,21 +1,13 @@
import * as _ from 'lodash';
-import RaisedButton from 'material-ui/RaisedButton';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
-import {Link} from 'react-router-dom';
-import {Footer} from 'ts/components/footer';
-import {TopBar} from 'ts/components/top_bar';
-import {Profile} from 'ts/pages/about/profile';
-import {Question} from 'ts/pages/faq/question';
-import {ProfileInfo, Styles} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-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';
+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 teamRow1: ProfileInfo[] = [
{
@@ -48,6 +40,9 @@ const teamRow1: ProfileInfo[] = [
github: 'https://github.com/fabioberger',
medium: 'https://medium.com/@fabioberger',
},
+];
+
+const teamRow2: ProfileInfo[] = [
{
name: 'Alex Xu',
title: 'Director of Operations',
@@ -56,11 +51,8 @@ const teamRow1: ProfileInfo[] = [
image: '/images/team/alex.jpg',
linkedIn: 'https://www.linkedin.com/in/alex-xu/',
github: '',
- medium: '',
+ medium: 'https://medium.com/@aqxu',
},
-];
-
-const teamRow2: ProfileInfo[] = [
{
name: 'Leonid Logvinov',
title: 'Engineer',
@@ -69,7 +61,7 @@ const teamRow2: ProfileInfo[] = [
image: '/images/team/leonid.png',
linkedIn: 'https://www.linkedin.com/in/leonidlogvinov/',
github: 'https://github.com/LogvinovLeon',
- medium: '',
+ medium: 'https://medium.com/@Logvinov',
},
{
name: 'Ben Burns',
@@ -81,23 +73,36 @@ const teamRow2: ProfileInfo[] = [
github: '',
medium: '',
},
- {
- name: 'Philippe Castonguay',
- title: 'Dev Relations Manager',
- description: `Developer relations. Previously computational neuroscience \
- research at Janelia. Statistics at Western University. MA Dropout.`,
- image: '/images/team/philippe.png',
- linkedIn: '',
- github: 'https://github.com/PhABC',
- medium: '',
- },
+];
+
+const teamRow3: ProfileInfo[] = [
{
name: 'Brandon Millman',
title: 'Senior Engineer',
description: `Full-stack engineer. Previously senior software engineer at \
Twitter. Electrical and Computer Engineering at Duke.`,
image: '/images/team/brandon.png',
- linkedIn: 'https://www.linkedin.com/company-beta/17942619/',
+ linkedIn: 'https://www.linkedin.com/in/brandon-millman-b093a022/',
+ github: 'https://github.com/BMillman19',
+ medium: 'https://medium.com/@bchillman',
+ },
+ {
+ name: 'Tom Schmidt',
+ title: 'Product Manager',
+ description: `Previously engineering at Apple, product management at Facebook and Instagram. Computer Science at Stanford.`,
+ image: '/images/team/tom.jpg',
+ linkedIn: 'https://www.linkedin.com/in/tomhschmidt/',
+ github: 'https://github.com/tomhschmidt',
+ medium: '',
+ },
+ {
+ name: 'Jacob Evans',
+ title: 'Blockchain Engineer',
+ description: `Previously software engineer at Qantas and RSA Security.`,
+ image: '/images/team/jacob.jpg',
+ linkedIn: 'https://www.linkedin.com/in/dekzter/',
+ github: 'https://github.com/dekz',
+ medium: '',
},
];
@@ -149,6 +154,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> {
@@ -157,95 +168,79 @@ export class About extends React.Component<AboutProps, AboutState> {
}
public render() {
return (
- <div style={{backgroundColor: CUSTOM_BACKGROUND_COLOR}}>
- <DocumentTitle title="0x About Us"/>
+ <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"
- className="mx-auto max-width-4 py4"
- style={{color: colors.grey800}}
- >
- <div
- className="mx-auto pb4 sm-px3"
- style={{maxWidth: 435}}
- >
- <div
- style={styles.header}
- >
- About us:
- </div>
+ <div id="about" className="mx-auto max-width-4 py4" style={{ color: colors.grey800 }}>
+ <div className="mx-auto pb4 sm-px3" style={{ maxWidth: 435 }}>
+ <div style={styles.header}>About us:</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
- decentralized technology and its potential to act as an equalizing force
- in the world.
+ Our team is a diverse and globally distributed group with backgrounds in engineering,
+ research, business and design. We are passionate about decentralized technology and its
+ potential to act as an equalizing force in the world.
</div>
</div>
<div className="pt3 md-px4 lg-px0">
- <div className="clearfix pb3">
- {this.renderProfiles(teamRow1)}
- </div>
- <div className="clearfix">
- {this.renderProfiles(teamRow2)}
- </div>
+ <div className="clearfix pb3">{this._renderProfiles(teamRow1)}</div>
+ <div className="clearfix">{this._renderProfiles(teamRow2)}</div>
+ <div className="clearfix">{this._renderProfiles(teamRow3)}</div>
</div>
<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>
- <div className="clearfix">
- {this.renderProfiles(advisors)}
- </div>
+ <div className="clearfix">{this._renderProfiles(advisors)}</div>
</div>
- <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}}
- >
+ <div className="mx-auto py4 sm-px3" style={{ maxWidth: 308 }}>
+ <div className="pb2" 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}
- target="_blank"
- style={{color: 'black'}}
- >
+ <a href={constants.URL_ANGELLIST} target="_blank" style={{ color: 'black' }}>
join our team
</a>
. We value passion, diversity and unique perspectives.
</div>
</div>
</div>
- <Footer location={this.props.location} />
+ <Footer />
</div>
);
}
- private renderProfiles(profiles: ProfileInfo[]) {
+ private _renderProfiles(profiles: ProfileInfo[]) {
const numIndiv = profiles.length;
- const colSize = utils.getColSize(profiles.length);
+ const colSize = utils.getColSize(numIndiv);
return _.map(profiles, profile => {
return (
- <div
- key={`profile-${profile.name}`}
- >
- <Profile
- colSize={colSize}
- profileInfo={profile}
- />
+ <div key={`profile-${profile.name}`}>
+ <Profile colSize={colSize} profileInfo={profile} />
</div>
);
});
diff --git a/packages/website/ts/pages/about/profile.tsx b/packages/website/ts/pages/about/profile.tsx
index 71dbd09b5..18b4e0d5a 100644
--- a/packages/website/ts/pages/about/profile.tsx
+++ b/packages/website/ts/pages/about/profile.tsx
@@ -1,9 +1,7 @@
import * as _ from 'lodash';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {Element as ScrollElement} from 'react-scroll';
-import {ProfileInfo, Styles} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { ProfileInfo, Styles } from 'ts/types';
+import { colors } from 'ts/utils/colors';
const IMAGE_DIMENSION = 149;
const styles: Styles = {
@@ -26,43 +24,30 @@ interface ProfileProps {
export function Profile(props: ProfileProps) {
return (
- <div
- className={`lg-col md-col lg-col-${props.colSize} md-col-6`}
- >
- <div
- style={{maxWidth: 300}}
- className="mx-auto lg-px3 md-px3 sm-px4 sm-pb3"
- >
- <div
- className="circle overflow-hidden mx-auto"
- style={styles.imageContainer}
- >
- <img
- width={IMAGE_DIMENSION}
- src={props.profileInfo.image}
- />
+ <div className={`lg-col md-col lg-col-${props.colSize} md-col-6`}>
+ <div style={{ maxWidth: 300 }} className="mx-auto lg-px3 md-px3 sm-px4 sm-pb3">
+ <div className="circle overflow-hidden mx-auto" style={styles.imageContainer}>
+ <img width={IMAGE_DIMENSION} src={props.profileInfo.image} />
</div>
- <div
- className="center"
- style={{fontSize: 18, fontWeight: 'bold', paddingTop: 20}}
- >
+ <div className="center" style={{ fontSize: 18, fontWeight: 'bold', paddingTop: 20 }}>
{props.profileInfo.name}
</div>
- {!_.isUndefined(props.profileInfo.title) &&
+ {!_.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>
- }
- <div
- style={{minHeight: 60, lineHeight: 1.4}}
- className="pt1 pb2 mx-auto lg-h6 md-h6 sm-h5 sm-center"
- >
+ )}
+ <div style={{ minHeight: 60, lineHeight: 1.4 }} className="pt1 pb2 mx-auto lg-h6 md-h6 sm-h5 sm-center">
{props.profileInfo.description}
</div>
- <div className="flex pb3 mx-auto sm-hide xs-hide" style={{width: 180, opacity: 0.5}}>
+ <div className="flex pb3 mx-auto sm-hide xs-hide" style={{ width: 280, opacity: 0.5 }}>
{renderSocialMediaIcons(props.profileInfo)}
</div>
</div>
@@ -86,13 +71,8 @@ function renderSocialMediaIcon(iconName: string, url: string) {
return (
<div key={url} className="pr1">
- <a
- href={url}
- style={{color: 'inherit'}}
- target="_blank"
- className="text-decoration-none"
- >
- <i className={`zmdi ${iconName}`} style={{...styles.socalIcon}} />
+ <a href={url} style={{ color: 'inherit' }} target="_blank" className="text-decoration-none">
+ <i className={`zmdi ${iconName}`} style={{ ...styles.socalIcon }} />
</a>
</div>
);
diff --git a/packages/website/ts/pages/documentation/comment.tsx b/packages/website/ts/pages/documentation/comment.tsx
index 78bbdc069..23cfd96bd 100644
--- a/packages/website/ts/pages/documentation/comment.tsx
+++ b/packages/website/ts/pages/documentation/comment.tsx
@@ -1,7 +1,7 @@
import * as _ from 'lodash';
import * as React from 'react';
import * as ReactMarkdown from 'react-markdown';
-import {MarkdownCodeBlock} from 'ts/pages/shared/markdown_code_block';
+import { MarkdownCodeBlock } from 'ts/pages/shared/markdown_code_block';
interface CommentProps {
comment: string;
@@ -15,10 +15,9 @@ const defaultProps = {
export const Comment: React.SFC<CommentProps> = (props: CommentProps) => {
return (
<div className={`${props.className} comment`}>
- <ReactMarkdown
- source={props.comment}
- renderers={{CodeBlock: MarkdownCodeBlock}}
- />
+ <ReactMarkdown source={props.comment} renderers={{ CodeBlock: MarkdownCodeBlock }} />
</div>
);
};
+
+Comment.defaultProps = defaultProps;
diff --git a/packages/website/ts/pages/documentation/custom_enum.tsx b/packages/website/ts/pages/documentation/custom_enum.tsx
index 7dced9b60..8d50a2f52 100644
--- a/packages/website/ts/pages/documentation/custom_enum.tsx
+++ b/packages/website/ts/pages/documentation/custom_enum.tsx
@@ -1,7 +1,7 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {CustomType} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { CustomType } from 'ts/types';
+import { utils } from 'ts/utils/utils';
const STRING_ENUM_CODE_PREFIX = ' strEnum(';
@@ -23,8 +23,9 @@ export function CustomEnum(props: CustomEnumProps) {
return (
<span>
{`{`}
- {'\t'}{enumValues}
- <br />
+ {'\t'}
+ {enumValues}
+ <br />
{`}`}
</span>
);
diff --git a/packages/website/ts/pages/documentation/docs_info.ts b/packages/website/ts/pages/documentation/docs_info.ts
index 1afcf8aaf..4b1ec122a 100644
--- a/packages/website/ts/pages/documentation/docs_info.ts
+++ b/packages/website/ts/pages/documentation/docs_info.ts
@@ -18,8 +18,8 @@ export class DocsInfo {
public docsJsonRoot: string;
public menu: DocsMenu;
public sections: SectionsMap;
- public sectionNameToMarkdown: {[sectionName: string]: string};
- private docsInfo: DocsInfoConfig;
+ public sectionNameToMarkdown: { [sectionName: string]: string };
+ private _docsInfo: DocsInfoConfig;
constructor(config: DocsInfoConfig) {
this.displayName = config.displayName;
this.packageUrl = config.packageUrl;
@@ -28,35 +28,34 @@ export class DocsInfo {
this.docsJsonRoot = config.docsJsonRoot;
this.sections = config.sections;
this.sectionNameToMarkdown = config.sectionNameToMarkdown;
- this.docsInfo = config;
+ this._docsInfo = config;
}
public isPublicType(typeName: string): boolean {
- if (_.isUndefined(this.docsInfo.publicTypes)) {
+ if (_.isUndefined(this._docsInfo.publicTypes)) {
return false;
}
- const isPublic = _.includes(this.docsInfo.publicTypes, typeName);
+ const isPublic = _.includes(this._docsInfo.publicTypes, typeName);
return isPublic;
}
public getModulePathsIfExists(sectionName: string): string[] {
- const modulePathsIfExists = this.docsInfo.sectionNameToModulePath[sectionName];
+ const modulePathsIfExists = this._docsInfo.sectionNameToModulePath[sectionName];
return modulePathsIfExists;
}
- public getMenu(selectedVersion?: string): {[section: string]: string[]} {
- if (_.isUndefined(selectedVersion) || _.isUndefined(this.docsInfo.menuSubsectionToVersionWhenIntroduced)) {
- return this.docsInfo.menu;
+ public getMenu(selectedVersion?: string): { [section: string]: string[] } {
+ if (_.isUndefined(selectedVersion) || _.isUndefined(this._docsInfo.menuSubsectionToVersionWhenIntroduced)) {
+ return this._docsInfo.menu;
}
- const finalMenu = _.cloneDeep(this.docsInfo.menu);
+ const finalMenu = _.cloneDeep(this._docsInfo.menu);
if (_.isUndefined(finalMenu.contracts)) {
return finalMenu;
}
// TODO: refactor to include more sections then simply the `contracts` section
finalMenu.contracts = _.filter(finalMenu.contracts, (contractName: string) => {
- const versionIntroducedIfExists = this.docsInfo.menuSubsectionToVersionWhenIntroduced[contractName];
+ const versionIntroducedIfExists = this._docsInfo.menuSubsectionToVersionWhenIntroduced[contractName];
if (!_.isUndefined(versionIntroducedIfExists)) {
- const existsInSelectedVersion = compareVersions(selectedVersion,
- versionIntroducedIfExists) >= 0;
+ const existsInSelectedVersion = compareVersions(selectedVersion, versionIntroducedIfExists) >= 0;
return existsInSelectedVersion;
} else {
return true;
@@ -104,9 +103,9 @@ export class DocsInfo {
return typeDefinitionByName;
}
public isVisibleConstructor(sectionName: string): boolean {
- return _.includes(this.docsInfo.visibleConstructors, sectionName);
+ return _.includes(this._docsInfo.visibleConstructors, sectionName);
}
- public convertToDocAgnosticFormat(docObj: DoxityDocObj|TypeDocNode): DocAgnosticFormat {
- return this.docsInfo.convertToDocAgnosticFormatFn(docObj, this);
+ public convertToDocAgnosticFormat(docObj: DoxityDocObj | TypeDocNode): DocAgnosticFormat {
+ return this._docsInfo.convertToDocAgnosticFormatFn(docObj, this);
}
}
diff --git a/packages/website/ts/pages/documentation/documentation.tsx b/packages/website/ts/pages/documentation/documentation.tsx
index be99e77a2..2315847ad 100644
--- a/packages/website/ts/pages/documentation/documentation.tsx
+++ b/packages/website/ts/pages/documentation/documentation.tsx
@@ -1,60 +1,48 @@
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 {
- scroller,
-} from 'react-scroll';
+import { scroller } from 'react-scroll';
import semverSort = require('semver-sort');
-import {TopBar} from 'ts/components/top_bar';
-import {Badge} from 'ts/components/ui/badge';
-import {Comment} from 'ts/pages/documentation/comment';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
-import {EventDefinition} from 'ts/pages/documentation/event_definition';
-import {MethodBlock} from 'ts/pages/documentation/method_block';
-import {SourceLink} from 'ts/pages/documentation/source_link';
-import {Type} from 'ts/pages/documentation/type';
-import {TypeDefinition} from 'ts/pages/documentation/type_definition';
-import {AnchorTitle} from 'ts/pages/shared/anchor_title';
-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 {Dispatcher} from 'ts/redux/dispatcher';
+import { TopBar } from 'ts/components/top_bar';
+import { Badge } from 'ts/components/ui/badge';
+import { Comment } from 'ts/pages/documentation/comment';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
+import { EventDefinition } from 'ts/pages/documentation/event_definition';
+import { MethodBlock } from 'ts/pages/documentation/method_block';
+import { SourceLink } from 'ts/pages/documentation/source_link';
+import { Type } from 'ts/pages/documentation/type';
+import { TypeDefinition } from 'ts/pages/documentation/type_definition';
+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 { Dispatcher } from 'ts/redux/dispatcher';
import {
AddressByContractName,
- CustomType,
DocAgnosticFormat,
- Docs,
- DocsInfoConfig,
DoxityDocObj,
EtherscanLinkSuffixes,
Event,
- MenuSubsectionsBySection,
Networks,
Property,
SolidityMethod,
Styles,
TypeDefinitionByName,
- TypeDocNode,
TypescriptMethod,
- WebsitePaths,
} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {docUtils} from 'ts/utils/doc_utils';
-import {utils} from 'ts/utils/utils';
+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_TO_TIMEOUT = 500;
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,
+const networkNameToColor: { [network: string]: string } = {
+ [Networks.kovan]: colors.purple,
+ [Networks.ropsten]: colors.red,
+ [Networks.mainnet]: colors.turquois,
};
export interface DocumentationAllProps {
@@ -73,13 +61,13 @@ interface DocumentationState {
const styles: Styles = {
mainContainers: {
position: 'absolute',
- top: 60,
+ top: 1,
left: 0,
bottom: 0,
right: 0,
overflowZ: 'hidden',
overflowY: 'scroll',
- minHeight: 'calc(100vh - 60px)',
+ minHeight: 'calc(100vh - 1px)',
WebkitOverflowScrolling: 'touch',
},
menuContainer: {
@@ -89,8 +77,7 @@ const styles: Styles = {
},
};
-export class Documentation extends
- React.Component<DocumentationAllProps, DocumentationState> {
+export class Documentation extends React.Component<DocumentationAllProps, DocumentationState> {
constructor(props: DocumentationAllProps) {
super(props);
this.state = {
@@ -103,15 +90,15 @@ export class Documentation extends
const versions = findVersions(lastSegment);
const preferredVersionIfExists = versions.length > 0 ? versions[0] : undefined;
// tslint:disable-next-line:no-floating-promises
- this.fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists);
+ this._fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists);
}
public render() {
- const menuSubsectionsBySection = _.isUndefined(this.state.docAgnosticFormat) ?
- {} :
- this.props.docsInfo.getMenuSubsectionsBySection(this.state.docAgnosticFormat);
+ const menuSubsectionsBySection = _.isUndefined(this.state.docAgnosticFormat)
+ ? {}
+ : this.props.docsInfo.getMenuSubsectionsBySection(this.state.docAgnosticFormat);
return (
<div>
- <DocumentTitle title={`${this.props.docsInfo.displayName} Documentation`}/>
+ <DocumentTitle title={`${this.props.docsInfo.displayName} Documentation`} />
<TopBar
blockchainIsLoaded={false}
location={this.props.location}
@@ -122,29 +109,26 @@ export class Documentation extends
shouldFullWidth={true}
docsInfo={this.props.docsInfo}
/>
- {_.isUndefined(this.state.docAgnosticFormat) ?
- <div
- className="col col-12"
- style={styles.mainContainers}
- >
+ {_.isUndefined(this.state.docAgnosticFormat) ? (
+ <div className="col col-12" style={styles.mainContainers}>
<div
className="relative sm-px2 sm-pt2 sm-m1"
- style={{height: 122, top: '50%', transform: 'translateY(-50%)'}}
+ style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
>
<div className="center pb2">
<CircularProgress size={40} thickness={5} />
</div>
- <div className="center pt2" style={{paddingBottom: 11}}>Loading documentation...</div>
+ <div className="center pt2" style={{ paddingBottom: 11 }}>
+ Loading documentation...
+ </div>
</div>
- </div> :
- <div
- className="mx-auto flex"
- style={{color: colors.grey800, height: 43}}
- >
+ </div>
+ ) : (
+ <div className="mx-auto flex" style={{ color: colors.grey800, height: 43 }}>
<div className="relative col md-col-3 lg-col-3 lg-pl0 md-pl1 sm-hide xs-hide">
<div
className="border-right absolute"
- style={{...styles.menuContainer, ...styles.mainContainers}}
+ style={{ ...styles.menuContainer, ...styles.mainContainers }}
>
<NestedSidebarMenu
selectedVersion={this.props.docsVersion}
@@ -156,35 +140,31 @@ export class Documentation extends
</div>
</div>
<div className="relative col lg-col-9 md-col-9 sm-col-12 col-12">
- <div
- id="documentation"
- style={styles.mainContainers}
- className="absolute"
- >
+ <div id="documentation" style={styles.mainContainers} className="absolute">
<div id={SCROLL_TOP_ID} />
<h1 className="md-pl2 sm-pl3">
<a href={this.props.docsInfo.packageUrl} target="_blank">
{this.props.docsInfo.displayName}
</a>
</h1>
- {this.renderDocumentation()}
+ {this._renderDocumentation()}
</div>
</div>
</div>
- }
+ )}
</div>
);
}
- private renderDocumentation(): React.ReactNode {
+ private _renderDocumentation(): React.ReactNode {
const subMenus = _.values(this.props.docsInfo.getMenu());
const orderedSectionNames = _.flatten(subMenus);
const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.state.docAgnosticFormat);
- const renderedSections = _.map(orderedSectionNames, this.renderSection.bind(this, typeDefinitionByName));
+ const renderedSections = _.map(orderedSectionNames, this._renderSection.bind(this, typeDefinitionByName));
return renderedSections;
}
- private renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode {
+ private _renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode {
const markdownFileIfExists = this.props.docsInfo.sectionNameToMarkdown[sectionName];
if (!_.isUndefined(markdownFileIfExists)) {
return (
@@ -205,6 +185,7 @@ export class Documentation extends
const typeDefs = _.map(sortedTypes, customType => {
return (
<TypeDefinition
+ sectionName={sectionName}
key={`type-${customType.name}`}
customType={customType}
docsInfo={this.props.docsInfo}
@@ -213,12 +194,12 @@ export class Documentation extends
});
const sortedProperties = _.sortBy(docSection.properties, 'name');
- const propertyDefs = _.map(sortedProperties, this.renderProperty.bind(this));
+ const propertyDefs = _.map(sortedProperties, this._renderProperty.bind(this, sectionName));
const sortedMethods = _.sortBy(docSection.methods, 'name');
const methodDefs = _.map(sortedMethods, method => {
const isConstructor = false;
- return this.renderMethodBlocks(method, sectionName, isConstructor, typeDefinitionByName);
+ return this._renderMethodBlocks(method, sectionName, isConstructor, typeDefinitionByName);
});
const sortedEvents = _.sortBy(docSection.events, 'name');
@@ -227,148 +208,143 @@ export class Documentation extends
<EventDefinition
key={`event-${event.name}-${i}`}
event={event}
+ sectionName={sectionName}
docsInfo={this.props.docsInfo}
/>
);
});
return (
- <div
- key={`section-${sectionName}`}
- className="py2 pr3 md-pl2 sm-pl3"
- >
+ <div key={`section-${sectionName}`} className="py2 pr3 md-pl2 sm-pl3">
<div className="flex">
- <div style={{marginRight: 7}}>
- <SectionHeader sectionName={sectionName} />
- </div>
- {this.renderNetworkBadgesIfExists(sectionName)}
+ <div style={{ marginRight: 7 }}>
+ <SectionHeader sectionName={sectionName} />
+ </div>
+ {this._renderNetworkBadgesIfExists(sectionName)}
</div>
- {docSection.comment &&
- <Comment
- comment={docSection.comment}
- />
- }
+ {docSection.comment && <Comment comment={docSection.comment} />}
{docSection.constructors.length > 0 &&
- this.props.docsInfo.isVisibleConstructor(sectionName) &&
- <div>
- <h2 className="thin">Constructor</h2>
- {this.renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)}
- </div>
- }
- {docSection.properties.length > 0 &&
+ this.props.docsInfo.isVisibleConstructor(sectionName) && (
+ <div>
+ <h2 className="thin">Constructor</h2>
+ {this._renderConstructors(docSection.constructors, sectionName, typeDefinitionByName)}
+ </div>
+ )}
+ {docSection.properties.length > 0 && (
<div>
<h2 className="thin">Properties</h2>
<div>{propertyDefs}</div>
</div>
- }
- {docSection.methods.length > 0 &&
+ )}
+ {docSection.methods.length > 0 && (
<div>
<h2 className="thin">Methods</h2>
<div>{methodDefs}</div>
</div>
- }
- {!_.isUndefined(docSection.events) && docSection.events.length > 0 &&
- <div>
- <h2 className="thin">Events</h2>
- <div>{eventDefs}</div>
- </div>
- }
- {!_.isUndefined(typeDefs) && typeDefs.length > 0 &&
- <div>
- <div>{typeDefs}</div>
- </div>
- }
+ )}
+ {!_.isUndefined(docSection.events) &&
+ docSection.events.length > 0 && (
+ <div>
+ <h2 className="thin">Events</h2>
+ <div>{eventDefs}</div>
+ </div>
+ )}
+ {!_.isUndefined(typeDefs) &&
+ typeDefs.length > 0 && (
+ <div>
+ <div>{typeDefs}</div>
+ </div>
+ )}
</div>
);
}
- private renderNetworkBadgesIfExists(sectionName: string) {
- const networkToAddressByContractName = constants.contractAddresses[this.props.docsVersion];
- const badges = _.map(networkToAddressByContractName,
+ private _renderNetworkBadgesIfExists(sectionName: string) {
+ const networkToAddressByContractName = configs.CONTRACT_ADDRESS[this.props.docsVersion];
+ const badges = _.map(
+ networkToAddressByContractName,
(addressByContractName: AddressByContractName, networkName: string) => {
const contractAddress = addressByContractName[sectionName];
if (_.isUndefined(contractAddress)) {
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}
- backgroundColor={networkNameToColor[networkName]}
- />
+ <Badge title={networkName} backgroundColor={networkNameToColor[networkName]} />
</a>
);
- });
+ },
+ );
return badges;
}
- private renderConstructors(constructors: SolidityMethod[]|TypescriptMethod[],
- sectionName: string,
- typeDefinitionByName: TypeDefinitionByName): React.ReactNode {
+ private _renderConstructors(
+ constructors: SolidityMethod[] | TypescriptMethod[],
+ sectionName: string,
+ typeDefinitionByName: TypeDefinitionByName,
+ ): React.ReactNode {
const constructorDefs = _.map(constructors, constructor => {
- return this.renderMethodBlocks(
- constructor, sectionName, constructor.isConstructor, typeDefinitionByName,
- );
+ return this._renderMethodBlocks(constructor, sectionName, constructor.isConstructor, typeDefinitionByName);
});
- return (
- <div>
- {constructorDefs}
- </div>
- );
+ return <div>{constructorDefs}</div>;
}
- private renderProperty(property: Property): React.ReactNode {
+ private _renderProperty(sectionName: string, property: Property): React.ReactNode {
return (
- <div
- key={`property-${property.name}-${property.type.name}`}
- className="pb3"
- >
+ <div key={`property-${property.name}-${property.type.name}`} className="pb3">
<code className="hljs">
- {property.name}: <Type type={property.type} docsInfo={this.props.docsInfo} />
+ {property.name}:
+ <Type type={property.type} sectionName={sectionName} docsInfo={this.props.docsInfo} />
</code>
- {property.source &&
+ {property.source && (
<SourceLink
version={this.props.docsVersion}
source={property.source}
baseUrl={this.props.docsInfo.packageUrl}
subPackageName={this.props.docsInfo.subPackageName}
/>
- }
- {property.comment &&
- <Comment
- comment={property.comment}
- className="py2"
- />
- }
+ )}
+ {property.comment && <Comment comment={property.comment} className="py2" />}
</div>
);
}
- private renderMethodBlocks(method: SolidityMethod|TypescriptMethod, sectionName: string,
- isConstructor: boolean, typeDefinitionByName: TypeDefinitionByName): React.ReactNode {
+ private _renderMethodBlocks(
+ method: SolidityMethod | TypescriptMethod,
+ sectionName: string,
+ isConstructor: boolean,
+ typeDefinitionByName: TypeDefinitionByName,
+ ): React.ReactNode {
return (
<MethodBlock
- key={`method-${method.name}-${sectionName}`}
- method={method}
- typeDefinitionByName={typeDefinitionByName}
- libraryVersion={this.props.docsVersion}
- docsInfo={this.props.docsInfo}
+ key={`method-${method.name}-${sectionName}`}
+ sectionName={sectionName}
+ method={method}
+ typeDefinitionByName={typeDefinitionByName}
+ libraryVersion={this.props.docsVersion}
+ docsInfo={this.props.docsInfo}
/>
);
}
- private scrollToHash(): void {
+ private _scrollToHash(): void {
const hashWithPrefix = this.props.location.hash;
let hash = hashWithPrefix.slice(1);
if (_.isEmpty(hash)) {
hash = SCROLL_TOP_ID; // scroll to the top
}
- scroller.scrollTo(hash, {duration: 0, offset: 0, containerId: 'documentation'});
+ scroller.scrollTo(hash, {
+ duration: 0,
+ offset: 0,
+ containerId: 'documentation',
+ });
}
- private async fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> {
+ private async _fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> {
const versionToFileName = await docUtils.getVersionToFileNameAsync(this.props.docsInfo.docsJsonRoot);
const versions = _.keys(versionToFileName);
this.props.dispatcher.updateAvailableDocVersions(versions);
@@ -386,14 +362,18 @@ export class Documentation extends
const versionFileNameToFetch = versionToFileName[versionToFetch];
const versionDocObj = await docUtils.getJSONDocFileAsync(
- versionFileNameToFetch, this.props.docsInfo.docsJsonRoot,
+ versionFileNameToFetch,
+ this.props.docsInfo.docsJsonRoot,
);
const docAgnosticFormat = this.props.docsInfo.convertToDocAgnosticFormat(versionDocObj as DoxityDocObj);
- this.setState({
- docAgnosticFormat,
- }, () => {
- this.scrollToHash();
- });
+ this.setState(
+ {
+ docAgnosticFormat,
+ },
+ () => {
+ this._scrollToHash();
+ },
+ );
}
}
diff --git a/packages/website/ts/pages/documentation/enum.tsx b/packages/website/ts/pages/documentation/enum.tsx
index 8fcd2c252..7dfdee771 100644
--- a/packages/website/ts/pages/documentation/enum.tsx
+++ b/packages/website/ts/pages/documentation/enum.tsx
@@ -1,9 +1,6 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {EnumValue, TypeDocNode} from 'ts/types';
-import {utils} from 'ts/utils/utils';
-
-const STRING_ENUM_CODE_PREFIX = ' strEnum(';
+import { EnumValue } from 'ts/types';
interface EnumProps {
values: EnumValue[];
@@ -11,15 +8,14 @@ interface EnumProps {
export function Enum(props: EnumProps) {
const values = _.map(props.values, (value, i) => {
- const isLast = i === props.values.length - 1;
const defaultValueIfAny = !_.isUndefined(value.defaultValue) ? ` = ${value.defaultValue}` : '';
return `\n\t${value.name}${defaultValueIfAny},`;
});
return (
<span>
{`{`}
- {values}
- <br />
+ {values}
+ <br />
{`}`}
</span>
);
diff --git a/packages/website/ts/pages/documentation/event_definition.tsx b/packages/website/ts/pages/documentation/event_definition.tsx
index 469e6bb37..0e53e38e7 100644
--- a/packages/website/ts/pages/documentation/event_definition.tsx
+++ b/packages/website/ts/pages/documentation/event_definition.tsx
@@ -1,17 +1,14 @@
import * as _ from 'lodash';
import * as React from 'react';
-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';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
-
-const KEYWORD_COLOR = '#a81ca6';
-const CUSTOM_GREEN = 'rgb(77, 162, 75)';
+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';
+import { colors } from 'ts/utils/colors';
interface EventDefinitionProps {
event: Event;
+ sectionName: string;
docsInfo: DocsInfo;
}
@@ -30,11 +27,11 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event
const event = this.props.event;
return (
<div
- id={event.name}
+ id={`${this.props.sectionName}-${event.name}`}
className="pb2"
- style={{overflow: 'hidden', width: '100%'}}
- onMouseOver={this.setAnchorVisibility.bind(this, true)}
- onMouseOut={this.setAnchorVisibility.bind(this, false)}
+ style={{ overflow: 'hidden', width: '100%' }}
+ onMouseOver={this._setAnchorVisibility.bind(this, true)}
+ onMouseOut={this._setAnchorVisibility.bind(this, false)}
>
<AnchorTitle
headerSize={HeaderSizes.H3}
@@ -42,28 +39,24 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event
id={event.name}
shouldShowAnchor={this.state.shouldShowAnchor}
/>
- <div style={{fontSize: 16}}>
+ <div style={{ fontSize: 16 }}>
<pre>
- <code className="hljs">
- {this.renderEventCode()}
- </code>
+ <code className="hljs">{this._renderEventCode()}</code>
</pre>
</div>
</div>
);
}
- private renderEventCode() {
- const indexed = <span style={{color: CUSTOM_GREEN}}> indexed</span>;
+ private _renderEventCode() {
+ const indexed = <span style={{ color: colors.green }}> indexed</span>;
const eventArgs = _.map(this.props.event.eventArgs, (eventArg: EventArg) => {
const type = (
- <Type
- type={eventArg.type}
- docsInfo={this.props.docsInfo}
- />
+ <Type type={eventArg.type} sectionName={this.props.sectionName} docsInfo={this.props.docsInfo} />
);
return (
<span key={`eventArg-${eventArg.name}`}>
- {eventArg.name}{eventArg.isIndexed ? indexed : ''}: {type},
+ {eventArg.name}
+ {eventArg.isIndexed ? indexed : ''}: {type},
</span>
);
});
@@ -73,14 +66,15 @@ export class EventDefinition extends React.Component<EventDefinitionProps, Event
return (
<span>
{`{`}
- <br />
- {'\t'}{argList}
- <br />
+ <br />
+ {'\t'}
+ {argList}
+ <br />
{`}`}
</span>
);
}
- private setAnchorVisibility(shouldShowAnchor: boolean) {
+ private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({
shouldShowAnchor,
});
diff --git a/packages/website/ts/pages/documentation/interface.tsx b/packages/website/ts/pages/documentation/interface.tsx
index e671db2b8..16a772125 100644
--- a/packages/website/ts/pages/documentation/interface.tsx
+++ b/packages/website/ts/pages/documentation/interface.tsx
@@ -1,12 +1,13 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
-import {MethodSignature} from 'ts/pages/documentation/method_signature';
-import {Type} from 'ts/pages/documentation/type';
-import {CustomType, TypeDocTypes} from 'ts/types';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
+import { MethodSignature } from 'ts/pages/documentation/method_signature';
+import { Type } from 'ts/pages/documentation/type';
+import { CustomType, TypeDocTypes } from 'ts/types';
interface InterfaceProps {
type: CustomType;
+ sectionName: string;
docsInfo: DocsInfo;
}
@@ -16,15 +17,17 @@ export function Interface(props: InterfaceProps) {
return (
<span key={`property-${property.name}-${property.type}-${type.name}`}>
{property.name}:{' '}
- {property.type.typeDocType !== TypeDocTypes.Reflection ?
- <Type type={property.type} docsInfo={props.docsInfo} /> :
+ {property.type.typeDocType !== TypeDocTypes.Reflection ? (
+ <Type type={property.type} sectionName={props.sectionName} docsInfo={props.docsInfo} />
+ ) : (
<MethodSignature
method={property.type.method}
+ sectionName={props.sectionName}
shouldHideMethodName={true}
shouldUseArrowSyntax={true}
docsInfo={props.docsInfo}
/>
- },
+ )},
</span>
);
});
@@ -33,14 +36,14 @@ export function Interface(props: InterfaceProps) {
const is = type.indexSignature;
const param = (
<span key={`indexSigParams-${is.keyName}-${is.keyType}-${type.name}`}>
- {is.keyName}: <Type type={is.keyType} docsInfo={props.docsInfo} />
+ {is.keyName}: <Type type={is.keyType} sectionName={props.sectionName} docsInfo={props.docsInfo} />
</span>
);
- properties.push((
+ properties.push(
<span key={`indexSignature-${type.name}-${is.keyType.name}`}>
[{param}]: {is.valueName},
- </span>
- ));
+ </span>,
+ );
}
const propertyList = _.reduce(properties, (prev: React.ReactNode, curr: React.ReactNode) => {
return [prev, '\n\t', curr];
@@ -48,9 +51,10 @@ export function Interface(props: InterfaceProps) {
return (
<span>
{`{`}
- <br />
- {'\t'}{propertyList}
- <br />
+ <br />
+ {'\t'}
+ {propertyList}
+ <br />
{`}`}
</span>
);
diff --git a/packages/website/ts/pages/documentation/method_block.tsx b/packages/website/ts/pages/documentation/method_block.tsx
index 44e549211..dfde5931b 100644
--- a/packages/website/ts/pages/documentation/method_block.tsx
+++ b/packages/website/ts/pages/documentation/method_block.tsx
@@ -1,27 +1,17 @@
import * as _ from 'lodash';
-import {Chip} from 'material-ui/Chip';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import * as ReactMarkdown from 'react-markdown';
-import {Comment} from 'ts/pages/documentation/comment';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
-import {MethodSignature} from 'ts/pages/documentation/method_signature';
-import {SourceLink} from 'ts/pages/documentation/source_link';
-import {AnchorTitle} from 'ts/pages/shared/anchor_title';
-import {
- HeaderSizes,
- Parameter,
- SolidityMethod,
- Styles,
- TypeDefinitionByName,
- TypeDocNode,
- TypescriptMethod,
-} from 'ts/types';
-import {typeDocUtils} from 'ts/utils/typedoc_utils';
-import {utils} from 'ts/utils/utils';
+import { Comment } from 'ts/pages/documentation/comment';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
+import { MethodSignature } from 'ts/pages/documentation/method_signature';
+import { SourceLink } from 'ts/pages/documentation/source_link';
+import { AnchorTitle } from 'ts/pages/shared/anchor_title';
+import { HeaderSizes, Parameter, SolidityMethod, Styles, TypeDefinitionByName, TypescriptMethod } from 'ts/types';
+import { colors } from 'ts/utils/colors';
+import { typeDocUtils } from 'ts/utils/typedoc_utils';
interface MethodBlockProps {
- method: SolidityMethod|TypescriptMethod;
+ method: SolidityMethod | TypescriptMethod;
+ sectionName: string;
libraryVersion: string;
typeDefinitionByName: TypeDefinitionByName;
docsInfo: DocsInfo;
@@ -35,7 +25,7 @@ const styles: Styles = {
chip: {
fontSize: 13,
backgroundColor: colors.lightBlueA700,
- color: 'white',
+ color: colors.white,
height: 11,
borderRadius: 14,
marginTop: 19,
@@ -58,119 +48,93 @@ export class MethodBlock extends React.Component<MethodBlockProps, MethodBlockSt
return (
<div
- id={method.name}
- style={{overflow: 'hidden', width: '100%'}}
+ id={`${this.props.sectionName}-${method.name}`}
+ style={{ overflow: 'hidden', width: '100%' }}
className="pb4"
- onMouseOver={this.setAnchorVisibility.bind(this, true)}
- onMouseOut={this.setAnchorVisibility.bind(this, false)}
+ onMouseOver={this._setAnchorVisibility.bind(this, true)}
+ onMouseOut={this._setAnchorVisibility.bind(this, false)}
>
- {!method.isConstructor &&
+ {!method.isConstructor && (
<div className="flex">
- {(method as TypescriptMethod).isStatic &&
- this.renderChip('Static')
- }
- {(method as SolidityMethod).isConstant &&
- this.renderChip('Constant')
- }
- {(method as SolidityMethod).isPayable &&
- this.renderChip('Payable')
- }
+ {(method as TypescriptMethod).isStatic && this._renderChip('Static')}
+ {(method as SolidityMethod).isConstant && this._renderChip('Constant')}
+ {(method as SolidityMethod).isPayable && this._renderChip('Payable')}
<AnchorTitle
headerSize={HeaderSizes.H3}
title={method.name}
- id={method.name}
+ id={`${this.props.sectionName}-${method.name}`}
shouldShowAnchor={this.state.shouldShowAnchor}
/>
</div>
- }
+ )}
<code className="hljs">
<MethodSignature
method={method}
+ sectionName={this.props.sectionName}
typeDefinitionByName={this.props.typeDefinitionByName}
docsInfo={this.props.docsInfo}
/>
</code>
- {(method as TypescriptMethod).source &&
+ {(method as TypescriptMethod).source && (
<SourceLink
version={this.props.libraryVersion}
source={(method as TypescriptMethod).source}
baseUrl={this.props.docsInfo.packageUrl}
subPackageName={this.props.docsInfo.subPackageName}
/>
- }
- {method.comment &&
- <Comment
- comment={method.comment}
- className="py2"
- />
- }
- {method.parameters && !_.isEmpty(method.parameters) &&
- <div>
- <h4
- className="pb1 thin"
- style={{borderBottom: '1px solid #e1e8ed'}}
- >
- ARGUMENTS
- </h4>
- {this.renderParameterDescriptions(method.parameters)}
- </div>
- }
- {method.returnComment &&
+ )}
+ {method.comment && <Comment comment={method.comment} className="py2" />}
+ {method.parameters &&
+ !_.isEmpty(method.parameters) && (
+ <div>
+ <h4 className="pb1 thin" style={{ borderBottom: '1px solid #e1e8ed' }}>
+ ARGUMENTS
+ </h4>
+ {this._renderParameterDescriptions(method.parameters)}
+ </div>
+ )}
+ {method.returnComment && (
<div className="pt1 comment">
- <h4
- className="pb1 thin"
- style={{borderBottom: '1px solid #e1e8ed'}}
- >
+ <h4 className="pb1 thin" style={{ borderBottom: '1px solid #e1e8ed' }}>
RETURNS
</h4>
- <Comment
- comment={method.returnComment}
- />
+ <Comment comment={method.returnComment} />
</div>
- }
+ )}
</div>
);
}
- private renderChip(text: string) {
+ private _renderChip(text: string) {
return (
- <div
- className="p1 mr1"
- style={styles.chip}
- >
+ <div className="p1 mr1" style={styles.chip}>
{text}
</div>
);
}
- private renderParameterDescriptions(parameters: Parameter[]) {
+ private _renderParameterDescriptions(parameters: Parameter[]) {
const descriptions = _.map(parameters, parameter => {
const isOptional = parameter.isOptional;
return (
<div
key={`param-description-${parameter.name}`}
className="flex pb1 mb2"
- style={{borderBottom: '1px solid #f0f4f7'}}
+ style={{ borderBottom: '1px solid #f0f4f7' }}
>
<div className="pl2 col lg-col-4 md-col-4 sm-col-12 col-12">
- <div className="bold">
- {parameter.name}
- </div>
- <div className="pt1" style={{color: colors.grey500, fontSize: 14}}>
+ <div className="bold">{parameter.name}</div>
+ <div className="pt1" style={{ color: colors.grey, fontSize: 14 }}>
{isOptional && 'optional'}
</div>
</div>
<div className="col lg-col-8 md-col-8 sm-col-12 col-12">
- {parameter.comment &&
- <Comment
- comment={parameter.comment}
- />
- }
+ {parameter.comment && <Comment comment={parameter.comment} />}
</div>
</div>
);
});
return descriptions;
}
- private setAnchorVisibility(shouldShowAnchor: boolean) {
+ private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({
shouldShowAnchor,
});
diff --git a/packages/website/ts/pages/documentation/method_signature.tsx b/packages/website/ts/pages/documentation/method_signature.tsx
index 846c9fa4f..041dcd093 100644
--- a/packages/website/ts/pages/documentation/method_signature.tsx
+++ b/packages/website/ts/pages/documentation/method_signature.tsx
@@ -1,11 +1,13 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
-import {Type} from 'ts/pages/documentation/type';
-import {Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod} from 'ts/types';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
+import { Type } from 'ts/pages/documentation/type';
+import { Parameter, SolidityMethod, TypeDefinitionByName, TypescriptMethod } from 'ts/types';
+import { constants } from 'ts/utils/constants';
interface MethodSignatureProps {
- method: TypescriptMethod|SolidityMethod;
+ method: TypescriptMethod | SolidityMethod;
+ sectionName: string;
shouldHideMethodName?: boolean;
shouldUseArrowSyntax?: boolean;
typeDefinitionByName?: TypeDefinitionByName;
@@ -18,32 +20,40 @@ const defaultProps = {
};
export const MethodSignature: React.SFC<MethodSignatureProps> = (props: MethodSignatureProps) => {
- const parameters = renderParameters(props.method, props.docsInfo, props.typeDefinitionByName);
+ const sectionName = constants.TYPES_SECTION_NAME;
+ const parameters = renderParameters(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
const paramString = _.reduce(parameters, (prev: React.ReactNode, curr: React.ReactNode) => {
return [prev, ', ', curr];
});
const methodName = props.shouldHideMethodName ? '' : props.method.name;
- const typeParameterIfExists = _.isUndefined((props.method as TypescriptMethod).typeParameter) ?
- undefined :
- renderTypeParameter(props.method, props.docsInfo, props.typeDefinitionByName);
+ const typeParameterIfExists = _.isUndefined((props.method as TypescriptMethod).typeParameter)
+ ? undefined
+ : renderTypeParameter(props.method, props.docsInfo, sectionName, props.typeDefinitionByName);
return (
<span>
- {props.method.callPath}{methodName}{typeParameterIfExists}({paramString})
- {props.shouldUseArrowSyntax ? ' => ' : ': '}
- {' '}
- {props.method.returnType &&
+ {props.method.callPath}
+ {methodName}
+ {typeParameterIfExists}({paramString})
+ {props.shouldUseArrowSyntax ? ' => ' : ': '}{' '}
+ {props.method.returnType && (
<Type
type={props.method.returnType}
+ sectionName={sectionName}
typeDefinitionByName={props.typeDefinitionByName}
docsInfo={props.docsInfo}
/>
- }
+ )}
</span>
);
};
+MethodSignature.defaultProps = defaultProps;
+
function renderParameters(
- method: TypescriptMethod|SolidityMethod, docsInfo: DocsInfo, typeDefinitionByName?: TypeDefinitionByName,
+ method: TypescriptMethod | SolidityMethod,
+ docsInfo: DocsInfo,
+ sectionName: string,
+ typeDefinitionByName?: TypeDefinitionByName,
) {
const parameters = method.parameters;
const params = _.map(parameters, (p: Parameter) => {
@@ -51,13 +61,15 @@ function renderParameters(
const type = (
<Type
type={p.type}
+ sectionName={sectionName}
typeDefinitionByName={typeDefinitionByName}
docsInfo={docsInfo}
/>
);
return (
<span key={`param-${p.type}-${p.name}`}>
- {p.name}{isOptional && '?'}: {type}
+ {p.name}
+ {isOptional && '?'}: {type}
</span>
);
});
@@ -65,17 +77,21 @@ function renderParameters(
}
function renderTypeParameter(
- method: TypescriptMethod, docsInfo: DocsInfo, typeDefinitionByName?: TypeDefinitionByName,
+ method: TypescriptMethod,
+ docsInfo: DocsInfo,
+ sectionName: string,
+ typeDefinitionByName?: TypeDefinitionByName,
) {
const typeParameter = method.typeParameter;
const typeParam = (
<span>
{`<${typeParameter.name} extends `}
- <Type
- type={typeParameter.type}
- typeDefinitionByName={typeDefinitionByName}
- docsInfo={docsInfo}
- />
+ <Type
+ type={typeParameter.type}
+ sectionName={sectionName}
+ typeDefinitionByName={typeDefinitionByName}
+ docsInfo={docsInfo}
+ />
{`>`}
</span>
);
diff --git a/packages/website/ts/pages/documentation/source_link.tsx b/packages/website/ts/pages/documentation/source_link.tsx
index 74fc6d4d5..6588ee39e 100644
--- a/packages/website/ts/pages/documentation/source_link.tsx
+++ b/packages/website/ts/pages/documentation/source_link.tsx
@@ -1,8 +1,7 @@
import * as _ from 'lodash';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {Source} from 'ts/types';
-import {constants} from 'ts/utils/constants';
+import { Source } from 'ts/types';
+import { colors } from 'ts/utils/colors';
interface SourceLinkProps {
source: Source;
@@ -11,9 +10,7 @@ interface SourceLinkProps {
subPackageName: string;
}
-const packagesWithNamespace = [
- 'connect',
-];
+const packagesWithNamespace = ['connect'];
export function SourceLink(props: SourceLinkProps) {
const src = props.source;
@@ -25,13 +22,8 @@ export function SourceLink(props: SourceLinkProps) {
}
const sourceCodeUrl = `${url}/blob/${tagPrefix}%40${props.version}/packages/${pkg}/${src.fileName}#L${src.line}`;
return (
- <div className="pt2" style={{fontSize: 14}}>
- <a
- href={sourceCodeUrl}
- target="_blank"
- className="underline"
- style={{color: colors.grey500}}
- >
+ <div className="pt2" style={{ fontSize: 14 }}>
+ <a href={sourceCodeUrl} target="_blank" className="underline" style={{ color: colors.grey }}>
Source
</a>
</div>
diff --git a/packages/website/ts/pages/documentation/type.tsx b/packages/website/ts/pages/documentation/type.tsx
index c564429d0..e989e7129 100644
--- a/packages/website/ts/pages/documentation/type.tsx
+++ b/packages/website/ts/pages/documentation/type.tsx
@@ -1,34 +1,30 @@
import * as _ from 'lodash';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
-import {Link as ScrollLink} from 'react-scroll';
+import { Link as ScrollLink } from 'react-scroll';
import * as ReactTooltip from 'react-tooltip';
-import {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 {constants} from 'ts/utils/constants';
-import {typeDocUtils} from 'ts/utils/typedoc_utils';
-import {utils} from 'ts/utils/utils';
-
-const BUILT_IN_TYPE_COLOR = '#e69d00';
-const STRING_LITERAL_COLOR = '#4da24b';
+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';
// 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,
+const typeToUrl: { [typeName: string]: string } = {
+ 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} = {
+const typePrefix: { [typeName: string]: string } = {
Provider: 'Web3',
DecodedLogEntryEvent: 'Web3',
LogEntryEvent: 'Web3',
};
-const typeToSection: {[typeName: string]: string} = {
+const typeToSection: { [typeName: string]: string } = {
ExchangeWrapper: 'exchange',
TokenWrapper: 'token',
TokenRegistryWrapper: 'tokenRegistry',
@@ -41,6 +37,7 @@ const typeToSection: {[typeName: string]: string} = {
interface TypeProps {
type: TypeDef;
docsInfo: DocsInfo;
+ sectionName: string;
typeDefinitionByName?: TypeDefinitionByName;
}
@@ -48,18 +45,16 @@ interface TypeProps {
// <Type /> components (e.g when rendering the union type).
export function Type(props: TypeProps): any {
const type = props.type;
- const isIntrinsic = type.typeDocType === TypeDocTypes.Intrinsic;
const isReference = type.typeDocType === TypeDocTypes.Reference;
const isArray = type.typeDocType === TypeDocTypes.Array;
- const isStringLiteral = type.typeDocType === TypeDocTypes.StringLiteral;
let typeNameColor = 'inherit';
- let typeName: string|React.ReactNode;
+ let typeName: string | React.ReactNode;
let typeArgs: React.ReactNode[] = [];
switch (type.typeDocType) {
case TypeDocTypes.Intrinsic:
case TypeDocTypes.Unknown:
typeName = type.name;
- typeNameColor = BUILT_IN_TYPE_COLOR;
+ typeNameColor = colors.orange;
break;
case TypeDocTypes.Reference:
@@ -72,6 +67,7 @@ export function Type(props: TypeProps): any {
<Type
key={key}
type={arg.elementType}
+ sectionName={props.sectionName}
typeDefinitionByName={props.typeDefinitionByName}
docsInfo={props.docsInfo}
/>[]
@@ -82,6 +78,7 @@ export function Type(props: TypeProps): any {
<Type
key={`type-${arg.name}-${arg.value}-${arg.typeDocType}`}
type={arg}
+ sectionName={props.sectionName}
typeDefinitionByName={props.typeDefinitionByName}
docsInfo={props.docsInfo}
/>
@@ -93,7 +90,7 @@ export function Type(props: TypeProps): any {
case TypeDocTypes.StringLiteral:
typeName = `'${type.value}'`;
- typeNameColor = STRING_LITERAL_COLOR;
+ typeNameColor = colors.green;
break;
case TypeDocTypes.Array:
@@ -106,6 +103,7 @@ export function Type(props: TypeProps): any {
<Type
key={`type-${t.name}-${t.value}-${t.typeDocType}`}
type={t}
+ sectionName={props.sectionName}
typeDefinitionByName={props.typeDefinitionByName}
docsInfo={props.docsInfo}
/>
@@ -132,25 +130,29 @@ export function Type(props: TypeProps): any {
return [prev, ', ', curr];
});
- const typeNameUrlIfExists = typeToUrl[(typeName as string)];
- const typePrefixIfExists = typePrefix[(typeName as string)];
- const sectionNameIfExists = typeToSection[(typeName as string)];
+ const typeNameUrlIfExists = typeToUrl[typeName as string];
+ const typePrefixIfExists = typePrefix[typeName as string];
+ const sectionNameIfExists = typeToSection[typeName as string];
if (!_.isUndefined(typeNameUrlIfExists)) {
typeName = (
<a
href={typeNameUrlIfExists}
target="_blank"
className="text-decoration-none"
- style={{color: colors.lightBlueA700}}
+ style={{ color: colors.lightBlueA700 }}
>
- {!_.isUndefined(typePrefixIfExists) ? `${typePrefixIfExists}.` : ''}{typeName}
+ {!_.isUndefined(typePrefixIfExists) ? `${typePrefixIfExists}.` : ''}
+ {typeName}
</a>
);
- } else if ((isReference || isArray) &&
- (props.docsInfo.isPublicType(typeName as string) ||
- !_.isUndefined(sectionNameIfExists))) {
+ } else if (
+ (isReference || isArray) &&
+ (props.docsInfo.isPublicType(typeName as string) || !_.isUndefined(sectionNameIfExists))
+ ) {
const id = Math.random().toString();
- const typeDefinitionAnchorId = _.isUndefined(sectionNameIfExists) ? typeName : sectionNameIfExists;
+ const typeDefinitionAnchorId = _.isUndefined(sectionNameIfExists)
+ ? `${props.sectionName}-${typeName}`
+ : sectionNameIfExists;
let typeDefinition;
if (props.typeDefinitionByName) {
typeDefinition = props.typeDefinitionByName[typeName as string];
@@ -162,45 +164,49 @@ export function Type(props: TypeProps): any {
duration={constants.DOCS_SCROLL_DURATION_MS}
containerId={constants.DOCS_CONTAINER_ID}
>
- {_.isUndefined(typeDefinition) || utils.isUserOnMobile() ?
- <span
- onClick={utils.setUrlHash.bind(null, typeDefinitionAnchorId)}
- style={{color: colors.lightBlueA700, cursor: 'pointer'}}
- >
- {typeName}
- </span> :
- <span
- data-tip={true}
- data-for={id}
- onClick={utils.setUrlHash.bind(null, typeDefinitionAnchorId)}
- style={{color: colors.lightBlueA700, cursor: 'pointer', display: 'inline-block'}}
- >
- {typeName}
- <ReactTooltip
- type="light"
- effect="solid"
- id={id}
- className="typeTooltip"
+ {_.isUndefined(typeDefinition) || utils.isUserOnMobile() ? (
+ <span
+ onClick={utils.setUrlHash.bind(null, typeDefinitionAnchorId)}
+ style={{ color: colors.lightBlueA700, cursor: 'pointer' }}
>
- <TypeDefinition
- customType={typeDefinition}
- shouldAddId={false}
- docsInfo={props.docsInfo}
- />
- </ReactTooltip>
- </span>
- }
+ {typeName}
+ </span>
+ ) : (
+ <span
+ data-tip={true}
+ data-for={id}
+ onClick={utils.setUrlHash.bind(null, typeDefinitionAnchorId)}
+ style={{
+ color: colors.lightBlueA700,
+ cursor: 'pointer',
+ display: 'inline-block',
+ }}
+ >
+ {typeName}
+ <ReactTooltip type="light" effect="solid" id={id} className="typeTooltip">
+ <TypeDefinition
+ sectionName={props.sectionName}
+ customType={typeDefinition}
+ shouldAddId={false}
+ docsInfo={props.docsInfo}
+ />
+ </ReactTooltip>
+ </span>
+ )}
</ScrollLink>
);
}
return (
<span>
- <span style={{color: typeNameColor}}>{typeName}</span>
- {isArray && '[]'}{!_.isEmpty(typeArgs) &&
+ <span style={{ color: typeNameColor }}>{typeName}</span>
+ {isArray && '[]'}
+ {!_.isEmpty(typeArgs) && (
<span>
- {'<'}{commaSeparatedTypeArgs}{'>'}
+ {'<'}
+ {commaSeparatedTypeArgs}
+ {'>'}
</span>
- }
+ )}
</span>
);
}
diff --git a/packages/website/ts/pages/documentation/type_definition.tsx b/packages/website/ts/pages/documentation/type_definition.tsx
index 17b182c70..d46eec76c 100644
--- a/packages/website/ts/pages/documentation/type_definition.tsx
+++ b/packages/website/ts/pages/documentation/type_definition.tsx
@@ -1,21 +1,19 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {Comment} from 'ts/pages/documentation/comment';
-import {CustomEnum} from 'ts/pages/documentation/custom_enum';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
-import {Enum} from 'ts/pages/documentation/enum';
-import {Interface} from 'ts/pages/documentation/interface';
-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 {constants} from 'ts/utils/constants';
-import {typeDocUtils} from 'ts/utils/typedoc_utils';
-import {utils} from 'ts/utils/utils';
-
-const KEYWORD_COLOR = '#a81ca6';
+import { Comment } from 'ts/pages/documentation/comment';
+import { CustomEnum } from 'ts/pages/documentation/custom_enum';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
+import { Enum } from 'ts/pages/documentation/enum';
+import { Interface } from 'ts/pages/documentation/interface';
+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';
interface TypeDefinitionProps {
+ sectionName: string;
customType: CustomType;
shouldAddId?: boolean;
docsInfo: DocsInfo;
@@ -47,20 +45,13 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
case KindString.Interface:
typePrefix = 'Interface';
codeSnippet = (
- <Interface
- type={customType}
- docsInfo={this.props.docsInfo}
- />
+ <Interface type={customType} sectionName={this.props.sectionName} docsInfo={this.props.docsInfo} />
);
break;
case KindString.Variable:
typePrefix = 'Enum';
- codeSnippet = (
- <CustomEnum
- type={customType}
- />
- );
+ codeSnippet = <CustomEnum type={customType} />;
break;
case KindString.Enumeration:
@@ -71,27 +62,29 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
defaultValue: c.defaultValue,
};
});
- codeSnippet = (
- <Enum
- values={enumValues}
- />
- );
+ codeSnippet = <Enum values={enumValues} />;
break;
- case KindString['Type alias']:
+ case KindString.TypeAlias:
typePrefix = 'Type Alias';
codeSnippet = (
<span>
- <span style={{color: KEYWORD_COLOR}}>type</span> {customType.name} ={' '}
- {customType.type.typeDocType !== TypeDocTypes.Reflection ?
- <Type type={customType.type} docsInfo={this.props.docsInfo} /> :
+ <span style={{ color: colors.lightPurple }}>type</span> {customType.name} ={' '}
+ {customType.type.typeDocType !== TypeDocTypes.Reflection ? (
+ <Type
+ type={customType.type}
+ sectionName={this.props.sectionName}
+ docsInfo={this.props.docsInfo}
+ />
+ ) : (
<MethodSignature
method={customType.type.method}
+ sectionName={this.props.sectionName}
shouldHideMethodName={true}
shouldUseArrowSyntax={true}
docsInfo={this.props.docsInfo}
/>
- }
+ )}
</span>
);
break;
@@ -100,14 +93,14 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
throw utils.spawnSwitchErr('type.kindString', customType.kindString);
}
- const typeDefinitionAnchorId = customType.name;
+ const typeDefinitionAnchorId = `${this.props.sectionName}-${customType.name}`;
return (
<div
id={this.props.shouldAddId ? typeDefinitionAnchorId : ''}
className="pb2"
- style={{overflow: 'hidden', width: '100%'}}
- onMouseOver={this.setAnchorVisibility.bind(this, true)}
- onMouseOut={this.setAnchorVisibility.bind(this, false)}
+ style={{ overflow: 'hidden', width: '100%' }}
+ onMouseOver={this._setAnchorVisibility.bind(this, true)}
+ onMouseOut={this._setAnchorVisibility.bind(this, false)}
>
<AnchorTitle
headerSize={HeaderSizes.H3}
@@ -115,23 +108,16 @@ export class TypeDefinition extends React.Component<TypeDefinitionProps, TypeDef
id={this.props.shouldAddId ? typeDefinitionAnchorId : ''}
shouldShowAnchor={this.state.shouldShowAnchor}
/>
- <div style={{fontSize: 16}}>
+ <div style={{ fontSize: 16 }}>
<pre>
- <code className="hljs">
- {codeSnippet}
- </code>
+ <code className="hljs">{codeSnippet}</code>
</pre>
</div>
- {customType.comment &&
- <Comment
- comment={customType.comment}
- className="py2"
- />
- }
+ {customType.comment && <Comment comment={customType.comment} className="py2" />}
</div>
);
}
- private setAnchorVisibility(shouldShowAnchor: boolean) {
+ private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({
shouldShowAnchor,
});
diff --git a/packages/website/ts/pages/faq/faq.tsx b/packages/website/ts/pages/faq/faq.tsx
index c53ed28b8..b4b5214a2 100644
--- a/packages/website/ts/pages/faq/faq.tsx
+++ b/packages/website/ts/pages/faq/faq.tsx
@@ -1,15 +1,13 @@
import * as _ from 'lodash';
-import RaisedButton from 'material-ui/RaisedButton';
-import {colors} from 'material-ui/styles';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
-import {Link} from 'react-router-dom';
-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 {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
+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';
export interface FAQProps {
source: string;
@@ -32,14 +30,19 @@ const sections: FAQSection[] = [
prompt: 'What is 0x?',
answer: (
<div>
- At its core, 0x is an open and non-rent seeking protocol that facilitates trustless,
- low friction exchange of Ethereum-based assets. Developers can use 0x as a platform
- to build exchange applications on top of{' '}
- (<a href={`${configs.BASE_URL}${WebsitePaths.ZeroExJs}#introduction`} target="blank">0x.js</a>
- {' '}is a Javascript library for interacting with the 0x protocol). For end users, 0x will be
- the infrastructure of a wide variety of user-facing applications i.e.{' '}
- <a href={`${configs.BASE_URL}${WebsitePaths.Portal}`} target="blank">0x Portal</a>,
- a decentralized application that facilitates trustless trading of Ethereum-based tokens
+ At its core, 0x is an open and non-rent seeking protocol that facilitates trustless, low
+ friction exchange of Ethereum-based assets. Developers can use 0x as a platform to build
+ exchange applications on top of (<a
+ href={`${configs.BASE_URL}${WebsitePaths.ZeroExJs}#introduction`}
+ target="blank"
+ >
+ 0x.js
+ </a>{' '}
+ is a Javascript library for interacting with the 0x protocol). For end users, 0x will be the
+ infrastructure of a wide variety of user-facing applications i.e.{' '}
+ <a href={`${configs.BASE_URL}${WebsitePaths.Portal}`} target="blank">
+ 0x Portal
+ </a>, a decentralized application that facilitates trustless trading of Ethereum-based tokens
between known counterparties.
</div>
),
@@ -49,15 +52,14 @@ const sections: FAQSection[] = [
answer: (
<div>
In the two years since the Ethereum blockchain’s genesis block, numerous decentralized
- applications (dApps) have created Ethereum smart contracts for peer-to-peer exchange.
- Rapid iteration and a lack of best practices have left the blockchain scattered with
- proprietary and application-specific implementations. As a result, end users are
- exposed to numerous smart contracts of varying quality and security, with unique
- configuration processes and learning curves, all of which implement the same
- functionality. This approach imposes unnecessary costs on the network by fragmenting
- end users according to the particular dApp each user happens to be using, eliminating
- valuable network effects around liquidity. 0x is the solution to this problem by
- acting as modular, unopinionated building blocks that may be assembled and reconfigured.
+ applications (dApps) have created Ethereum smart contracts for peer-to-peer exchange. Rapid
+ iteration and a lack of best practices have left the blockchain scattered with proprietary and
+ application-specific implementations. As a result, end users are exposed to numerous smart
+ contracts of varying quality and security, with unique configuration processes and learning
+ curves, all of which implement the same functionality. This approach imposes unnecessary costs
+ on the network by fragmenting end users according to the particular dApp each user happens to be
+ using, eliminating valuable network effects around liquidity. 0x is the solution to this problem
+ by acting as modular, unopinionated building blocks that may be assembled and reconfigured.
</div>
),
},
@@ -66,20 +68,18 @@ const sections: FAQSection[] = [
answer: (
<div>
<ul>
+ <li>0x is a protocol for exchange, not a user-facing exchange application.</li>
<li>
- 0x is a protocol for exchange, not a user-facing exchange application.
- </li>
- <li>
- 0x is decentralized and trustless; there is no central party which can be
- hacked, run away with customer funds or be subjected to government regulations.
- Hacks of Mt. Gox, Shapeshift and Bitfinex have demonstrated that these types of
- systemic risks are palpable.
+ 0x is decentralized and trustless; there is no central party which can be hacked, run
+ away with customer funds or be subjected to government regulations. Hacks of Mt. Gox,
+ Shapeshift and Bitfinex have demonstrated that these types of systemic risks are
+ palpable.
</li>
<li>
- Rather than a proprietary system that exists to extract rent for its owners,
- 0x is public infrastructure that is funded by a globally distributed community
- of stakeholders. While the protocol is free to use, it enables for-profit
- user-facing exchange applications to be built on top of the protocol.
+ Rather than a proprietary system that exists to extract rent for its owners, 0x is
+ public infrastructure that is funded by a globally distributed community of
+ stakeholders. While the protocol is free to use, it enables for-profit user-facing
+ exchange applications to be built on top of the protocol.
</li>
</ul>
</div>
@@ -89,13 +89,12 @@ const sections: FAQSection[] = [
prompt: 'If 0x protocol is free to use, where do transaction fees come in?',
answer: (
<div>
- 0x protocol uses off-chain order books to massively reduce friction costs for
- market makers and ensure that the blockchain is only used for trade settlement.
- Hosting and maintaining an off-chain order book is a service; to incent “Relayers”
- to provide this service they must be able to charge transaction fees on trading
- activity. Relayers are free to set their transaction fees to any value they desire.
- We expect Relayers to be highly competitive and transaction fees to approach an
- efficient economic equilibrium over time.
+ 0x protocol uses off-chain order books to massively reduce friction costs for market makers and
+ ensure that the blockchain is only used for trade settlement. Hosting and maintaining an
+ off-chain order book is a service; to incent “Relayers” to provide this service they must be
+ able to charge transaction fees on trading activity. Relayers are free to set their transaction
+ fees to any value they desire. We expect Relayers to be highly competitive and transaction fees
+ to approach an efficient economic equilibrium over time.
</div>
),
},
@@ -104,25 +103,23 @@ const sections: FAQSection[] = [
answer: (
<div>
<div>
- Participants in a state channel pass cryptographically signed messages back and
- forth, accumulating intermediate state changes without publishing them to the
- canonical chain until the channel is closed. State channels are ideal for “bar tab”
- applications where numerous intermediate state changes may be accumulated off-chain
- before being settled by a final on-chain transaction (i.e. day trading, poker,
- turn-based games).
+ Participants in a state channel pass cryptographically signed messages back and forth,
+ accumulating intermediate state changes without publishing them to the canonical chain until
+ the channel is closed. State channels are ideal for “bar tab” applications where numerous
+ intermediate state changes may be accumulated off-chain before being settled by a final
+ on-chain transaction (i.e. day trading, poker, turn-based games).
</div>
<ul>
<li>
- While state channels drastically reduce the number of on-chain transactions
- for specific use cases, numerous on-chain transactions and a security deposit
- are required to open and safely close a state channel making them less efficient
- than 0x for executing one-time trades.
+ While state channels drastically reduce the number of on-chain transactions for specific
+ use cases, numerous on-chain transactions and a security deposit are required to open
+ and safely close a state channel making them less efficient than 0x for executing
+ one-time trades.
</li>
<li>
- State channels are isolated from the Ethereum blockchain meaning that
- they cannot interact with smart contracts. 0x is designed to be integrated
- directly into smart contracts so trades can be executed programmatically
- in a single line of Solidity code.
+ State channels are isolated from the Ethereum blockchain meaning that they cannot
+ interact with smart contracts. 0x is designed to be integrated directly into smart
+ contracts so trades can be executed programmatically in a single line of Solidity code.
</li>
</ul>
</div>
@@ -132,16 +129,20 @@ const sections: FAQSection[] = [
prompt: 'What types of digital assets are supported by 0x?',
answer: (
<div>
- 0x supports all Ethereum-based assets that adhere to the ERC20 token standard.
- There are many ERC20 tokens, worth a combined $2.2B, and more tokens are created
- each month. We believe that, by 2020, thousands of assets will be tokenized and
- moved onto the Ethereum blockchain including traditional securities such as equities,
- bonds and derivatives, fiat currencies and scarce digital goods such as video game
- items. In the future, cross-blockchain solutions such as{' '}
- <a href="https://cosmos.network/" target="_blank">Cosmos</a> and{' '}
- <a href="http://polkadot.io/" target="_blank">Polkadot</a> will allow cryptocurrencies
- to freely move between blockchains and, naturally, currencies such as Bitcoin will
- end up being represented as ERC20 tokens on the Ethereum blockchain.
+ 0x supports all Ethereum-based assets that adhere to the ERC20 token standard. There are many
+ ERC20 tokens, worth a combined $2.2B, and more tokens are created each month. We believe that,
+ by 2020, thousands of assets will be tokenized and moved onto the Ethereum blockchain including
+ traditional securities such as equities, bonds and derivatives, fiat currencies and scarce
+ digital goods such as video game items. In the future, cross-blockchain solutions such as{' '}
+ <a href="https://cosmos.network/" target="_blank">
+ Cosmos
+ </a>{' '}
+ and{' '}
+ <a href="http://polkadot.io/" target="_blank">
+ Polkadot
+ </a>{' '}
+ will allow cryptocurrencies to freely move between blockchains and, naturally, currencies such
+ as Bitcoin will end up being represented as ERC20 tokens on the Ethereum blockchain.
</div>
),
},
@@ -149,23 +150,19 @@ const sections: FAQSection[] = [
prompt: '0x is open source: what prevents someone from forking the protocol?',
answer: (
<div>
- Ethereum and Bitcoin are both open source protocols. Each protocol has been forked,
- but the resulting clone networks have seen little adoption (as measured by transaction
- count or market cap). This is because users have little to no incentive to switch
- over to a clone network if the original has initial network effects and a talented
- developer team behind it.
- An exception is in the case that a protocol includes a controversial feature such as
- a method of rent extraction or a monetary policy that favors one group of users over
- another (Zcash developer subsidy - for better or worse - resulted in Zclassic).
- Perceived inequality can provide a strong enough incentive that users will fork the
- original protocol’s codebase and spin up a new network that eliminates the controversial
- feature. In the case of 0x, there is no rent extraction and no users are given
- special permissions.
-
- 0x protocol is upgradable. Cutting-edge technical capabilities can be integrated
- into 0x via decentralized governance (see section below), eliminating incentives
- to fork off of the original protocol and sacrifice the network effects surrounding
- liquidity that result from the shared protocol and settlement layer.
+ Ethereum and Bitcoin are both open source protocols. Each protocol has been forked, but the
+ resulting clone networks have seen little adoption (as measured by transaction count or market
+ cap). This is because users have little to no incentive to switch over to a clone network if the
+ original has initial network effects and a talented developer team behind it. An exception is in
+ the case that a protocol includes a controversial feature such as a method of rent extraction or
+ a monetary policy that favors one group of users over another (Zcash developer subsidy - for
+ better or worse - resulted in Zclassic). Perceived inequality can provide a strong enough
+ incentive that users will fork the original protocol’s codebase and spin up a new network that
+ eliminates the controversial feature. In the case of 0x, there is no rent extraction and no
+ users are given special permissions. 0x protocol is upgradable. Cutting-edge technical
+ capabilities can be integrated into 0x via decentralized governance (see section below),
+ eliminating incentives to fork off of the original protocol and sacrifice the network effects
+ surrounding liquidity that result from the shared protocol and settlement layer.
</div>
),
},
@@ -182,26 +179,25 @@ const sections: FAQSection[] = [
0x protocol token (ZRX) is utilized in two ways: 1) to solve the{' '}
<a href="https://en.wikipedia.org/wiki/Coordination_game" target="_blank">
coordination problem
- </a> and drive network effects around liquidity, creating a feedback loop
- where early adopters of the protocol benefit from wider adoption and 2) to
- be used for decentralized governance over 0x protocol's update mechanism.
- In more detail:
+ </a>{' '}
+ and drive network effects around liquidity, creating a feedback loop where early adopters of
+ the protocol benefit from wider adoption and 2) to be used for decentralized governance over
+ 0x protocol's update mechanism. In more detail:
</div>
<ul>
<li>
- ZRX tokens are used by Makers and Takers (market participants that generate
- and consume orders, respectively) to pay transaction fees to Relayers
- (entities that host and maintain public order books).
+ ZRX tokens are used by Makers and Takers (market participants that generate and consume
+ orders, respectively) to pay transaction fees to Relayers (entities that host and
+ maintain public order books).
</li>
<li>
- ZRX tokens are used for decentralized governance over 0x protocol’s update
- mechanism which allows its underlying smart contracts to be replaced and
- improved over time. An update mechanism is needed because 0x is built upon
- Ethereum’s rapidly evolving technology stack, decentralized governance is
- needed because 0x protocol’s smart contracts will have access to user funds
- and numerous dApps will need to plug into 0x smart contracts. Decentralized
- governance ensures that this update process is secure and minimizes disruption
- to the network.
+ ZRX tokens are used for decentralized governance over 0x protocol’s update mechanism
+ which allows its underlying smart contracts to be replaced and improved over time. An
+ update mechanism is needed because 0x is built upon Ethereum’s rapidly evolving
+ technology stack, decentralized governance is needed because 0x protocol’s smart
+ contracts will have access to user funds and numerous dApps will need to plug into 0x
+ smart contracts. Decentralized governance ensures that this update process is secure and
+ minimizes disruption to the network.
</li>
</ul>
</div>
@@ -211,9 +207,9 @@ const sections: FAQSection[] = [
prompt: 'Why must transaction fees be denominated in 0x token (ZRX) rather than ETH?',
answer: (
<div>
- 0x protocol’s decentralized update mechanism is analogous to proof-of-stake.
- To maximize the alignment of stakeholder and end user incentives, the staked
- asset must provide utility within the protocol.
+ 0x protocol’s decentralized update mechanism is analogous to proof-of-stake. To maximize the
+ alignment of stakeholder and end user incentives, the staked asset must provide utility within
+ the protocol.
</div>
),
},
@@ -221,10 +217,10 @@ const sections: FAQSection[] = [
prompt: 'How will decentralized governance work?',
answer: (
<div>
- Decentralized governance is an ongoing focus of research; it will involve token
- voting with ZRX. Ultimately the solution will maximize security while also maximizing
- the protocol’s ability to absorb new innovations. Until the governance structure is
- formalized and encoded within 0x DAO, a multi-sig will be used as a placeholder.
+ Decentralized governance is an ongoing focus of research; it will involve token voting with ZRX.
+ Ultimately the solution will maximize security while also maximizing the protocol’s ability to
+ absorb new innovations. Until the governance structure is formalized and encoded within 0x DAO,
+ a multi-sig will be used as a placeholder.
</div>
),
},
@@ -235,27 +231,19 @@ const sections: FAQSection[] = [
questions: [
{
prompt: 'What is the total supply of ZRX tokens?',
- answer: (
- <div>
- 1,000,000,000 ZRX. Fixed supply.
- </div>
- ),
+ answer: <div>1,000,000,000 ZRX. Fixed supply.</div>,
},
{
prompt: 'When is the Token Launch? will there be a pre-sale?',
- answer: (
- <div>
- The token launch will be on August 15th, 2017. There will not be a pre-sale.
- </div>
- ),
+ answer: <div>The token launch will be on August 15th, 2017. There will not be a pre-sale.</div>,
},
{
prompt: 'What will the token launch proceeds be used for?',
answer: (
<div>
- 100% of the proceeds raised in the token launch will be used to fund the development
- of free and open source software, tools and infrastructure that support the protocol
- and surrounding ecosystem. Check out our{' '}
+ 100% of the proceeds raised in the token launch will be used to fund the development of free and
+ open source software, tools and infrastructure that support the protocol and surrounding
+ ecosystem. Check out our{' '}
<a
href="https://docs.google.com/document/d/1_RVa-_bkU92fWRsC8eNy4vYjcTt-WC8GtqyyjbTd-oY"
target="_blank"
@@ -269,66 +257,50 @@ const sections: FAQSection[] = [
prompt: 'What will be the initial distribution of ZRX tokens?',
answer: (
<div>
- <div className="center" style={{width: '100%'}}>
- <img
- style={{width: 350}}
- src="/images/zrx_pie_chart.png"
- />
+ <div className="center" style={{ width: '100%' }}>
+ <img style={{ width: 350 }} src="/images/zrx_pie_chart.png" />
</div>
<div className="py1">
- <div className="bold pb1">
- Token Launch (50%)
- </div>
+ <div className="bold pb1">Token Launch (50%)</div>
<div>
- ZRX is inherently a governance token that plays a critical role in the
- process of upgrading 0x protocol. We are fully committed to formulating
- a functional and theoretically sound governance model and we plan to dedicate
- significant resources to R&D.
+ ZRX is inherently a governance token that plays a critical role in the process of
+ upgrading 0x protocol. We are fully committed to formulating a functional and
+ theoretically sound governance model and we plan to dedicate significant resources to
+ R&D.
</div>
</div>
<div className="py1">
- <div className="bold pb1">
- Retained by 0x (15%)
- </div>
+ <div className="bold pb1">Retained by 0x (15%)</div>
<div>
- The 0x core development team will be able to sustain itself for approximately
- five years using funds raised through the token launch. If 0x protocol
- proves to be as foundational a technology as we believe it to be, the
- retained ZRX tokens will allow the 0x core development team to sustain
- operations beyond the first 5 years.
+ The 0x core development team will be able to sustain itself for approximately five years
+ using funds raised through the token launch. If 0x protocol proves to be as foundational
+ a technology as we believe it to be, the retained ZRX tokens will allow the 0x core
+ development team to sustain operations beyond the first 5 years.
</div>
</div>
<div className="py1">
- <div className="bold pb1">
- Developer Fund (15%)
- </div>
+ <div className="bold pb1">Developer Fund (15%)</div>
<div>
- The Developer Fund will be used to make targeted capital injections
- into high potential projects and teams that are attempting to grow
- the 0x ecosystem, strategic partnerships, hackathon prizes and community
- development activities.
+ The Developer Fund will be used to make targeted capital injections into high potential
+ projects and teams that are attempting to grow the 0x ecosystem, strategic partnerships,
+ hackathon prizes and community development activities.
</div>
</div>
<div className="py1">
- <div className="bold pb1">
- Founding Team (10%)
- </div>
+ <div className="bold pb1">Founding Team (10%)</div>
<div>
- The founding team’s allocation of ZRX will vest over a traditional 4
- year vesting schedule with a one year cliff. We believe this should
- be standard practice for any team that is committed to making their
- project a long term success.
+ The founding team’s allocation of ZRX will vest over a traditional 4 year vesting
+ schedule with a one year cliff. We believe this should be standard practice for any team
+ that is committed to making their project a long term success.
</div>
</div>
<div className="py1">
- <div className="bold pb1">
- Early Backers & Advisors (10%)
- </div>
+ <div className="bold pb1">Early Backers & Advisors (10%)</div>
<div>
- Our backers and advisors have provided capital, resources and guidance
- that have allowed us to fill out our team, setup a robust legal entity
- and build a fully functional product before launching a token. As a result,
- we have a proven track record and can offer a token that holds genuine utility.
+ Our backers and advisors have provided capital, resources and guidance that have allowed
+ us to fill out our team, setup a robust legal entity and build a fully functional
+ product before launching a token. As a result, we have a proven track record and can
+ offer a token that holds genuine utility.
</div>
</div>
</div>
@@ -338,47 +310,39 @@ const sections: FAQSection[] = [
prompt: 'Can I mine ZRX tokens?',
answer: (
<div>
- No, the total supply of ZRX tokens is fixed and there is no continuous issuance
- model. Users that facilitate trading over 0x protocol by operating a Relayer
- earn transaction fees denominated in ZRX; as more trading activity is generated,
- more transaction fees are earned.
+ No, the total supply of ZRX tokens is fixed and there is no continuous issuance model. Users
+ that facilitate trading over 0x protocol by operating a Relayer earn transaction fees
+ denominated in ZRX; as more trading activity is generated, more transaction fees are earned.
</div>
),
},
{
prompt: 'Will there be a lockup period for ZRX tokens sold in the token launch?',
- answer: (
- <div>
- No, ZRX tokens sold in the token launch will immediately be liquid.
- </div>
- ),
+ answer: <div>No, ZRX tokens sold in the token launch will immediately be liquid.</div>,
},
{
prompt: 'Will there be a lockup period for tokens allocated to the founding team?',
answer: (
<div>
- Yes. ZRX tokens allocated to founders, advisors and staff members will be released
- over a 4 year vesting schedule with a 25% cliff upon completion of the initial
- token launch and 25% released each subsequent year in monthly installments. Staff
- members hired after the token launch will have a 4 year vesting schedule with a
- one year cliff.
+ Yes. ZRX tokens allocated to founders, advisors and staff members will be released over a 4 year
+ vesting schedule with a 25% cliff upon completion of the initial token launch and 25% released
+ each subsequent year in monthly installments. Staff members hired after the token launch will
+ have a 4 year vesting schedule with a one year cliff.
</div>
),
},
{
prompt: 'Which cryptocurrencies will be accepted in the token launch?',
- answer: (
- <div>ETH.</div>
- ),
+ answer: <div>ETH.</div>,
},
{
prompt: 'When will 0x be live?',
answer: (
<div>
- An alpha version of 0x has been live on our private test network since January
- 2017. Version 1.0 of 0x protocol will be deployed to the canonical Ethereum
- blockchain after a round of security audits and prior to the public token launch.
- 0x will be using the 0x protocol during our token launch.
+ An alpha version of 0x has been live on our private test network since January 2017. Version 1.0
+ of 0x protocol will be deployed to the canonical Ethereum blockchain after a round of security
+ audits and prior to the public token launch. 0x will be using the 0x protocol during our token
+ launch.
</div>
),
},
@@ -403,19 +367,17 @@ const sections: FAQSection[] = [
questions: [
{
prompt: 'Where is 0x based?',
- answer: (
- <div>
- 0x was founded in SF and is driven by a diverse group of contributors.
- </div>
- ),
+ answer: <div>0x was founded in SF and is driven by a diverse group of contributors.</div>,
},
{
prompt: 'How can I get involved?',
answer: (
<div>
- Join our <a href={constants.ZEROEX_CHAT_URL} 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.
+ 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>
),
},
@@ -423,20 +385,15 @@ const sections: FAQSection[] = [
prompt: 'Why the name 0x?',
answer: (
<div>
- 0x is the prefix for hexadecimal numeric constants including Ethereum addresses.
- In a more abstract context, as the first open protocol for exchange 0x represents
- the beginning of the end for the exchange industry’s rent seeking oligopoly:
- zero exchange.
+ 0x is the prefix for hexadecimal numeric constants including Ethereum addresses. In a more
+ abstract context, as the first open protocol for exchange 0x represents the beginning of the end
+ for the exchange industry’s rent seeking oligopoly: zero exchange.
</div>
),
},
{
prompt: 'How do you pronounce 0x?',
- answer: (
- <div>
- We pronounce 0x as “zero-ex,” but you are free to pronounce it however you please.
- </div>
- ),
+ answer: <div>We pronounce 0x as “zero-ex,” but you are free to pronounce it however you please.</div>,
},
],
},
@@ -449,38 +406,31 @@ export class FAQ extends React.Component<FAQProps, FAQState> {
public render() {
return (
<div>
- <DocumentTitle title="0x FAQ"/>
- <TopBar
- blockchainIsLoaded={false}
- location={this.props.location}
- />
- <div
- id="faq"
- className="mx-auto max-width-4 pt4"
- style={{color: colors.grey800}}
- >
- <h1 className="center" style={{...styles.thin}}>0x FAQ</h1>
- <div className="sm-px2 md-px2 lg-px0 pb4">
- {this.renderSections()}
- </div>
+ <DocumentTitle title="0x FAQ" />
+ <TopBar blockchainIsLoaded={false} location={this.props.location} />
+ <div id="faq" className="mx-auto max-width-4 pt4" style={{ color: colors.grey800 }}>
+ <h1 className="center" style={{ ...styles.thin }}>
+ 0x FAQ
+ </h1>
+ <div className="sm-px2 md-px2 lg-px0 pb4">{this._renderSections()}</div>
</div>
- <Footer location={this.props.location} />
+ <Footer />
</div>
);
}
- private renderSections() {
+ private _renderSections() {
const renderedSections = _.map(sections, (section: FAQSection, i: number) => {
const isFirstSection = i === 0;
return (
<div key={section.name}>
<h3>{section.name}</h3>
- {this.renderQuestions(section.questions, isFirstSection)}
+ {this._renderQuestions(section.questions, isFirstSection)}
</div>
);
});
return renderedSections;
}
- private renderQuestions(questions: FAQQuestion[], isFirstSection: boolean) {
+ private _renderQuestions(questions: FAQQuestion[], isFirstSection: boolean) {
const renderedQuestions = _.map(questions, (question: FAQQuestion, i: number) => {
const isFirstQuestion = i === 0;
return (
diff --git a/packages/website/ts/pages/faq/question.tsx b/packages/website/ts/pages/faq/question.tsx
index 917863e4a..988c04bc9 100644
--- a/packages/website/ts/pages/faq/question.tsx
+++ b/packages/website/ts/pages/faq/question.tsx
@@ -1,6 +1,7 @@
import * as _ from 'lodash';
-import {Card, CardHeader, CardText} from 'material-ui/Card';
+import { Card, CardHeader, CardText } from 'material-ui/Card';
import * as React from 'react';
+import { colors } from 'ts/utils/colors';
export interface QuestionProps {
prompt: string;
@@ -21,30 +22,28 @@ export class Question extends React.Component<QuestionProps, QuestionState> {
}
public render() {
return (
- <div
- className="py1"
- >
+ <div className="py1">
<Card
initiallyExpanded={this.props.shouldDisplayExpanded}
- onExpandChange={this.onExchangeChange.bind(this)}
+ onExpandChange={this._onExchangeChange.bind(this)}
>
<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)'}}
+ style={{
+ borderBottom: this.state.isExpanded ? '1px solid rgba(0, 0, 0, 0.19)' : 'none',
+ }}
+ titleStyle={{ color: colors.darkerGrey }}
actAsExpander={true}
showExpandableButton={true}
/>
<CardText expandable={true}>
- <div style={{lineHeight: 1.4}}>
- {this.props.answer}
- </div>
+ <div style={{ lineHeight: 1.4 }}>{this.props.answer}</div>
</CardText>
</Card>
</div>
);
}
- private onExchangeChange() {
+ private _onExchangeChange() {
this.setState({
isExpanded: !this.state.isExpanded,
});
diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx
index f3c46b8c7..ca76497df 100644
--- a/packages/website/ts/pages/landing/landing.tsx
+++ b/packages/website/ts/pages/landing/landing.tsx
@@ -1,15 +1,14 @@
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, Styles, WebsitePaths} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+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';
interface BoxContent {
title: string;
@@ -36,31 +35,29 @@ 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[] = [
{
title: 'Trustless exchange',
- description: 'Built on Ethereum\'s distributed network with no centralized \
+ description:
+ "Built on Ethereum's distributed network with no centralized \
point of failure and no down time, each trade is settled atomically \
- and without counterparty risk.',
+ and without counterparty risk.",
imageUrl: '/images/landing/distributed_network.png',
classNames: '',
},
{
title: 'Shared liquidity',
- description: 'By sharing a standard API, relayers can easily aggregate liquidity pools, \
+ description:
+ 'By sharing a standard API, relayers can easily aggregate liquidity pools, \
creating network effects around liquidity that compound as more relayers come online.',
imageUrl: '/images/landing/liquidity.png',
classNames: 'mx-auto',
},
{
title: 'Open source',
- description: '0x is open source, permissionless and free to use. Trade directly with a known \
+ description:
+ '0x is open source, permissionless and free to use. Trade directly with a known \
counterparty for free or pay a relayer some ZRX tokens to access their liquidity \
pool.',
imageUrl: '/images/landing/open_source.png',
@@ -71,67 +68,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,
},
];
@@ -144,45 +141,45 @@ interface LandingState {
}
export class Landing extends React.Component<LandingProps, LandingState> {
- private throttledScreenWidthUpdate: () => void;
+ private _throttledScreenWidthUpdate: () => void;
constructor(props: LandingProps) {
super(props);
this.state = {
screenWidth: utils.getScreenWidth(),
};
- this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
+ this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
}
public componentDidMount() {
- window.addEventListener('resize', this.throttledScreenWidthUpdate);
+ window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0);
}
public componentWillUnmount() {
- window.removeEventListener('resize', this.throttledScreenWidthUpdate);
+ window.removeEventListener('resize', this._throttledScreenWidthUpdate);
}
public render() {
return (
- <div id="landing" className="clearfix" style={{color: colors.grey800}}>
- <DocumentTitle title="0x Protocol"/>
+ <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()}
- {this.renderTokenizationSection()}
- {this.renderProtocolSection()}
- {this.renderInfoBoxes()}
- {this.renderBuildingBlocksSection()}
- {this.renderUseCases()}
- {this.renderCallToAction()}
- <Footer location={this.props.location} />
+ {this._renderHero()}
+ {this._renderProjects()}
+ {this._renderTokenizationSection()}
+ {this._renderProtocolSection()}
+ {this._renderInfoBoxes()}
+ {this._renderBuildingBlocksSection()}
+ {this._renderUseCases()}
+ {this._renderCallToAction()}
+ <Footer />
</div>
);
}
- private renderHero() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
+ private _renderHero() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const buttonLabelStyle: React.CSSProperties = {
textTransform: 'none',
fontSize: isSmallScreen ? 12 : 14,
@@ -194,46 +191,43 @@ export class Landing extends React.Component<LandingProps, LandingState> {
lineHeight: '33px',
height: 38,
};
- const left = 'col lg-col-7 md-col-7 col-12 lg-pt4 md-pt4 sm-pt0 mt1 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center';
+ const left = 'col lg-col-7 md-col-7 col-12 lg-pt4 md-pt4 sm-pt0 mt1 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center';
return (
- <div
- className="clearfix py4"
- style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}}
- >
- <div
- className="mx-auto max-width-4 clearfix"
- >
+ <div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}>
+ <div className="mx-auto max-width-4 clearfix">
<div className="lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-my4 md-my4 sm-mt2 sm-mb4 clearfix">
<div className="col lg-col-5 md-col-5 col-12 sm-center">
- <img
- src="/images/landing/hero_chip_image.png"
- height={isSmallScreen ? 300 : 395}
- />
+ <img src="/images/landing/hero_chip_image.png" height={isSmallScreen ? 300 : 395} />
</div>
- <div
- className={left}
- style={{color: 'white'}}
- >
- <div style={{paddingLeft: isSmallScreen ? 0 : 12}}>
+ <div className={left} style={{ color: colors.white }}>
+ <div style={{ paddingLeft: isSmallScreen ? 0 : 12 }}>
<div
className="sm-pb2"
- style={{fontFamily: 'Roboto Mono', fontSize: isSmallScreen ? 26 : 34}}
+ style={{
+ fontFamily: 'Roboto Mono',
+ fontSize: isSmallScreen ? 26 : 34,
+ }}
>
Powering decentralized exchange
</div>
<div
className="pt2 h5 sm-mx-auto"
- style={{maxWidth: 446, fontFamily: 'Roboto Mono', lineHeight: 1.7, fontWeight: 300}}
+ style={{
+ maxWidth: 446,
+ fontFamily: 'Roboto Mono',
+ lineHeight: 1.7,
+ fontWeight: 300,
+ }}
>
- 0x is an open, permissionless protocol allowing for ERC20 tokens to
- be traded on the Ethereum blockchain.
+ 0x is an open, permissionless protocol allowing for ERC20 tokens to be traded on the
+ Ethereum blockchain.
</div>
- <div className="pt3 clearfix sm-mx-auto" style={{maxWidth: 342}}>
+ <div className="pt3 clearfix sm-mx-auto" style={{ maxWidth: 342 }}>
<div className="lg-pr2 md-pr2 col col-6 sm-center">
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
<RaisedButton
- style={{borderRadius: 6, minWidth: 157.36}}
- buttonStyle={{borderRadius: 6}}
+ style={{ borderRadius: 6, minWidth: 157.36 }}
+ buttonStyle={{ borderRadius: 6 }}
labelStyle={buttonLabelStyle}
label="Build on 0x"
onClick={_.noop}
@@ -242,15 +236,15 @@ 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"
>
<RaisedButton
- style={{borderRadius: 6, minWidth: 150}}
+ 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,22 +259,15 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
}
- private renderProjects() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
- const isMediumScreen = this.state.screenWidth === ScreenWidths.MD;
+ private _renderProjects() {
+ 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);
+ const colWidth = isSmallScreen ? 3 : isMediumScreen ? 4 : 2 - i % 2;
return (
- <div
- key={`project-${project.logoFileName}`}
- className={`col col-${colWidth} center`}
- >
+ <div key={`project-${project.logoFileName}`} className={`col col-${colWidth} center`}>
<div>
- <a
- href={project.projectUrl}
- target="_blank"
- className="text-decoration-none"
- >
+ <a href={project.projectUrl} target="_blank" className="text-decoration-none">
<img
src={`/images/landing/project_logos/${project.logoFileName}`}
height={isSmallScreen ? 60 : 92}
@@ -292,35 +279,32 @@ 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,
};
return (
- <div
- className="clearfix py4"
- style={{backgroundColor: CUSTOM_PROJECTS_BACKGROUND_COLOR}}
- >
+ <div className="clearfix py4" style={{ backgroundColor: colors.projectsGrey }}>
<div className="mx-auto max-width-4 clearfix sm-px3">
- <div
- className="h4 pb3 md-pl3 sm-pl2"
- style={titleStyle}
- >
+ <div className="h4 pb3 md-pl3 sm-pl2" style={titleStyle}>
Projects building on 0x
</div>
- <div className="clearfix">
- {projectList}
- </div>
+ <div className="clearfix">{projectList}</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,137 +313,129 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
}
- private renderTokenizationSection() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
+ private _renderTokenizationSection() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return (
- <div
- className="clearfix lg-py4 md-py4 sm-pb4 sm-pt2"
- style={{backgroundColor: CUSTOM_WHITE_BACKGROUND}}
- >
+ <div className="clearfix lg-py4 md-py4 sm-pb4 sm-pt2" style={{ backgroundColor: colors.grey100 }}>
<div className="mx-auto max-width-4 py4 clearfix">
- {isSmallScreen &&
- this.renderTokenCloud()
- }
+ {isSmallScreen && this._renderTokenCloud()}
<div className="col lg-col-6 md-col-6 col-12">
- <div className="mx-auto" style={{maxWidth: 385, paddingTop: 7}}>
- <div
- className="lg-h1 md-h1 sm-h2 sm-center sm-pt3"
- style={{fontFamily: 'Roboto Mono'}}
- >
+ <div className="mx-auto" style={{ maxWidth: 385, paddingTop: 7 }}>
+ <div className="lg-h1 md-h1 sm-h2 sm-center sm-pt3" style={{ fontFamily: 'Roboto Mono' }}>
The world's value is becoming tokenized
</div>
<div
className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 h5 sm-center"
- style={{fontFamily: 'Roboto Mono', lineHeight: 1.7}}
+ style={{ fontFamily: 'Roboto Mono', lineHeight: 1.7 }}
>
- {isSmallScreen ?
+ {isSmallScreen ? (
<span>
The Ethereum blockchain is an open, borderless financial system that represents
a wide variety of assets as cryptographic tokens. In the future, most digital
assets and goods will be tokenized.
- </span> :
+ </span>
+ ) : (
<div>
<div>
- The Ethereum blockchain is an open, borderless
- financial system that represents
+ The Ethereum blockchain is an open, borderless financial system that
+ represents
</div>
<div>
- a wide variety of assets as cryptographic tokens.
- In the future, most digital assets and goods will be tokenized.
+ a wide variety of assets as cryptographic tokens. In the future, most
+ digital assets and goods will be tokenized.
</div>
</div>
- }
- </div>
- <div className="flex pt1 sm-px3">
- {this.renderAssetTypes()}
+ )}
</div>
+ <div className="flex pt1 sm-px3">{this._renderAssetTypes()}</div>
</div>
</div>
- {!isSmallScreen &&
- this.renderTokenCloud()
- }
+ {!isSmallScreen && this._renderTokenCloud()}
</div>
</div>
);
}
- private renderProtocolSection() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
+ private _renderProtocolSection() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return (
- <div
- className="clearfix lg-py4 md-py4 sm-pt4"
- style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}}
- >
+ <div className="clearfix lg-py4 md-py4 sm-pt4" 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">
- <img
- src="/images/landing/relayer_diagram.png"
- height={isSmallScreen ? 326 : 426}
- />
+ <img src="/images/landing/relayer_diagram.png" height={isSmallScreen ? 326 : 426} />
</div>
<div
className="col lg-col-6 md-col-6 col-12 lg-pr3 md-pr3 sm-mx-auto"
- style={{color: 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"
- style={{fontFamily: 'Roboto Mono'}}
- >
- <div>
- Off-chain order relay
- </div>
- <div>
- On-chain settlement
- </div>
+ <div className="lg-h1 md-h1 sm-h2 pb1 sm-pt3 sm-center" style={{ fontFamily: 'Roboto Mono' }}>
+ <div>Off-chain order relay</div>
+ <div>On-chain settlement</div>
</div>
<div
className="pb2 pt2 h5 sm-center sm-px3 sm-mx-auto"
- style={{fontFamily: 'Roboto Mono', lineHeight: 1.7, fontWeight: 300, maxWidth: 445}}
+ style={{
+ fontFamily: 'Roboto Mono',
+ lineHeight: 1.7,
+ fontWeight: 300,
+ maxWidth: 445,
+ }}
>
- In 0x protocol, orders are transported off-chain, massively reducing gas
- costs and eliminating blockchain bloat. Relayers help broadcast orders and
- collect a fee each time they facilitate a trade. Anyone can build a relayer.
+ In 0x protocol, orders are transported off-chain, massively reducing gas costs and
+ eliminating blockchain bloat. Relayers help broadcast orders and collect a fee each time
+ they facilitate a trade. Anyone can build a relayer.
</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 className="flex" style={{ fontSize: 18 }}>
<div
className="lg-h4 md-h4 sm-h5"
- style={{letterSpacing: isSmallScreen ? 1 : 3, fontFamily: 'Roboto Mono'}}
+ style={{
+ letterSpacing: isSmallScreen ? 1 : 3,
+ fontFamily: 'Roboto Mono',
+ }}
>
RELAYERS BUILDING ON 0X
</div>
- <div className="h5" style={{marginLeft: isSmallScreen ? 26 : 49}}>
+ <div className="h5" style={{ marginLeft: isSmallScreen ? 26 : 49 }}>
<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>
</div>
</div>
- <div className="lg-flex md-flex sm-clearfix pt3" style={{opacity: 0.4}}>
+ <div className="lg-flex md-flex sm-clearfix pt3" style={{ opacity: 0.4 }}>
<div className="col col-4 sm-center">
- <img
- src="/images/landing/ethfinex.png"
- style={{height: isSmallScreen ? 85 : 107}}
- />
+ <img
+ src="/images/landing/ethfinex.png"
+ style={{ height: isSmallScreen ? 85 : 107 }}
+ />
</div>
- <div
- className="col col-4 center"
- >
- <img
- src="/images/landing/radar_relay.png"
- style={{height: isSmallScreen ? 85 : 107}}
- />
+ <div className="col col-4 center">
+ <img
+ src="/images/landing/radar_relay.png"
+ style={{ height: isSmallScreen ? 85 : 107 }}
+ />
</div>
- <div className="col col-4 sm-center" style={{textAlign: 'right'}}>
- <img
- src="/images/landing/paradex.png"
- style={{height: isSmallScreen ? 85 : 107}}
- />
+ <div className="col col-4 sm-center" style={{ textAlign: 'right' }}>
+ <img
+ src="/images/landing/paradex.png"
+ style={{ height: isSmallScreen ? 85 : 107 }}
+ />
</div>
</div>
</div>
@@ -468,13 +444,8 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
}
- private renderBuildingBlocksSection() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
- const underlineStyle: React.CSSProperties = {
- height: isSmallScreen ? 18 : 23,
- lineHeight: 'none',
- borderBottom: '2px solid #979797',
- };
+ private _renderBuildingBlocksSection() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const descriptionStyle: React.CSSProperties = {
fontFamily: 'Roboto Mono',
lineHeight: isSmallScreen ? 1.5 : 2,
@@ -489,86 +460,67 @@ export class Landing extends React.Component<LandingProps, LandingState> {
maxWidth: isSmallScreen ? 375 : 441,
};
return (
- <div
- className="clearfix lg-pt4 md-pt4"
- style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}}
- >
+ <div className="clearfix lg-pt4 md-pt4" style={{ backgroundColor: colors.heroGrey }}>
<div className="mx-auto max-width-4 lg-pt4 md-pt4 lg-mb4 md-mb4 sm-mb2 clearfix">
- {isSmallScreen &&
- this.renderBlockChipImage()
- }
+ {isSmallScreen && this._renderBlockChipImage()}
<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"
- style={{fontFamily: 'Roboto Mono'}}
+ style={{ fontFamily: 'Roboto Mono' }}
>
A building block for dApps
</div>
- <div
- className="pb3 pt2 sm-mx-auto sm-center"
- style={descriptionStyle}
- >
+ <div className="pb3 pt2 sm-mx-auto sm-center" style={descriptionStyle}>
0x protocol is a pluggable building block for dApps that require exchange functionality.
Join the many developers that are already using 0x in their web applications and smart
contracts.
</div>
- <div
- className="sm-mx-auto sm-center"
- style={callToActionStyle}
- >
+ <div className="sm-mx-auto sm-center" style={callToActionStyle}>
Learn how in our{' '}
<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>
- {' '}and{' '}
+ </Link>{' '}
+ and{' '}
<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>
- {' '}docs
+ </Link>{' '}
+ docs
</div>
</div>
- {!isSmallScreen &&
- this.renderBlockChipImage()
- }
+ {!isSmallScreen && this._renderBlockChipImage()}
</div>
</div>
);
}
- private renderBlockChipImage() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
+ private _renderBlockChipImage() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return (
<div className="col lg-col-6 md-col-6 col-12 sm-center">
- <img
- src="/images/landing/0x_chips.png"
- height={isSmallScreen ? 240 : 368}
- />
+ <img src="/images/landing/0x_chips.png" height={isSmallScreen ? 240 : 368} />
</div>
);
}
- private renderTokenCloud() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
+ private _renderTokenCloud() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return (
<div className="col lg-col-6 md-col-6 col-12 center">
- <img
- src="/images/landing/tokenized_world.png"
- height={isSmallScreen ? 280 : 364.5}
- />
+ <img src="/images/landing/tokenized_world.png" height={isSmallScreen ? 280 : 364.5} />
</div>
);
}
- private renderAssetTypes() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
+ private _renderAssetTypes() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const assetTypes: AssetType[] = [
{
title: 'Currency',
@@ -577,7 +529,10 @@ export class Landing extends React.Component<LandingProps, LandingState> {
{
title: 'Traditional assets',
imageUrl: '/images/landing/stocks.png',
- style: {paddingLeft: isSmallScreen ? 41 : 56, paddingRight: isSmallScreen ? 41 : 56},
+ style: {
+ paddingLeft: isSmallScreen ? 41 : 56,
+ paddingRight: isSmallScreen ? 41 : 56,
+ },
},
{
title: 'Digital goods',
@@ -587,18 +542,18 @@ export class Landing extends React.Component<LandingProps, LandingState> {
const assets = _.map(assetTypes, (assetType: AssetType) => {
const style = _.isUndefined(assetType.style) ? {} : assetType.style;
return (
- <div
- key={`asset-${assetType.title}`}
- className="center"
- style={{opacity: 0.8, ...style}}
- >
+ <div key={`asset-${assetType.title}`} className="center" style={{ opacity: 0.8, ...style }}>
<div>
- <img
- src={assetType.imageUrl}
- height="80"
- />
+ <img src={assetType.imageUrl} height="80" />
</div>
- <div style={{fontFamily: 'Roboto Mono', fontSize: 13.5, fontWeight: 400, opacity: 0.75}}>
+ <div
+ style={{
+ fontFamily: 'Roboto Mono',
+ fontSize: 13.5,
+ fontWeight: 400,
+ opacity: 0.75,
+ }}
+ >
{assetType.title}
</div>
</div>
@@ -606,83 +561,49 @@ export class Landing extends React.Component<LandingProps, LandingState> {
});
return assets;
}
- private renderLink(label: string, path: string, color: string, style?: React.CSSProperties) {
- return (
- <div
- style={{borderBottom: `1px solid ${color}`, paddingBottom: 1, height: 20, lineHeight: 1.7, ...style}}
- >
- <Link
- to={path}
- className="text-decoration-none"
- style={{color, fontFamily: 'Roboto Mono'}}
- >
- {label}
- </Link>
- </div>
- );
- }
- private renderInfoBoxes() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
+ private _renderInfoBoxes() {
+ 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',
};
const boxes = _.map(boxContents, (boxContent: BoxContent) => {
return (
- <div
- key={`box-${boxContent.title}`}
- className="col lg-col-4 md-col-4 col-12 sm-pb4"
- >
- <div
- className={`center sm-mx-auto ${!isSmallScreen && boxContent.classNames}`}
- style={boxStyle}
- >
+ <div key={`box-${boxContent.title}`} className="col lg-col-4 md-col-4 col-12 sm-pb4">
+ <div className={`center sm-mx-auto ${!isSmallScreen && boxContent.classNames}`} style={boxStyle}>
<div>
- <img src={boxContent.imageUrl} style={{height: 210}} />
+ <img src={boxContent.imageUrl} style={{ height: 210 }} />
</div>
- <div
- className="h3"
- style={{color: 'black', fontFamily: 'Roboto Mono'}}
- >
+ <div className="h3" style={{ color: 'black', fontFamily: 'Roboto Mono' }}>
{boxContent.title}
</div>
- <div
- className="pt2 pb2"
- style={{fontFamily: 'Roboto Mono', fontSize: 14}}
- >
+ <div className="pt2 pb2" style={{ fontFamily: 'Roboto Mono', fontSize: 14 }}>
{boxContent.description}
</div>
</div>
</div>
);
-
});
return (
- <div
- className="clearfix"
- style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}}
- >
- <div
- className="mx-auto py4 sm-mt2 clearfix"
- style={{maxWidth: '60em'}}
- >
+ <div className="clearfix" style={{ backgroundColor: colors.heroGrey }}>
+ <div className="mx-auto py4 sm-mt2 clearfix" style={{ maxWidth: '60em' }}>
{boxes}
</div>
</div>
);
}
- private renderUseCases() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
- const isMediumScreen = this.state.screenWidth === ScreenWidths.MD;
+ private _renderUseCases() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const useCases: UseCase[] = [
{
imageUrl: '/images/landing/governance_icon.png',
type: 'Decentralized governance',
- description: 'Decentralized organizations use tokens to represent ownership and \
+ description:
+ 'Decentralized organizations use tokens to represent ownership and \
guide their governance logic. 0x allows decentralized organizations \
to seamlessly and safely trade ownership for startup capital.',
projectIconUrls: ['/images/landing/aragon.png'],
@@ -691,7 +612,8 @@ export class Landing extends React.Component<LandingProps, LandingState> {
{
imageUrl: '/images/landing/prediction_market_icon.png',
type: 'Prediction markets',
- description: 'Decentralized prediction market platforms generate sets of tokens that \
+ description:
+ 'Decentralized prediction market platforms generate sets of tokens that \
represent a financial stake in the outcomes of real-world events. 0x allows \
these tokens to be instantly tradable.',
projectIconUrls: ['/images/landing/augur.png'],
@@ -700,7 +622,8 @@ export class Landing extends React.Component<LandingProps, LandingState> {
{
imageUrl: '/images/landing/stable_tokens_icon.png',
type: 'Stable tokens',
- description: 'Novel economic constructs such as stable coins require efficient, liquid \
+ description:
+ 'Novel economic constructs such as stable coins require efficient, liquid \
markets to succeed. 0x will facilitate the underlying economic mechanisms \
that allow these tokens to remain stable.',
projectIconUrls: ['/images/landing/maker.png'],
@@ -709,36 +632,42 @@ export class Landing extends React.Component<LandingProps, LandingState> {
{
imageUrl: '/images/landing/loans_icon.png',
type: 'Decentralized loans',
- description: 'Efficient lending requires liquid markets where investors can buy and re-sell loans. \
+ description:
+ 'Efficient lending requires liquid markets where investors can buy and re-sell loans. \
0x enables an ecosystem of lenders to self-organize and efficiently determine \
market prices for all outstanding loans.',
projectIconUrls: ['/images/landing/dharma.png', '/images/landing/lendroid.png'],
classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6',
- style: {width: 291, float: 'right', marginTop: !isSmallScreen ? 38 : 0},
+ style: {
+ width: 291,
+ float: 'right',
+ marginTop: !isSmallScreen ? 38 : 0,
+ },
},
{
imageUrl: '/images/landing/fund_management_icon.png',
type: 'Fund management',
- description: 'Decentralized fund management limits fund managers to investing in pre-agreed \
+ description:
+ 'Decentralized fund management limits fund managers to investing in pre-agreed \
upon asset classes. Embedding 0x into fund management smart contracts enables \
them to enforce these security constraints.',
projectIconUrls: ['/images/landing/melonport.png'],
classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6',
- style: {width: 291, marginTop: !isSmallScreen ? 38 : 0},
+ style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 },
},
];
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',
@@ -749,22 +678,21 @@ export class Landing extends React.Component<LandingProps, LandingState> {
key={`useCase-${useCase.type}`}
className={`col lg-col-4 md-col-4 col-12 sm-pt3 sm-px3 sm-pb3 ${useCase.classNames}`}
>
- <div
- className="relative p2 pb2 sm-mx-auto"
- style={useCaseBoxStyle}
- >
- <div
- className="absolute center"
- style={{top: -35, width: 'calc(100% - 32px)'}}
- >
- <img src={useCase.imageUrl} style={{height: 50}} />
+ <div className="relative p2 pb2 sm-mx-auto" style={useCaseBoxStyle}>
+ <div className="absolute center" style={{ top: -35, width: 'calc(100% - 32px)' }}>
+ <img src={useCase.imageUrl} style={{ height: 50 }} />
</div>
<div className="pt2 center" style={typeStyle}>
{useCase.type}
</div>
<div
className="pt2"
- style={{lineHeight: 1.5, fontSize: 14, overflow: 'hidden', height: 104}}
+ style={{
+ lineHeight: 1.5,
+ fontSize: 14,
+ overflow: 'hidden',
+ height: 104,
+ }}
>
{useCase.description}
</div>
@@ -773,21 +701,15 @@ 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}}
- >
- <div
- className="mx-auto pb4 pt3 mt1 sm-mt2 clearfix"
- style={{maxWidth: '67em'}}
- >
+ <div className="clearfix pb4 lg-pt2 md-pt2 sm-pt4" style={{ backgroundColor: colors.heroGrey }}>
+ <div className="mx-auto pb4 pt3 mt1 sm-mt2 clearfix" style={{ maxWidth: '67em' }}>
{cases}
</div>
</div>
);
}
- private renderCallToAction() {
- const isSmallScreen = this.state.screenWidth === ScreenWidths.SM;
+ private _renderCallToAction() {
+ const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const buttonLabelStyle: React.CSSProperties = {
textTransform: 'none',
fontSize: 15,
@@ -799,29 +721,29 @@ export class Landing extends React.Component<LandingProps, LandingState> {
lineHeight: '33px',
height: 49,
};
- const callToActionClassNames = 'col lg-col-8 md-col-8 col-12 lg-pr3 md-pr3 \
+ const callToActionClassNames =
+ 'col lg-col-8 md-col-8 col-12 lg-pr3 md-pr3 \
lg-right-align md-right-align sm-center sm-px3 h4';
return (
- <div
- className="clearfix pb4"
- style={{backgroundColor: CUSTOM_HERO_BACKGROUND_COLOR}}
- >
- <div
- className="mx-auto max-width-4 pb4 mb3 clearfix"
- >
+ <div className="clearfix pb4" 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>
<div className="col lg-col-4 md-col-4 col-12 sm-center sm-pt2">
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
<RaisedButton
- style={{borderRadius: 6, minWidth: 150}}
+ 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}
@@ -832,7 +754,7 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
);
}
- private updateScreenWidth() {
+ private _updateScreenWidth() {
const newScreenWidth = utils.getScreenWidth();
if (newScreenWidth !== this.state.screenWidth) {
this.setState({
diff --git a/packages/website/ts/pages/not_found.tsx b/packages/website/ts/pages/not_found.tsx
index 075bcf91e..ff277c377 100644
--- a/packages/website/ts/pages/not_found.tsx
+++ b/packages/website/ts/pages/not_found.tsx
@@ -1,9 +1,8 @@
import * as _ from 'lodash';
import * as React from 'react';
-import {Link} from 'react-router-dom';
-import {Footer} from 'ts/components/footer';
-import {TopBar} from 'ts/components/top_bar';
-import {Styles} from 'ts/types';
+import { Footer } from 'ts/components/footer';
+import { TopBar } from 'ts/components/top_bar';
+import { Styles } from 'ts/types';
export interface NotFoundProps {
location: Location;
@@ -21,15 +20,12 @@ export class NotFound extends React.Component<NotFoundProps, NotFoundState> {
public render() {
return (
<div>
- <TopBar
- blockchainIsLoaded={false}
- location={this.props.location}
- />
+ <TopBar blockchainIsLoaded={false} location={this.props.location} />
<div className="mx-auto max-width-4 py4">
<div className="center py4">
<div className="py4">
<div className="py4">
- <h1 style={{...styles.thin}}>404 Not Found</h1>
+ <h1 style={{ ...styles.thin }}>404 Not Found</h1>
<div className="py1">
<div className="py3">
Hm... looks like we couldn't find what you are looking for.
@@ -39,7 +35,7 @@ export class NotFound extends React.Component<NotFoundProps, NotFoundState> {
</div>
</div>
</div>
- <Footer location={this.props.location} />
+ <Footer />
</div>
);
}
diff --git a/packages/website/ts/pages/shared/anchor_title.tsx b/packages/website/ts/pages/shared/anchor_title.tsx
index 0a3674fd9..db5be1f59 100644
--- a/packages/website/ts/pages/shared/anchor_title.tsx
+++ b/packages/website/ts/pages/shared/anchor_title.tsx
@@ -1,16 +1,16 @@
import * as React from 'react';
-import {Link as ScrollLink} from 'react-scroll';
-import {HeaderSizes, Styles} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+import { Link as ScrollLink } from 'react-scroll';
+import { HeaderSizes, Styles } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { utils } from 'ts/utils/utils';
-const headerSizeToScrollOffset: {[headerSize: string]: number} = {
+const headerSizeToScrollOffset: { [headerSize: string]: number } = {
h2: -20,
h3: 0,
};
interface AnchorTitleProps {
- title: string|React.ReactNode;
+ title: string | React.ReactNode;
id: string;
headerSize: HeaderSizes;
shouldShowAnchor: boolean;
@@ -62,11 +62,8 @@ export class AnchorTitle extends React.Component<AnchorTitleProps, AnchorTitleSt
opacity = this.state.isHovering ? 0.6 : 1;
}
return (
- <div className="relative flex" style={{...styles[this.props.headerSize], ...styles.headers}}>
- <div
- className="inline-block"
- style={{paddingRight: 4}}
- >
+ <div className="relative flex" style={{ ...styles[this.props.headerSize], ...styles.headers }}>
+ <div className="inline-block" style={{ paddingRight: 4 }}>
{this.props.title}
</div>
<ScrollLink
@@ -78,15 +75,15 @@ export class AnchorTitle extends React.Component<AnchorTitleProps, AnchorTitleSt
<i
className="zmdi zmdi-link"
onClick={utils.setUrlHash.bind(utils, this.props.id)}
- style={{...styles.anchor, opacity}}
- onMouseOver={this.setHoverState.bind(this, true)}
- onMouseOut={this.setHoverState.bind(this, false)}
+ style={{ ...styles.anchor, opacity }}
+ onMouseOver={this._setHoverState.bind(this, true)}
+ onMouseOut={this._setHoverState.bind(this, false)}
/>
</ScrollLink>
</div>
);
}
- private setHoverState(isHovering: boolean) {
+ private _setHoverState(isHovering: boolean) {
this.setState({
isHovering,
});
diff --git a/packages/website/ts/pages/shared/markdown_code_block.tsx b/packages/website/ts/pages/shared/markdown_code_block.tsx
index 621e5b606..be96fda16 100644
--- a/packages/website/ts/pages/shared/markdown_code_block.tsx
+++ b/packages/website/ts/pages/shared/markdown_code_block.tsx
@@ -7,14 +7,19 @@ interface MarkdownCodeBlockProps {
language: string;
}
-export function MarkdownCodeBlock(props: MarkdownCodeBlockProps) {
- return (
- <span style={{fontSize: 16}}>
- <HighLight
- className={props.language || 'js'}
- >
- {props.literal}
- </HighLight>
- </span>
- );
+interface MarkdownCodeBlockState {}
+
+export class MarkdownCodeBlock extends React.Component<MarkdownCodeBlockProps, MarkdownCodeBlockState> {
+ // Re-rendering a codeblock causes any use selection to become de-selected. This is annoying when trying
+ // to copy-paste code examples. We therefore noop re-renders on this component if it's props haven't changed.
+ public shouldComponentUpdate(nextProps: MarkdownCodeBlockProps, nextState: MarkdownCodeBlockState) {
+ return nextProps.literal !== this.props.literal || nextProps.language !== this.props.language;
+ }
+ public render() {
+ return (
+ <span style={{ fontSize: 16 }}>
+ <HighLight className={this.props.language || 'javascript'}>{this.props.literal}</HighLight>
+ </span>
+ );
+ }
}
diff --git a/packages/website/ts/pages/shared/markdown_section.tsx b/packages/website/ts/pages/shared/markdown_section.tsx
index 8686e80b6..5487dc8cc 100644
--- a/packages/website/ts/pages/shared/markdown_section.tsx
+++ b/packages/website/ts/pages/shared/markdown_section.tsx
@@ -2,11 +2,11 @@ import * as _ from 'lodash';
import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
import * as ReactMarkdown from 'react-markdown';
-import {Element as ScrollElement} from 'react-scroll';
-import {AnchorTitle} from 'ts/pages/shared/anchor_title';
-import {MarkdownCodeBlock} from 'ts/pages/shared/markdown_code_block';
-import {HeaderSizes} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { Element as ScrollElement } from 'react-scroll';
+import { AnchorTitle } from 'ts/pages/shared/anchor_title';
+import { MarkdownCodeBlock } from 'ts/pages/shared/markdown_code_block';
+import { HeaderSizes } from 'ts/types';
+import { utils } from 'ts/utils/utils';
interface MarkdownSectionProps {
sectionName: string;
@@ -35,13 +35,13 @@ export class MarkdownSection extends React.Component<MarkdownSectionProps, Markd
return (
<div
className="pt2 pr3 md-pl2 sm-pl3 overflow-hidden"
- onMouseOver={this.setAnchorVisibility.bind(this, true)}
- onMouseOut={this.setAnchorVisibility.bind(this, false)}
+ onMouseOver={this._setAnchorVisibility.bind(this, true)}
+ onMouseOut={this._setAnchorVisibility.bind(this, false)}
>
<ScrollElement name={id}>
<div className="clearfix">
<div className="col lg-col-8 md-col-8 sm-col-12">
- <span style={{textTransform: 'capitalize'}}>
+ <span style={{ textTransform: 'capitalize' }}>
<AnchorTitle
headerSize={this.props.headerSize}
title={sectionName}
@@ -51,25 +51,22 @@ export class MarkdownSection extends React.Component<MarkdownSectionProps, Markd
</span>
</div>
<div className="col col-4 sm-hide xs-hide py2 right-align">
- {!_.isUndefined(this.props.githubLink) &&
+ {!_.isUndefined(this.props.githubLink) && (
<RaisedButton
href={this.props.githubLink}
target="_blank"
label="Edit on Github"
- icon={<i className="zmdi zmdi-github" style={{fontSize: 23}} />}
+ icon={<i className="zmdi zmdi-github" style={{ fontSize: 23 }} />}
/>
- }
+ )}
</div>
</div>
- <ReactMarkdown
- source={this.props.markdownContent}
- renderers={{CodeBlock: MarkdownCodeBlock}}
- />
+ <ReactMarkdown source={this.props.markdownContent} renderers={{ CodeBlock: MarkdownCodeBlock }} />
</ScrollElement>
</div>
);
}
- private setAnchorVisibility(shouldShowAnchor: boolean) {
+ private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({
shouldShowAnchor,
});
diff --git a/packages/website/ts/pages/shared/nested_sidebar_menu.tsx b/packages/website/ts/pages/shared/nested_sidebar_menu.tsx
index cbb863f3e..849c33504 100644
--- a/packages/website/ts/pages/shared/nested_sidebar_menu.tsx
+++ b/packages/website/ts/pages/shared/nested_sidebar_menu.tsx
@@ -1,16 +1,15 @@
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 {Docs, MenuSubsectionsBySection, Styles} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {typeDocUtils} from 'ts/utils/typedoc_utils';
-import {utils} from 'ts/utils/utils';
+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';
interface NestedSidebarMenuProps {
- topLevelMenu: {[topLevel: string]: string[]};
+ topLevelMenu: { [topLevel: string]: string[] };
menuSubsectionsBySection: MenuSubsectionsBySection;
shouldDisplaySectionHeaders?: boolean;
onMenuItemClick?: () => void;
@@ -45,55 +44,44 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
if (this.props.shouldDisplaySectionHeaders) {
const id = utils.getIdFromName(sectionName);
return (
- <div
- key={`section-${sectionName}`}
- className="py1"
- >
+ <div key={`section-${sectionName}`} className="py1">
<ScrollLink
to={id}
offset={-20}
duration={constants.DOCS_SCROLL_DURATION_MS}
containerId={constants.DOCS_CONTAINER_ID}
>
- <div
- style={{color: colors.grey500, cursor: 'pointer'}}
- className="pb1"
- >
+ <div style={{ color: colors.grey, cursor: 'pointer' }} className="pb1">
{finalSectionName.toUpperCase()}
</div>
</ScrollLink>
- {this.renderMenuItems(menuItems)}
+ {this._renderMenuItems(menuItems)}
</div>
);
} else {
- return (
- <div key={`section-${sectionName}`} >
- {this.renderMenuItems(menuItems)}
- </div>
- );
+ return <div key={`section-${sectionName}`}>{this._renderMenuItems(menuItems)}</div>;
}
});
return (
<div>
{!_.isUndefined(this.props.versions) &&
- !_.isUndefined(this.props.selectedVersion) &&
- !_.isUndefined(this.props.docPath) &&
- <VersionDropDown
- selectedVersion={this.props.selectedVersion}
- versions={this.props.versions}
- docPath={this.props.docPath}
- />
- }
+ !_.isUndefined(this.props.selectedVersion) &&
+ !_.isUndefined(this.props.docPath) && (
+ <VersionDropDown
+ selectedVersion={this.props.selectedVersion}
+ versions={this.props.versions}
+ docPath={this.props.docPath}
+ />
+ )}
{navigation}
</div>
);
}
- private renderMenuItems(menuItemNames: string[]): React.ReactNode[] {
- const menuItemStyles = this.props.shouldDisplaySectionHeaders ?
- styles.menuItemWithHeaders :
- styles.menuItemWithoutHeaders;
- const menuItemInnerDivStyles = this.props.shouldDisplaySectionHeaders ?
- styles.menuItemInnerDivWithHeaders : {};
+ private _renderMenuItems(menuItemNames: string[]): React.ReactNode[] {
+ const menuItemStyles = this.props.shouldDisplaySectionHeaders
+ ? styles.menuItemWithHeaders
+ : styles.menuItemWithoutHeaders;
+ const menuItemInnerDivStyles = this.props.shouldDisplaySectionHeaders ? styles.menuItemInnerDivWithHeaders : {};
const menuItems = _.map(menuItemNames, menuItemName => {
const id = utils.getIdFromName(menuItemName);
return (
@@ -106,57 +94,60 @@ export class NestedSidebarMenu extends React.Component<NestedSidebarMenuProps, N
containerId={constants.DOCS_CONTAINER_ID}
>
<MenuItem
- onTouchTap={this.onMenuItemClick.bind(this, menuItemName)}
+ onTouchTap={this._onMenuItemClick.bind(this, menuItemName)}
style={menuItemStyles}
innerDivStyle={menuItemInnerDivStyles}
>
- <span style={{textTransform: 'capitalize'}}>
- {menuItemName}
- </span>
+ <span style={{ textTransform: 'capitalize' }}>{menuItemName}</span>
</MenuItem>
</ScrollLink>
- {this.renderMenuItemSubsections(menuItemName)}
+ {this._renderMenuItemSubsections(menuItemName)}
</div>
);
});
return menuItems;
}
- private renderMenuItemSubsections(menuItemName: string): React.ReactNode {
+ private _renderMenuItemSubsections(menuItemName: string): React.ReactNode {
if (_.isUndefined(this.props.menuSubsectionsBySection[menuItemName])) {
return null;
}
- return this.renderMenuSubsectionsBySection(menuItemName, this.props.menuSubsectionsBySection[menuItemName]);
+ return this._renderMenuSubsectionsBySection(menuItemName, this.props.menuSubsectionsBySection[menuItemName]);
}
- private renderMenuSubsectionsBySection(menuItemName: string, entityNames: string[]): React.ReactNode {
+ private _renderMenuSubsectionsBySection(menuItemName: string, entityNames: string[]): React.ReactNode {
return (
- <ul style={{margin: 0, listStyleType: 'none', paddingLeft: 0}} key={menuItemName}>
- {_.map(entityNames, entityName => {
- const id = utils.getIdFromName(entityName);
- return (
- <li key={`menuItem-${entityName}`}>
- <ScrollLink
- to={id}
- offset={0}
- duration={constants.DOCS_SCROLL_DURATION_MS}
- containerId={constants.DOCS_CONTAINER_ID}
- onTouchTap={this.onMenuItemClick.bind(this, entityName)}
- >
- <MenuItem
- onTouchTap={this.onMenuItemClick.bind(this, menuItemName)}
- style={{minHeight: 35}}
- innerDivStyle={{paddingLeft: 36, fontSize: 14, lineHeight: '35px'}}
+ <ul style={{ margin: 0, listStyleType: 'none', paddingLeft: 0 }} key={menuItemName}>
+ {_.map(entityNames, entityName => {
+ const name = `${menuItemName}-${entityName}`;
+ const id = utils.getIdFromName(name);
+ return (
+ <li key={`menuItem-${entityName}`}>
+ <ScrollLink
+ to={id}
+ offset={0}
+ duration={constants.DOCS_SCROLL_DURATION_MS}
+ containerId={constants.DOCS_CONTAINER_ID}
+ onTouchTap={this._onMenuItemClick.bind(this, name)}
>
- {entityName}
- </MenuItem>
- </ScrollLink>
- </li>
- );
- })}
+ <MenuItem
+ onTouchTap={this._onMenuItemClick.bind(this, name)}
+ style={{ minHeight: 35 }}
+ innerDivStyle={{
+ paddingLeft: 36,
+ fontSize: 14,
+ lineHeight: '35px',
+ }}
+ >
+ {entityName}
+ </MenuItem>
+ </ScrollLink>
+ </li>
+ );
+ })}
</ul>
);
}
- private onMenuItemClick(menuItemName: string): void {
- const id = utils.getIdFromName(menuItemName);
+ private _onMenuItemClick(name: string): void {
+ const id = utils.getIdFromName(name);
utils.setUrlHash(id);
this.props.onMenuItemClick();
}
diff --git a/packages/website/ts/pages/shared/section_header.tsx b/packages/website/ts/pages/shared/section_header.tsx
index b5119b128..a5f5f52cf 100644
--- a/packages/website/ts/pages/shared/section_header.tsx
+++ b/packages/website/ts/pages/shared/section_header.tsx
@@ -1,8 +1,8 @@
import * as React from 'react';
-import {Element as ScrollElement} from 'react-scroll';
-import {AnchorTitle} from 'ts/pages/shared/anchor_title';
-import {HeaderSizes} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { Element as ScrollElement } from 'react-scroll';
+import { AnchorTitle } from 'ts/pages/shared/anchor_title';
+import { HeaderSizes } from 'ts/types';
+import { utils } from 'ts/utils/utils';
interface SectionHeaderProps {
sectionName: string;
@@ -28,13 +28,13 @@ export class SectionHeader extends React.Component<SectionHeaderProps, SectionHe
const id = utils.getIdFromName(sectionName);
return (
<div
- onMouseOver={this.setAnchorVisibility.bind(this, true)}
- onMouseOut={this.setAnchorVisibility.bind(this, false)}
+ onMouseOver={this._setAnchorVisibility.bind(this, true)}
+ onMouseOut={this._setAnchorVisibility.bind(this, false)}
>
<ScrollElement name={id}>
<AnchorTitle
headerSize={this.props.headerSize}
- title={<span style={{textTransform: 'capitalize'}}>{sectionName}</span>}
+ title={<span style={{ textTransform: 'capitalize' }}>{sectionName}</span>}
id={id}
shouldShowAnchor={this.state.shouldShowAnchor}
/>
@@ -42,7 +42,7 @@ export class SectionHeader extends React.Component<SectionHeaderProps, SectionHe
</div>
);
}
- private setAnchorVisibility(shouldShowAnchor: boolean) {
+ private _setAnchorVisibility(shouldShowAnchor: boolean) {
this.setState({
shouldShowAnchor,
});
diff --git a/packages/website/ts/pages/shared/version_drop_down.tsx b/packages/website/ts/pages/shared/version_drop_down.tsx
index 4af9a834f..b922e1048 100644
--- a/packages/website/ts/pages/shared/version_drop_down.tsx
+++ b/packages/website/ts/pages/shared/version_drop_down.tsx
@@ -2,8 +2,6 @@ import * as _ from 'lodash';
import DropDownMenu from 'material-ui/DropDownMenu';
import MenuItem from 'material-ui/MenuItem';
import * as React from 'react';
-import {Docs} from 'ts/types';
-import {constants} from 'ts/utils/constants';
interface VersionDropDownProps {
selectedVersion: string;
@@ -16,30 +14,24 @@ interface VersionDropDownState {}
export class VersionDropDown extends React.Component<VersionDropDownProps, VersionDropDownState> {
public render() {
return (
- <div className="mx-auto" style={{width: 120}}>
+ <div className="mx-auto" style={{ width: 120 }}>
<DropDownMenu
maxHeight={300}
value={this.props.selectedVersion}
- onChange={this.updateSelectedVersion.bind(this)}
+ onChange={this._updateSelectedVersion.bind(this)}
>
- {this.renderDropDownItems()}
+ {this._renderDropDownItems()}
</DropDownMenu>
</div>
);
}
- private renderDropDownItems() {
+ private _renderDropDownItems() {
const items = _.map(this.props.versions, version => {
- return (
- <MenuItem
- key={version}
- value={version}
- primaryText={`v${version}`}
- />
- );
+ return <MenuItem key={version} value={version} primaryText={`v${version}`} />;
});
return items;
}
- private updateSelectedVersion(e: any, index: number, value: string) {
+ private _updateSelectedVersion(e: any, index: number, value: string) {
window.location.href = `${this.props.docPath}/${value}${window.location.hash}`;
}
}
diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx
index 2447a24a2..d065614ba 100644
--- a/packages/website/ts/pages/wiki/wiki.tsx
+++ b/packages/website/ts/pages/wiki/wiki.tsx
@@ -1,19 +1,17 @@
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 {
- scroller,
-} from 'react-scroll';
-import {TopBar} from 'ts/components/top_bar';
-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 {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+import { scroller } from 'react-scroll';
+import { TopBar } from 'ts/components/top_bar';
+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';
const WIKI_NOT_READY_BACKOUT_TIMEOUT_MS = 5000;
@@ -29,13 +27,13 @@ interface WikiState {
const styles: Styles = {
mainContainers: {
position: 'absolute',
- top: 60,
+ top: 1,
left: 0,
bottom: 0,
right: 0,
overflowZ: 'hidden',
overflowY: 'scroll',
- minHeight: 'calc(100vh - 60px)',
+ minHeight: 'calc(100vh - 1px)',
WebkitOverflowScrolling: 'touch',
},
menuContainer: {
@@ -46,7 +44,7 @@ const styles: Styles = {
};
export class Wiki extends React.Component<WikiProps, WikiState> {
- private wikiBackoffTimeoutId: number;
+ private _wikiBackoffTimeoutId: number;
constructor(props: WikiProps) {
super(props);
this.state = {
@@ -55,47 +53,44 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
}
public componentWillMount() {
// tslint:disable-next-line:no-floating-promises
- this.fetchArticlesBySectionAsync();
+ this._fetchArticlesBySectionAsync();
}
public componentWillUnmount() {
- clearTimeout(this.wikiBackoffTimeoutId);
+ clearTimeout(this._wikiBackoffTimeoutId);
}
public render() {
const menuSubsectionsBySection = _.isUndefined(this.state.articlesBySection)
- ? {}
- : this.getMenuSubsectionsBySection(this.state.articlesBySection);
+ ? {}
+ : this._getMenuSubsectionsBySection(this.state.articlesBySection);
return (
<div>
- <DocumentTitle title="0x Protocol Wiki"/>
+ <DocumentTitle title="0x Protocol Wiki" />
<TopBar
blockchainIsLoaded={false}
location={this.props.location}
menuSubsectionsBySection={menuSubsectionsBySection}
shouldFullWidth={true}
/>
- {_.isUndefined(this.state.articlesBySection) ?
- <div
- className="col col-12"
- style={styles.mainContainers}
- >
+ {_.isUndefined(this.state.articlesBySection) ? (
+ <div className="col col-12" style={styles.mainContainers}>
<div
className="relative sm-px2 sm-pt2 sm-m1"
- style={{height: 122, top: '50%', transform: 'translateY(-50%)'}}
+ style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
>
<div className="center pb2">
<CircularProgress size={40} thickness={5} />
</div>
- <div className="center pt2" style={{paddingBottom: 11}}>Loading wiki...</div>
+ <div className="center pt2" style={{ paddingBottom: 11 }}>
+ Loading wiki...
+ </div>
</div>
- </div> :
- <div
- className="mx-auto flex"
- style={{color: colors.grey800, height: 43}}
- >
+ </div>
+ ) : (
+ <div className="mx-auto flex" style={{ color: colors.grey800, height: 43 }}>
<div className="relative col md-col-3 lg-col-3 lg-pl0 md-pl1 sm-hide xs-hide">
<div
className="border-right absolute pt2"
- style={{...styles.menuContainer, ...styles.mainContainers}}
+ style={{ ...styles.menuContainer, ...styles.mainContainers }}
>
<NestedSidebarMenu
topLevelMenu={menuSubsectionsBySection}
@@ -105,36 +100,30 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
</div>
</div>
<div className="relative col lg-col-9 md-col-9 sm-col-12 col-12">
- <div
- id="documentation"
- style={styles.mainContainers}
- className="absolute"
- >
+ <div id="documentation" style={styles.mainContainers} className="absolute">
<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>
- <div id="wiki">
- {this.renderWikiArticles()}
- </div>
+ <div id="wiki">{this._renderWikiArticles()}</div>
</div>
</div>
</div>
- }
+ )}
</div>
);
}
- private renderWikiArticles(): React.ReactNode {
+ private _renderWikiArticles(): React.ReactNode {
const sectionNames = _.keys(this.state.articlesBySection);
- const sections = _.map(sectionNames, sectionName => this.renderSection(sectionName));
+ const sections = _.map(sectionNames, sectionName => this._renderSection(sectionName));
return sections;
}
- private renderSection(sectionName: string) {
+ 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,12 +132,9 @@ 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}
- target="_blank"
- >
+ <a href={githubLink} target="_blank">
Edit here →
</a>
</div>
@@ -156,32 +142,33 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
);
});
return (
- <div
- key={`section-${sectionName}`}
- className="py2 pr3 md-pl2 sm-pl3"
- >
+ <div key={`section-${sectionName}`} className="py2 pr3 md-pl2 sm-pl3">
<SectionHeader sectionName={sectionName} headerSize={HeaderSizes.H1} />
{renderedArticles}
</div>
);
}
- private scrollToHash(): void {
+ private _scrollToHash(): void {
const hashWithPrefix = this.props.location.hash;
let hash = hashWithPrefix.slice(1);
if (_.isEmpty(hash)) {
hash = '0xProtocolWiki'; // scroll to the top
}
- scroller.scrollTo(hash, {duration: 0, offset: 0, containerId: 'documentation'});
+ scroller.scrollTo(hash, {
+ duration: 0,
+ offset: 0,
+ containerId: 'documentation',
+ });
}
- private async fetchArticlesBySectionAsync(): Promise<void> {
+ private async _fetchArticlesBySectionAsync(): Promise<void> {
const endpoint = `${configs.BACKEND_BASE_URL}${WebsitePaths.Wiki}`;
const response = await fetch(endpoint);
if (response.status === constants.HTTP_NO_CONTENT_STATUS_CODE) {
// We need to backoff and try fetching again later
- this.wikiBackoffTimeoutId = window.setTimeout(() => {
+ this._wikiBackoffTimeoutId = window.setTimeout(() => {
// tslint:disable-next-line:no-floating-promises
- this.fetchArticlesBySectionAsync();
+ this._fetchArticlesBySectionAsync();
}, WIKI_NOT_READY_BACKOUT_TIMEOUT_MS);
return;
}
@@ -192,15 +179,18 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
return;
}
const articlesBySection = await response.json();
- this.setState({
- articlesBySection,
- }, () => {
- this.scrollToHash();
- });
+ this.setState(
+ {
+ articlesBySection,
+ },
+ () => {
+ this._scrollToHash();
+ },
+ );
}
- private getMenuSubsectionsBySection(articlesBySection: ArticlesBySection) {
+ private _getMenuSubsectionsBySection(articlesBySection: ArticlesBySection) {
const sectionNames = _.keys(articlesBySection);
- const menuSubsectionsBySection: {[section: string]: string[]} = {};
+ const menuSubsectionsBySection: { [section: string]: string[] } = {};
for (const sectionName of sectionNames) {
const articles = articlesBySection[sectionName];
const articleNames = _.map(articles, article => article.title);
diff --git a/packages/website/ts/redux/dispatcher.ts b/packages/website/ts/redux/dispatcher.ts
index a0a1da21b..42989e5e1 100644
--- a/packages/website/ts/redux/dispatcher.ts
+++ b/packages/website/ts/redux/dispatcher.ts
@@ -1,12 +1,10 @@
-import BigNumber from 'bignumber.js';
-import {Dispatch} from 'redux';
-import {State} from 'ts/redux/reducer';
+import { BigNumber } from '@0xproject/utils';
+import { Dispatch } from 'redux';
+import { State } from 'ts/redux/reducer';
import {
ActionTypes,
AssetToken,
BlockchainErrs,
- Direction,
- Fill,
Order,
ProviderType,
ScreenWidths,
@@ -17,227 +15,221 @@ import {
} from 'ts/types';
export class Dispatcher {
- private dispatch: Dispatch<State>;
+ private _dispatch: Dispatch<State>;
constructor(dispatch: Dispatch<State>) {
- this.dispatch = dispatch;
+ this._dispatch = dispatch;
}
// Portal
public resetState() {
- this.dispatch({
- type: ActionTypes.RESET_STATE,
+ this._dispatch({
+ type: ActionTypes.ResetState,
});
}
public updateNodeVersion(nodeVersion: string) {
- this.dispatch({
+ this._dispatch({
data: nodeVersion,
- type: ActionTypes.UPDATE_NODE_VERSION,
+ type: ActionTypes.UpdateNodeVersion,
});
}
public updateScreenWidth(screenWidth: ScreenWidths) {
- this.dispatch({
+ 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,
+ this._dispatch({
+ type: ActionTypes.SwapAssetTokens,
});
}
public updateOrderSalt(salt: BigNumber) {
- this.dispatch({
+ this._dispatch({
data: salt,
- type: ActionTypes.UPDATE_ORDER_SALT,
+ type: ActionTypes.UpdateOrderSalt,
});
}
public updateUserSuppliedOrderCache(order: Order) {
- this.dispatch({
+ this._dispatch({
data: order,
- type: ActionTypes.UPDATE_USER_SUPPLIED_ORDER_CACHE,
+ type: ActionTypes.UpdateUserSuppliedOrderCache,
});
}
public updateShouldBlockchainErrDialogBeOpen(shouldBeOpen: boolean) {
- this.dispatch({
+ this._dispatch({
data: shouldBeOpen,
- type: ActionTypes.UPDATE_SHOULD_BLOCKCHAIN_ERR_DIALOG_BE_OPEN,
+ type: ActionTypes.UpdateShouldBlockchainErrDialogBeOpen,
});
}
public updateChosenAssetToken(side: Side, token: AssetToken) {
- this.dispatch({
+ this._dispatch({
data: {
side,
token,
},
- type: ActionTypes.UPDATE_CHOSEN_ASSET_TOKEN,
+ type: ActionTypes.UpdateChosenAssetToken,
});
}
public updateChosenAssetTokenAddress(side: Side, address: string) {
- this.dispatch({
+ this._dispatch({
data: {
address,
side,
},
- type: ActionTypes.UPDATE_CHOSEN_ASSET_TOKEN_ADDRESS,
+ type: ActionTypes.UpdateChosenAssetTokenAddress,
});
}
public updateOrderTakerAddress(address: string) {
- this.dispatch({
+ this._dispatch({
data: address,
- type: ActionTypes.UPDATE_ORDER_TAKER_ADDRESS,
+ type: ActionTypes.UpdateOrderTakerAddress,
});
}
public updateUserAddress(address: string) {
- this.dispatch({
+ this._dispatch({
data: address,
- type: ActionTypes.UPDATE_USER_ADDRESS,
+ type: ActionTypes.UpdateUserAddress,
});
}
public updateOrderExpiry(unixTimestampSec: BigNumber) {
- this.dispatch({
+ 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,
- });
+ this._dispatch({
+ data: err,
+ type: ActionTypes.BlockchainErrEncountered,
+ });
}
public updateBlockchainIsLoaded(isLoaded: boolean) {
- this.dispatch({
- data: isLoaded,
- type: ActionTypes.UPDATE_BLOCKCHAIN_IS_LOADED,
- });
+ this._dispatch({
+ data: isLoaded,
+ type: ActionTypes.UpdateBlockchainIsLoaded,
+ });
}
public addTokenToTokenByAddress(token: Token) {
- this.dispatch({
- data: token,
- type: ActionTypes.ADD_TOKEN_TO_TOKEN_BY_ADDRESS,
- });
+ this._dispatch({
+ data: token,
+ type: ActionTypes.AddTokenToTokenByAddress,
+ });
}
public removeTokenToTokenByAddress(token: Token) {
- this.dispatch({
- data: token,
- type: ActionTypes.REMOVE_TOKEN_TO_TOKEN_BY_ADDRESS,
- });
+ this._dispatch({
+ data: token,
+ type: ActionTypes.RemoveTokenFromTokenByAddress,
+ });
}
public clearTokenByAddress() {
- this.dispatch({
- type: ActionTypes.CLEAR_TOKEN_BY_ADDRESS,
- });
+ this._dispatch({
+ type: ActionTypes.ClearTokenByAddress,
+ });
}
public updateTokenByAddress(tokens: Token[]) {
- this.dispatch({
- data: tokens,
- type: ActionTypes.UPDATE_TOKEN_BY_ADDRESS,
- });
+ this._dispatch({
+ data: tokens,
+ type: ActionTypes.UpdateTokenByAddress,
+ });
}
public updateTokenStateByAddress(tokenStateByAddress: TokenStateByAddress) {
- this.dispatch({
- data: tokenStateByAddress,
- type: ActionTypes.UPDATE_TOKEN_STATE_BY_ADDRESS,
- });
+ this._dispatch({
+ data: tokenStateByAddress,
+ type: ActionTypes.UpdateTokenStateByAddress,
+ });
}
public removeFromTokenStateByAddress(tokenAddress: string) {
- this.dispatch({
+ this._dispatch({
data: tokenAddress,
- type: ActionTypes.REMOVE_FROM_TOKEN_STATE_BY_ADDRESS,
+ type: ActionTypes.RemoveFromTokenStateByAddress,
});
}
public replaceTokenAllowanceByAddress(address: string, allowance: BigNumber) {
- this.dispatch({
+ this._dispatch({
data: {
- address,
- allowance,
+ address,
+ allowance,
},
- type: ActionTypes.REPLACE_TOKEN_ALLOWANCE_BY_ADDRESS,
+ type: ActionTypes.ReplaceTokenAllowanceByAddress,
});
}
public replaceTokenBalanceByAddress(address: string, balance: BigNumber) {
- this.dispatch({
+ this._dispatch({
data: {
address,
balance,
},
- type: ActionTypes.REPLACE_TOKEN_BALANCE_BY_ADDRESS,
+ type: ActionTypes.ReplaceTokenBalanceByAddress,
});
}
public updateTokenBalanceByAddress(address: string, balanceDelta: BigNumber) {
- this.dispatch({
+ this._dispatch({
data: {
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,
- });
+ this._dispatch({
+ data: signatureData,
+ type: ActionTypes.UpdateOrderSignatureData,
+ });
}
public updateUserEtherBalance(balance: BigNumber) {
- this.dispatch({
- data: balance,
- type: ActionTypes.UPDATE_USER_ETHER_BALANCE,
- });
+ this._dispatch({
+ data: balance,
+ type: ActionTypes.UpdateUserEtherBalance,
+ });
}
public updateNetworkId(networkId: number) {
- this.dispatch({
- data: networkId,
- type: ActionTypes.UPDATE_NETWORK_ID,
- });
+ this._dispatch({
+ data: networkId,
+ type: ActionTypes.UpdateNetworkId,
+ });
}
public updateOrderFillAmount(amount: BigNumber) {
- this.dispatch({
+ this._dispatch({
data: amount,
- type: ActionTypes.UPDATE_ORDER_FILL_AMOUNT,
+ type: ActionTypes.UpdateOrderFillAmount,
});
}
// Docs
public updateCurrentDocsVersion(version: string) {
- this.dispatch({
+ this._dispatch({
data: version,
- type: ActionTypes.UPDATE_LIBRARY_VERSION,
+ type: ActionTypes.UpdateLibraryVersion,
});
}
public updateAvailableDocVersions(versions: string[]) {
- this.dispatch({
+ this._dispatch({
data: versions,
- type: ActionTypes.UPDATE_AVAILABLE_LIBRARY_VERSIONS,
+ type: ActionTypes.UpdateAvailableLibraryVersions,
});
}
// Shared
- public showFlashMessage(msg: string|React.ReactNode) {
- this.dispatch({
+ 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,
+ this._dispatch({
+ type: ActionTypes.HideFlashMessage,
});
}
public updateProviderType(providerType: ProviderType) {
- this.dispatch({
- type: ActionTypes.UPDATE_PROVIDER_TYPE,
+ this._dispatch({
+ type: ActionTypes.UpdateProviderType,
data: providerType,
});
}
public updateInjectedProviderName(injectedProviderName: string) {
- this.dispatch({
- type: ActionTypes.UPDATE_INJECTED_PROVIDER_NAME,
+ this._dispatch({
+ type: ActionTypes.UpdateInjectedProviderName,
data: injectedProviderName,
});
}
diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts
index da69a9d00..06ac8b670 100644
--- a/packages/website/ts/redux/reducer.ts
+++ b/packages/website/ts/redux/reducer.ts
@@ -1,12 +1,10 @@
-import {ZeroEx} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ZeroEx } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import {
Action,
ActionTypes,
BlockchainErrs,
- Direction,
- GenerateOrderSteps,
Order,
ProviderType,
ScreenWidths,
@@ -17,7 +15,7 @@ import {
TokenState,
TokenStateByAddress,
} from 'ts/types';
-import {utils} from 'ts/utils/utils';
+import { utils } from 'ts/utils/utils';
// Instead of defaulting the docs version to an empty string, we pre-populate it with
// a valid version value. This does not need to be updated however, since onLoad, it
@@ -28,7 +26,6 @@ export interface State {
// Portal
blockchainErr: BlockchainErrs;
blockchainIsLoaded: boolean;
- generateOrderStep: GenerateOrderSteps;
networkId: number;
orderExpiryTimestamp: BigNumber;
orderFillAmount: BigNumber;
@@ -51,16 +48,15 @@ export interface State {
availableDocVersions: string[];
// Shared
- flashMessage: string|React.ReactNode;
+ flashMessage: string | React.ReactNode;
providerType: ProviderType;
injectedProviderName: string;
}
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:
diff --git a/packages/website/ts/schemas/order_schema.ts b/packages/website/ts/schemas/order_schema.ts
index 61b93d273..bfbf9eb8b 100644
--- a/packages/website/ts/schemas/order_schema.ts
+++ b/packages/website/ts/schemas/order_schema.ts
@@ -1,24 +1,15 @@
export const orderSchema = {
id: '/Order',
properties: {
- maker: {$ref: '/OrderTaker'},
- taker: {$ref: '/OrderTaker'},
- salt: {type: 'string'},
- signature: {$ref: '/SignatureData'},
- expiration: {type: 'string'},
- feeRecipient: {type: 'string'},
- exchangeContract: {type: 'string'},
- networkId: {type: 'number'},
+ maker: { $ref: '/OrderTaker' },
+ taker: { $ref: '/OrderTaker' },
+ salt: { type: 'string' },
+ signature: { $ref: '/SignatureData' },
+ expiration: { type: 'string' },
+ feeRecipient: { type: 'string' },
+ exchangeContract: { type: 'string' },
+ networkId: { type: 'number' },
},
- required: [
- 'maker',
- 'taker',
- 'salt',
- 'signature',
- 'expiration',
- 'feeRecipient',
- 'exchangeContract',
- 'networkId',
- ],
+ required: ['maker', 'taker', 'salt', 'signature', 'expiration', 'feeRecipient', 'exchangeContract', 'networkId'],
type: 'object',
};
diff --git a/packages/website/ts/schemas/order_taker_schema.ts b/packages/website/ts/schemas/order_taker_schema.ts
index 6b484a60d..c784c29c5 100644
--- a/packages/website/ts/schemas/order_taker_schema.ts
+++ b/packages/website/ts/schemas/order_taker_schema.ts
@@ -1,10 +1,10 @@
export const orderTakerSchema = {
id: '/OrderTaker',
properties: {
- address: {type: 'string'},
- token: {$ref: '/Token'},
- amount: {type: 'string'},
- feeAmount: {type: 'string'},
+ address: { type: 'string' },
+ token: { $ref: '/Token' },
+ amount: { type: 'string' },
+ feeAmount: { type: 'string' },
},
required: ['address', 'token', 'amount', 'feeAmount'],
type: 'object',
diff --git a/packages/website/ts/schemas/signature_data_schema.ts b/packages/website/ts/schemas/signature_data_schema.ts
index d208cc438..8d3f15926 100644
--- a/packages/website/ts/schemas/signature_data_schema.ts
+++ b/packages/website/ts/schemas/signature_data_schema.ts
@@ -1,10 +1,10 @@
export const signatureDataSchema = {
id: '/SignatureData',
properties: {
- hash: {type: 'string'},
- r: {type: 'string'},
- s: {type: 'string'},
- v: {type: 'number'},
+ hash: { type: 'string' },
+ r: { type: 'string' },
+ s: { type: 'string' },
+ v: { type: 'number' },
},
required: ['hash', 'r', 's', 'v'],
type: 'object',
diff --git a/packages/website/ts/schemas/token_schema.ts b/packages/website/ts/schemas/token_schema.ts
index c15f57429..92b53a463 100644
--- a/packages/website/ts/schemas/token_schema.ts
+++ b/packages/website/ts/schemas/token_schema.ts
@@ -1,10 +1,10 @@
export const tokenSchema = {
id: '/Token',
properties: {
- name: {type: 'string'},
- symbol: {type: 'string'},
- decimals: {type: 'number'},
- address: {type: 'string'},
+ name: { type: 'string' },
+ symbol: { type: 'string' },
+ decimals: { type: 'number' },
+ address: { type: 'string' },
},
required: ['name', 'symbol', 'decimals', 'address'],
type: 'object',
diff --git a/packages/website/ts/schemas/validator.ts b/packages/website/ts/schemas/validator.ts
index e8eb4aaf2..5177501c6 100644
--- a/packages/website/ts/schemas/validator.ts
+++ b/packages/website/ts/schemas/validator.ts
@@ -1,19 +1,19 @@
-import {Schema as JSONSchema, Validator} from 'jsonschema';
-import {orderSchema} from 'ts/schemas/order_schema';
-import {orderTakerSchema} from 'ts/schemas/order_taker_schema';
-import {signatureDataSchema} from 'ts/schemas/signature_data_schema';
-import {tokenSchema} from 'ts/schemas/token_schema';
+import { Schema as JSONSchema, Validator } from 'jsonschema';
+import { orderSchema } from 'ts/schemas/order_schema';
+import { orderTakerSchema } from 'ts/schemas/order_taker_schema';
+import { signatureDataSchema } from 'ts/schemas/signature_data_schema';
+import { tokenSchema } from 'ts/schemas/token_schema';
export class SchemaValidator {
- private validator: Validator;
+ private _validator: Validator;
constructor() {
- this.validator = new Validator();
- this.validator.addSchema(signatureDataSchema as JSONSchema, signatureDataSchema.id);
- this.validator.addSchema(tokenSchema as JSONSchema, tokenSchema.id);
- this.validator.addSchema(orderTakerSchema as JSONSchema, orderTakerSchema.id);
- this.validator.addSchema(orderSchema as JSONSchema, orderSchema.id);
+ this._validator = new Validator();
+ this._validator.addSchema(signatureDataSchema as JSONSchema, signatureDataSchema.id);
+ this._validator.addSchema(tokenSchema as JSONSchema, tokenSchema.id);
+ this._validator.addSchema(orderTakerSchema as JSONSchema, orderTakerSchema.id);
+ this._validator.addSchema(orderSchema as JSONSchema, orderSchema.id);
}
public validate(instance: object, schema: Schema) {
- return this.validator.validate(instance, schema);
+ return this._validator.validate(instance, schema);
}
}
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index d225e7784..f873f95fa 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -1,41 +1,10 @@
-import BigNumber from 'bignumber.js';
+import { BigNumber } from '@0xproject/utils';
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 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 enum Side {
+ Receive = 'RECEIVE',
+ Deposit = 'DEPOSIT',
+}
export interface Token {
iconUrl?: string;
@@ -135,53 +104,50 @@ export enum BalanceErrs {
faucetRequestFailed,
faucetQueueIsFull,
mintingFailed,
- wethConversionFailed,
sendFailed,
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;
@@ -189,7 +155,11 @@ export interface Action {
}
export interface TrackedTokensByNetworkId {
- [networkId: number]: Token;
+ [networkId: number]: Token[];
+}
+
+export interface TrackedTokensByUserAddress {
+ [userAddress: string]: TrackedTokensByNetworkId;
}
export interface Styles {
@@ -254,44 +224,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 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 const KindString = strEnum([
- 'Constructor',
- 'Property',
- 'Method',
- 'Interface',
- 'Type alias',
- 'Variable',
- 'Function',
- 'Enumeration',
-]);
-export type KindString = keyof typeof KindString;
+export enum EtherscanLinkSuffixes {
+ Address = 'address',
+ Tx = 'tx',
+}
+
+export enum BlockchainErrs {
+ AContractNotDeployedOnNetwork = 'A_CONTRACT_NOT_DEPLOYED_ON_NETWORK',
+ DisconnectedFromEthereumNode = 'DISCONNECTED_FROM_ETHEREUM_NODE',
+ NoError = 'NO_ERROR',
+}
+
+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;
@@ -367,8 +340,8 @@ export interface DocAgnosticFormat {
export interface DocSection {
comment: string;
- constructors: Array<TypescriptMethod|SolidityMethod>;
- methods: Array<TypescriptMethod|SolidityMethod>;
+ constructors: Array<TypescriptMethod | SolidityMethod>;
+ methods: Array<TypescriptMethod | SolidityMethod>;
properties: Property[];
types: CustomType[];
events?: Event[];
@@ -395,7 +368,7 @@ export interface Property {
export interface BaseMethod {
isConstructor: boolean;
name: string;
- returnComment?: string|undefined;
+ returnComment?: string | undefined;
callPath: string;
parameters: Parameter[];
returnType: Type;
@@ -487,11 +460,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;
@@ -511,8 +483,11 @@ interface LedgerCommunication {
close_async: () => Promise<void>;
}
export interface LedgerEthConnection {
- getAddress_async: (derivationPath: string, askForDeviceConfirmation: boolean,
- shouldGetChainCode: boolean) => Promise<LedgerGetAddressResult>;
+ getAddress_async: (
+ derivationPath: string,
+ askForDeviceConfirmation: boolean,
+ shouldGetChainCode: boolean,
+ ) => Promise<LedgerGetAddressResult>;
signPersonalMessage_async: (derivationPath: string, messageHex: string) => Promise<LedgerSignResult>;
signTransaction_async: (derivationPath: string, txHex: string) => Promise<LedgerSignResult>;
comm: LedgerCommunication;
@@ -668,19 +643,39 @@ export interface SectionsMap {
}
export interface DocsInfoConfig {
- displayName: string;
- packageUrl: string;
- websitePath: string;
- docsJsonRoot: string;
- menu: DocsMenu;
- sections: SectionsMap;
- sectionNameToMarkdown: {[sectionName: string]: string};
- visibleConstructors: string[];
- convertToDocAgnosticFormatFn: (docObj: DoxityDocObj|TypeDocNode, docsInfo?: any) => DocAgnosticFormat;
- subPackageName?: string;
- publicTypes?: string[];
- sectionNameToModulePath?: {[sectionName: string]: string[]};
- menuSubsectionToVersionWhenIntroduced?: {[sectionName: string]: string};
+ displayName: string;
+ packageUrl: string;
+ websitePath: string;
+ docsJsonRoot: string;
+ menu: DocsMenu;
+ sections: SectionsMap;
+ sectionNameToMarkdown: { [sectionName: string]: string };
+ visibleConstructors: string[];
+ convertToDocAgnosticFormatFn: (docObj: DoxityDocObj | TypeDocNode, docsInfo?: any) => DocAgnosticFormat;
+ subPackageName?: string;
+ publicTypes?: string[];
+ sectionNameToModulePath?: { [sectionName: string]: string[] };
+ menuSubsectionToVersionWhenIntroduced?: { [sectionName: string]: string };
+}
+
+export interface TimestampMsRange {
+ startTimestampMs: number;
+ endTimestampMs: number;
+}
+
+export interface OutdatedWrappedEtherByNetworkId {
+ [networkId: number]: {
+ address: string;
+ timestampMsRange: TimestampMsRange;
+ };
+}
+
+export enum SmartContractDocSections {
+ Introduction = 'Introduction',
+ Exchange = 'Exchange',
+ TokenTransferProxy = 'TokenTransferProxy',
+ TokenRegistry = 'TokenRegistry',
+ ZRXToken = 'ZRXToken',
}
// tslint:disable:max-file-line-count
diff --git a/packages/website/ts/utils/colors.ts b/packages/website/ts/utils/colors.ts
new file mode 100644
index 000000000..58ce667e3
--- /dev/null
+++ b/packages/website/ts/utils/colors.ts
@@ -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',
+};
diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts
index 63fcd27b6..3d37a89ab 100644
--- a/packages/website/ts/utils/configs.ts
+++ b/packages/website/ts/utils/configs.ts
@@ -1,18 +1,126 @@
import * as _ from 'lodash';
-import {Environments} from 'ts/types';
+import {
+ ContractAddresses,
+ Environments,
+ Networks,
+ OutdatedWrappedEtherByNetworkId,
+ PublicNodeUrlsByNetworkId,
+ SmartContractDocSections,
+} from 'ts/types';
const BASE_URL = window.location.origin;
-const isDevelopment = _.includes(BASE_URL, 'https://0xproject.dev:3572') ||
- _.includes(BASE_URL, 'https://localhost:3572') ||
- _.includes(BASE_URL, 'https://127.0.0.1');
+const isDevelopment = _.includes(
+ ['https://0xproject.localhost:3572', 'https://localhost:3572', 'https://127.0.0.1'],
+ BASE_URL,
+);
+const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs';
export const configs = {
- BASE_URL,
- ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION,
BACKEND_BASE_URL: isDevelopment ? 'https://localhost:3001' : 'https://website-api.0xproject.com',
- symbolsOfMintableTokens: ['MKR', 'MLN', 'GNT', 'DGD', 'REP'],
+ BASE_URL,
+ BITLY_ACCESS_TOKEN: 'ffc4c1a31e5143848fb7c523b39f91b9b213d208',
+ CONTRACT_ADDRESS: {
+ '1.0.0': {
+ [Networks.mainnet]: {
+ [SmartContractDocSections.Exchange]: '0x12459c951127e0c374ff9105dda097662a027093',
+ [SmartContractDocSections.TokenTransferProxy]: '0x8da0d80f5007ef1e431dd2127178d224e32c2ef4',
+ [SmartContractDocSections.ZRXToken]: '0xe41d2489571d322189246dafa5ebde1f4699f498',
+ [SmartContractDocSections.TokenRegistry]: '0x926a74c5c36adf004c87399e65f75628b0f98d2c',
+ },
+ [Networks.ropsten]: {
+ [SmartContractDocSections.Exchange]: '0x479cc461fecd078f766ecc58533d6f69580cf3ac',
+ [SmartContractDocSections.TokenTransferProxy]: '0x4e9aad8184de8833365fea970cd9149372fdf1e6',
+ [SmartContractDocSections.ZRXToken]: '0xa8e9fa8f91e5ae138c74648c9c304f1c75003a8d',
+ [SmartContractDocSections.TokenRegistry]: '0x6b1a50f0bb5a7995444bd3877b22dc89c62843ed',
+ },
+ [Networks.kovan]: {
+ [SmartContractDocSections.Exchange]: '0x90fe2af704b34e0224bf2299c838e04d4dcf1364',
+ [SmartContractDocSections.TokenTransferProxy]: '0x087Eed4Bc1ee3DE49BeFbd66C662B434B15d49d4',
+ [SmartContractDocSections.ZRXToken]: '0x6ff6c0ff1d68b964901f986d4c9fa3ac68346570',
+ [SmartContractDocSections.TokenRegistry]: '0xf18e504561f4347bea557f3d4558f559dddbae7f',
+ },
+ },
+ } as ContractAddresses,
+ DEFAULT_DERIVATION_PATH: `44'/60'/0'`,
// WARNING: ZRX & WETH MUST always be default trackedTokens
- defaultTrackedTokenSymbols: ['WETH', 'ZRX'],
- lastLocalStorageFillClearanceDate: '2017-11-22',
- isMainnetEnabled: true,
+ DEFAULT_TRACKED_TOKEN_SYMBOLS: ['WETH', 'ZRX'],
+ DOMAIN_STAGING: 'staging-0xproject.s3-website-us-east-1.amazonaws.com',
+ DOMAIN_DEVELOPMENT: '0xproject.localhost:3572',
+ DOMAIN_PRODUCTION: '0xproject.com',
+ ENVIRONMENT: isDevelopment ? Environments.DEVELOPMENT : Environments.PRODUCTION,
+ ICON_URL_BY_SYMBOL: {
+ REP: '/images/token_icons/augur.png',
+ DGD: '/images/token_icons/digixdao.png',
+ WETH: '/images/token_icons/ether_erc20.png',
+ MLN: '/images/token_icons/melon.png',
+ GNT: '/images/token_icons/golem.png',
+ MKR: '/images/token_icons/makerdao.png',
+ ZRX: '/images/token_icons/zero_ex.png',
+ ANT: '/images/token_icons/aragon.png',
+ BNT: '/images/token_icons/bancor.png',
+ BAT: '/images/token_icons/basicattentiontoken.png',
+ CVC: '/images/token_icons/civic.png',
+ EOS: '/images/token_icons/eos.png',
+ FUN: '/images/token_icons/funfair.png',
+ GNO: '/images/token_icons/gnosis.png',
+ ICN: '/images/token_icons/iconomi.png',
+ OMG: '/images/token_icons/omisego.png',
+ SNT: '/images/token_icons/status.png',
+ STORJ: '/images/token_icons/storjcoinx.png',
+ PAY: '/images/token_icons/tenx.png',
+ QTUM: '/images/token_icons/qtum.png',
+ DNT: '/images/token_icons/district0x.png',
+ SNGLS: '/images/token_icons/singularity.png',
+ EDG: '/images/token_icons/edgeless.png',
+ '1ST': '/images/token_icons/firstblood.jpg',
+ WINGS: '/images/token_icons/wings.png',
+ BQX: '/images/token_icons/bitquence.png',
+ LUN: '/images/token_icons/lunyr.png',
+ RLC: '/images/token_icons/iexec.png',
+ MCO: '/images/token_icons/monaco.png',
+ ADT: '/images/token_icons/adtoken.png',
+ CFI: '/images/token_icons/cofound-it.png',
+ ROL: '/images/token_icons/etheroll.png',
+ WGNT: '/images/token_icons/golem.png',
+ MTL: '/images/token_icons/metal.png',
+ NMR: '/images/token_icons/numeraire.png',
+ SAN: '/images/token_icons/santiment.png',
+ TAAS: '/images/token_icons/taas.png',
+ TKN: '/images/token_icons/tokencard.png',
+ TRST: '/images/token_icons/trust.png',
+ } as { [symbol: string]: string },
+ IS_MAINNET_ENABLED: true,
+ LAST_LOCAL_STORAGE_FILL_CLEARANCE_DATE: '2017-11-22',
+ LAST_LOCAL_STORAGE_TRACKED_TOKEN_CLEARANCE_DATE: '2017-12-19',
+ // NEW_WRAPPED_ETHERS is temporary until we remove the SHOULD_DEPRECATE_OLD_WETH_TOKEN flag
+ // and add the new WETHs to the tokenRegistry
+ NEW_WRAPPED_ETHERS: {
+ 1: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
+ 42: '0xd0a1e359811322d97991e03f863a0c30c2cf029c',
+ } as { [networkId: string]: string },
+ OUTDATED_WRAPPED_ETHERS: [
+ {
+ 42: {
+ address: '0x05d090b51c40b020eab3bfcb6a2dff130df22e9c',
+ timestampMsRange: {
+ startTimestampMs: 1502455607000,
+ endTimestampMs: 1513790926000,
+ },
+ },
+ 1: {
+ address: '0x2956356cd2a2bf3202f771f50d3d14a367b48070',
+ timestampMsRange: {
+ startTimestampMs: 1502455607000,
+ endTimestampMs: 1513790926000,
+ },
+ },
+ },
+ ] 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}`, 'https://mainnet.0xproject.com'],
+ [42]: [`https://kovan.infura.io/${INFURA_API_KEY}`, 'https://kovan.0xproject.com'],
+ } as PublicNodeUrlsByNetworkId,
+ SHOULD_DEPRECATE_OLD_WETH_TOKEN: true,
+ SYMBOLS_OF_MINTABLE_TOKENS: ['MKR', 'MLN', 'GNT', 'DGD', 'REP'],
};
diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts
index cae59af5f..dded82114 100644
--- a/packages/website/ts/utils/constants.ts
+++ b/packages/website/ts/utils/constants.ts
@@ -1,189 +1,87 @@
-import BigNumber from 'bignumber.js';
-import {
- ContractAddresses,
- Docs,
- ExchangeContractErrs,
- 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',
-};
+import { BigNumber } from '@0xproject/utils';
+import { Networks } from 'ts/types';
export const constants = {
- ANGELLIST_URL: 'https://angel.co/0xproject/jobs',
- STAGING_DOMAIN: 'staging-0xproject.s3-website-us-east-1.amazonaws.com',
- PRODUCTION_DOMAIN: '0xproject.com',
- DEVELOPMENT_DOMAIN: '0xproject.dev:3572',
- BIGNUMBERJS_GITHUB_URL: 'http://mikemcl.github.io/bignumber.js',
- BITLY_ACCESS_TOKEN: 'ffc4c1a31e5143848fb7c523b39f91b9b213d208',
- BITLY_ENDPOINT: 'https://api-ssl.bitly.com',
- BLOG_URL: 'https://blog.0xproject.com/latest',
- CUSTOM_BLUE: '#60a4f4',
- DEFAULT_DERIVATION_PATH: `44'/60'/0'`,
- ETHER_FAUCET_ENDPOINT: 'https://faucet.0xproject.com',
- FEE_RECIPIENT_ADDRESS: '0x0000000000000000000000000000000000000000',
- FIREFOX_U2F_ADDON: 'https://addons.mozilla.org/en-US/firefox/addon/u2f-support-add-on/',
- GITHUB_URL: 'https://github.com/0xProject',
- GITHUB_WIKI_URL: 'https://github.com/0xProject/wiki',
- HTTP_NO_CONTENT_STATUS_CODE: 204,
- ACCEPT_DISCLAIMER_LOCAL_STORAGE_KEY: 'didAcceptPortalDisclaimer',
- LINKEDIN_0X_URL: 'https://www.linkedin.com/company/0x',
- LEDGER_PROVIDER_NAME: 'Ledger',
- METAMASK_PROVIDER_NAME: 'Metamask',
+ DECIMAL_PLACES_ETH: 18,
+ DECIMAL_PLACES_ZRX: 18,
+ DOCS_SCROLL_DURATION_MS: 0,
+ DOCS_CONTAINER_ID: 'documentation',
GENESIS_ORDER_BLOCK_BY_NETWORK_ID: {
1: 4145578,
42: 3117574,
50: 0,
- } as {[networkId: number]: number},
- PUBLIC_PROVIDER_NAME: '0x Public',
- // The order matters. We first try first node and only then fall back to others.
- PUBLIC_NODE_URLS_BY_NETWORK_ID: {
- [1]: [
- `https://mainnet.infura.io/${INFURA_API_KEY}`,
- ],
- [42]: [
- `https://kovan.infura.io/${INFURA_API_KEY}`,
- ],
- } as PublicNodeUrlsByNetworkId,
- PARITY_SIGNER_PROVIDER_NAME: 'Parity Signer',
- GENERIC_PROVIDER_NAME: 'Injected Web3',
+ } as { [networkId: number]: number },
+ HOME_SCROLL_DURATION_MS: 500,
+ HTTP_NO_CONTENT_STATUS_CODE: 204,
+ LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER: 'didAcceptPortalDisclaimer',
+ LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE: 'hasDismissedWethNotice',
MAKER_FEE: new BigNumber(0),
MAINNET_NAME: 'Main network',
- MAINNET_NETWORK_ID: 1,
- METAMASK_CHROME_STORE_URL: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
- // tslint:disable-next-line:max-line-length
- PARITY_CHROME_STORE_URL: 'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig',
- MIST_DOWNLOAD_URL: 'https://github.com/ethereum/mist/releases',
- NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
- ROLLBAR_ACCESS_TOKEN: 'a6619002b51c4464928201e6ea94de65',
- DOCS_SCROLL_DURATION_MS: 0,
- DOCS_CONTAINER_ID: 'documentation',
- HOME_SCROLL_DURATION_MS: 500,
- REDDIT_URL: 'https://reddit.com/r/0xproject',
- STANDARD_RELAYER_API_GITHUB: 'https://github.com/0xProject/standard-relayer-api/blob/master/README.md',
- SUCCESS_STATUS: 200,
- UNAVAILABLE_STATUS: 503,
- TAKER_FEE: new BigNumber(0),
- TESTNET_NAME: 'Kovan',
- TESTNET_NETWORK_ID: 42,
- TESTRPC_NETWORK_ID: 50,
- TWITTER_URL: 'https://twitter.com/0xproject',
- ETH_DECIMAL_PLACES: 18,
MINT_AMOUNT: new BigNumber('100000000000000000000'),
- WEB3_DOCS_URL: 'https://github.com/ethereum/wiki/wiki/JavaScript-API',
- WEB3_PROVIDER_DOCS_URL: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150',
- WEB3_DECODED_LOG_ENTRY_EVENT_URL:
- 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L123',
- WEB3_LOG_ENTRY_EVENT_URL: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L127',
- ZEROEX_CHAT_URL: 'https://chat.0xproject.com',
- // Projects
- ETHFINEX_URL: 'https://www.bitfinex.com/ethfinex',
- RADAR_RELAY_URL: 'https://radarrelay.com',
- PARADEX_URL: 'https://paradex.io',
- DYDX_URL: 'https://dydx.exchange',
- MELONPORT_URL: 'https://melonport.com',
- DISTRICT_0X_URL: 'https://district0x.io',
- DHARMA_URL: 'https://dharma.io',
- LENDROID_URL: 'https://lendroid.com',
- MAKER_URL: 'https://makerdao.com',
- ARAGON_URL: 'https://aragon.one',
- BLOCKNET_URL: 'https://blocknet.co',
- OCEAN_URL: 'http://the0cean.com',
- STATUS_URL: 'https://status.im',
- AUGUR_URL: 'https://augur.net',
- AUCTUS_URL: 'https://auctus.org',
- OPEN_ANX_URL: 'https://www.openanx.org',
-
- iconUrlBySymbol: {
- 'REP': '/images/token_icons/augur.png',
- 'DGD': '/images/token_icons/digixdao.png',
- 'WETH': '/images/token_icons/ether_erc20.png',
- 'MLN': '/images/token_icons/melon.png',
- 'GNT': '/images/token_icons/golem.png',
- 'MKR': '/images/token_icons/makerdao.png',
- 'ZRX': '/images/token_icons/zero_ex.png',
- 'ANT': '/images/token_icons/aragon.png',
- 'BNT': '/images/token_icons/bancor.png',
- 'BAT': '/images/token_icons/basicattentiontoken.png',
- 'CVC': '/images/token_icons/civic.png',
- 'EOS': '/images/token_icons/eos.png',
- 'FUN': '/images/token_icons/funfair.png',
- 'GNO': '/images/token_icons/gnosis.png',
- 'ICN': '/images/token_icons/iconomi.png',
- 'OMG': '/images/token_icons/omisego.png',
- 'SNT': '/images/token_icons/status.png',
- 'STORJ': '/images/token_icons/storjcoinx.png',
- 'PAY': '/images/token_icons/tenx.png',
- 'QTUM': '/images/token_icons/qtum.png',
- 'DNT': '/images/token_icons/district0x.png',
- 'SNGLS': '/images/token_icons/singularity.png',
- 'EDG': '/images/token_icons/edgeless.png',
- '1ST': '/images/token_icons/firstblood.jpg',
- 'WINGS': '/images/token_icons/wings.png',
- 'BQX': '/images/token_icons/bitquence.png',
- 'LUN': '/images/token_icons/lunyr.png',
- 'RLC': '/images/token_icons/iexec.png',
- 'MCO': '/images/token_icons/monaco.png',
- 'ADT': '/images/token_icons/adtoken.png',
- 'CFI': '/images/token_icons/cofound-it.png',
- 'ROL': '/images/token_icons/etheroll.png',
- 'WGNT': '/images/token_icons/golem.png',
- 'MTL': '/images/token_icons/metal.png',
- 'NMR': '/images/token_icons/numeraire.png',
- 'SAN': '/images/token_icons/santiment.png',
- 'TAAS': '/images/token_icons/taas.png',
- 'TKN': '/images/token_icons/tokencard.png',
- 'TRST': '/images/token_icons/trust.png',
- } as {[symbol: string]: string},
- networkNameById: {
+ NETWORK_ID_MAINNET: 1,
+ NETWORK_ID_TESTNET: 42,
+ NETWORK_ID_TESTRPC: 50,
+ NETWORK_NAME_BY_ID: {
1: Networks.mainnet,
3: Networks.ropsten,
4: Networks.rinkeby,
42: Networks.kovan,
- } as {[symbol: number]: string},
- networkIdByName: {
+ } as { [symbol: number]: string },
+ 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,
+ } as { [networkName: string]: number },
+ 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',
+ TYPES_SECTION_NAME: 'types',
+ 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_DISCOURSE_FORUM: 'https://forum.0xproject.com',
+ URL_FIREFOX_U2F_ADDON: 'https://addons.mozilla.org/en-US/firefox/addon/u2f-support-add-on/',
+ URL_ETHER_FAUCET: 'https://faucet.0xproject.com',
+ URL_GITHUB_ORG: 'https://github.com/0xProject',
+ URL_GITHUB_WIKI: 'https://github.com/0xProject/wiki',
+ URL_METAMASK_CHROME_STORE: 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn',
+ URL_MIST_DOWNLOAD: 'https://github.com/ethereum/mist/releases',
+ URL_PARITY_CHROME_STORE:
+ 'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig',
+ URL_REDDIT: 'https://reddit.com/r/0xproject',
+ URL_STANDARD_RELAYER_API_GITHUB: 'https://github.com/0xProject/standard-relayer-api/blob/master/README.md',
+ URL_TWITTER: 'https://twitter.com/0xproject',
+ URL_WEB3_DOCS: 'https://github.com/ethereum/wiki/wiki/JavaScript-API',
+ URL_WEB3_DECODED_LOG_ENTRY_EVENT:
+ 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L123',
+ URL_WEB3_LOG_ENTRY_EVENT: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L127',
+ URL_WEB3_PROVIDER_DOCS: 'https://github.com/0xProject/web3-typescript-typings/blob/f5bcb96/index.d.ts#L150',
+ URL_WETH_IO: 'https://weth.io/',
+ URL_ZEROEX_CHAT: 'https://chat.0xproject.com',
};
diff --git a/packages/website/ts/utils/doc_utils.ts b/packages/website/ts/utils/doc_utils.ts
index 594e3bae6..1f5f75ee2 100644
--- a/packages/website/ts/utils/doc_utils.ts
+++ b/packages/website/ts/utils/doc_utils.ts
@@ -1,13 +1,11 @@
import findVersions = require('find-versions');
import * as _ from 'lodash';
-import {DoxityDocObj, S3FileObject, TypeDocNode, VersionToFileName} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+import { DoxityDocObj, S3FileObject, TypeDocNode, VersionToFileName } from 'ts/types';
+import { utils } from 'ts/utils/utils';
import convert = require('xml-js');
export const docUtils = {
- async getVersionToFileNameAsync(s3DocJsonRoot: string):
- Promise<VersionToFileName> {
+ async getVersionToFileNameAsync(s3DocJsonRoot: string): Promise<VersionToFileName> {
const versionFileNames = await this.getVersionFileNamesAsync(s3DocJsonRoot);
const versionToFileName: VersionToFileName = {};
_.each(versionFileNames, fileName => {
@@ -22,30 +20,30 @@ export const docUtils = {
// TODO: Show the user an error message when the docs fail to load
const errMsg = await response.text();
utils.consoleLog(`Failed to load JSON file list: ${response.status} ${errMsg}`);
- return;
+ throw new Error(errMsg);
}
const responseXML = await response.text();
const responseJSONString = convert.xml2json(responseXML, {
compact: true,
});
const responseObj = JSON.parse(responseJSONString);
- const fileObjs: S3FileObject[] = (_.isArray(responseObj.ListBucketResult.Contents)) ?
- responseObj.ListBucketResult.Contents as S3FileObject[] :
- [responseObj.ListBucketResult.Contents];
+ const fileObjs: S3FileObject[] = _.isArray(responseObj.ListBucketResult.Contents)
+ ? (responseObj.ListBucketResult.Contents as S3FileObject[])
+ : [responseObj.ListBucketResult.Contents];
const versionFileNames = _.map(fileObjs, fileObj => {
return fileObj.Key._text;
});
return versionFileNames;
},
- async getJSONDocFileAsync(fileName: string, s3DocJsonRoot: string): Promise<TypeDocNode|DoxityDocObj> {
+ async getJSONDocFileAsync(fileName: string, s3DocJsonRoot: string): Promise<TypeDocNode | DoxityDocObj> {
const endpoint = `${s3DocJsonRoot}/${fileName}`;
const response = await fetch(endpoint);
if (response.status !== 200) {
// TODO: Show the user an error message when the docs fail to load
const errMsg = await response.text();
utils.consoleLog(`Failed to load Doc JSON: ${response.status} ${errMsg}`);
- return;
+ throw new Error(errMsg);
}
const jsonDocObj = await response.json();
return jsonDocObj;
diff --git a/packages/website/ts/utils/doxity_utils.ts b/packages/website/ts/utils/doxity_utils.ts
index 26e555b16..5f1d02132 100644
--- a/packages/website/ts/utils/doxity_utils.ts
+++ b/packages/website/ts/utils/doxity_utils.ts
@@ -36,41 +36,46 @@ export const doxityUtils = {
constructors.push(constructor);
}
- const doxityMethods: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>
- (doxityContractObj.abiDocs, (abiDoc: DoxityAbiDoc) => {
- return this._isMethod(abiDoc);
- });
- const methods: SolidityMethod[] = _.map<DoxityAbiDoc, SolidityMethod>(doxityMethods,
+ const doxityMethods: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>(
+ doxityContractObj.abiDocs,
+ (abiDoc: DoxityAbiDoc) => {
+ return this._isMethod(abiDoc);
+ },
+ );
+ const methods: SolidityMethod[] = _.map<DoxityAbiDoc, SolidityMethod>(
+ doxityMethods,
(doxityMethod: DoxityAbiDoc) => {
- // We assume that none of our functions returns more then a single value
- const outputIfExists = !_.isUndefined(doxityMethod.outputs) ?
- doxityMethod.outputs[0] :
- undefined;
- const returnTypeIfExists = !_.isUndefined(outputIfExists) ?
- this._convertType(outputIfExists.type) :
- undefined;
- // For ZRXToken, we want to convert it to zrxToken, rather then simply zRXToken
- const callPath = contractName !== 'ZRXToken' ?
- `${contractName[0].toLowerCase()}${contractName.slice(1)}.` :
- `${contractName.slice(0, 3).toLowerCase()}${contractName.slice(3)}.`;
- const method = {
- isConstructor: false,
- isConstant: doxityMethod.constant,
- isPayable: doxityMethod.payable,
- name: doxityMethod.name,
- comment: doxityMethod.details,
- returnComment: doxityMethod.return,
- callPath,
- parameters: this._convertParameters(doxityMethod.inputs),
- returnType: returnTypeIfExists,
- };
- return method;
- });
+ // We assume that none of our functions returns more then a single value
+ const outputIfExists = !_.isUndefined(doxityMethod.outputs) ? doxityMethod.outputs[0] : undefined;
+ const returnTypeIfExists = !_.isUndefined(outputIfExists)
+ ? this._convertType(outputIfExists.type)
+ : undefined;
+ // For ZRXToken, we want to convert it to zrxToken, rather then simply zRXToken
+ const callPath =
+ contractName !== 'ZRXToken'
+ ? `${contractName[0].toLowerCase()}${contractName.slice(1)}.`
+ : `${contractName.slice(0, 3).toLowerCase()}${contractName.slice(3)}.`;
+ const method = {
+ isConstructor: false,
+ isConstant: doxityMethod.constant,
+ isPayable: doxityMethod.payable,
+ name: doxityMethod.name,
+ comment: doxityMethod.details,
+ returnComment: doxityMethod.return,
+ callPath,
+ parameters: this._convertParameters(doxityMethod.inputs),
+ returnType: returnTypeIfExists,
+ };
+ return method;
+ },
+ );
- const doxityProperties: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>
- (doxityContractObj.abiDocs, (abiDoc: DoxityAbiDoc) => {
- return this._isProperty(abiDoc);
- });
+ const doxityProperties: DoxityAbiDoc[] = _.filter<DoxityAbiDoc>(
+ doxityContractObj.abiDocs,
+ (abiDoc: DoxityAbiDoc) => {
+ return this._isProperty(abiDoc);
+ },
+ );
const properties = _.map<DoxityAbiDoc, Property>(doxityProperties, (doxityProperty: DoxityAbiDoc) => {
// We assume that none of our functions return more then a single return value
let typeName = doxityProperty.outputs[0].type;
@@ -87,7 +92,8 @@ export const doxityUtils = {
});
const doxityEvents = _.filter(
- doxityContractObj.abiDocs, (abiDoc: DoxityAbiDoc) => abiDoc.type === AbiTypes.Event,
+ doxityContractObj.abiDocs,
+ (abiDoc: DoxityAbiDoc) => abiDoc.type === AbiTypes.Event,
);
const events = _.map(doxityEvents, doxityEvent => {
const event = {
diff --git a/packages/website/ts/utils/error_reporter.ts b/packages/website/ts/utils/error_reporter.ts
index 40991afbf..0bd247c5b 100644
--- a/packages/website/ts/utils/error_reporter.ts
+++ b/packages/website/ts/utils/error_reporter.ts
@@ -1,7 +1,7 @@
-import {Environments} from 'ts/types';
-import {configs} from 'ts/utils/configs';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+import { Environments } from 'ts/types';
+import { configs } from 'ts/utils/configs';
+import { constants } from 'ts/utils/constants';
+import { utils } from 'ts/utils/utils';
// Suggested way to include Rollbar with Webpack
// https://github.com/rollbar/rollbar.js/tree/master/examples/webpack
@@ -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',
@@ -23,7 +23,7 @@ const rollbarConfig = {
'TypeError: Failed to fetch',
'Exchange has not been deployed to detected network (network/artifact mismatch)',
// Source: https://groups.google.com/a/chromium.org/forum/#!topic/chromium-discuss/7VU0_VvC7mE
- 'undefined is not an object (evaluating \'__gCrWeb.autofill.extractForms\')',
+ "undefined is not an object (evaluating '__gCrWeb.autofill.extractForms')",
// Source: http://stackoverflow.com/questions/43399818/securityerror-from-facebook-and-cross-domain-messaging
'SecurityError (DOM Exception 18)',
],
diff --git a/packages/website/ts/utils/mui_theme.ts b/packages/website/ts/utils/mui_theme.ts
new file mode 100644
index 000000000..d73e80606
--- /dev/null
+++ b/packages/website/ts/utils/mui_theme.ts
@@ -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,
+ },
+});
diff --git a/packages/website/ts/utils/typedoc_utils.ts b/packages/website/ts/utils/typedoc_utils.ts
index 803cfa0cf..11ec8da58 100644
--- a/packages/website/ts/utils/typedoc_utils.ts
+++ b/packages/website/ts/utils/typedoc_utils.ts
@@ -1,34 +1,32 @@
import * as _ from 'lodash';
-import {DocsInfo} from 'ts/pages/documentation/docs_info';
+import { DocsInfo } from 'ts/pages/documentation/docs_info';
import {
CustomType,
CustomTypeChild,
DocAgnosticFormat,
DocSection,
- DocsMenu,
IndexSignature,
KindString,
- MenuSubsectionsBySection,
Parameter,
Property,
SectionsMap,
Type,
TypeDocNode,
TypeDocType,
- TypeDocTypes,
TypeParameter,
TypescriptMethod,
} from 'ts/types';
-import {constants} from 'ts/utils/constants';
-import {utils} from 'ts/utils/utils';
+import { utils } from 'ts/utils/utils';
export const typeDocUtils = {
isType(entity: TypeDocNode): boolean {
- return entity.kindString === KindString.Interface ||
- entity.kindString === KindString.Function ||
- entity.kindString === KindString['Type alias'] ||
- entity.kindString === KindString.Variable ||
- entity.kindString === KindString.Enumeration;
+ return (
+ entity.kindString === KindString.Interface ||
+ entity.kindString === KindString.Function ||
+ entity.kindString === KindString.TypeAlias ||
+ entity.kindString === KindString.Variable ||
+ entity.kindString === KindString.Enumeration
+ );
},
isMethod(entity: TypeDocNode): boolean {
return entity.kindString === KindString.Method;
@@ -42,8 +40,10 @@ export const typeDocUtils = {
isPrivateOrProtectedProperty(propertyName: string): boolean {
return _.startsWith(propertyName, '_');
},
- getModuleDefinitionBySectionNameIfExists(versionDocObj: TypeDocNode, modulePaths: string[]):
- TypeDocNode|undefined {
+ getModuleDefinitionBySectionNameIfExists(
+ versionDocObj: TypeDocNode,
+ modulePaths: string[],
+ ): TypeDocNode | undefined {
const modules = versionDocObj.children;
for (const mod of modules) {
if (_.includes(modulePaths, mod.name)) {
@@ -63,7 +63,8 @@ export const typeDocUtils = {
return; // no-op
}
const packageDefinitionIfExists = typeDocUtils.getModuleDefinitionBySectionNameIfExists(
- typeDocJson, modulePathsIfExists,
+ typeDocJson,
+ modulePathsIfExists,
);
if (_.isUndefined(packageDefinitionIfExists)) {
return; // no-op
@@ -103,7 +104,11 @@ export const typeDocUtils = {
case KindString.Constructor:
isConstructor = true;
const constructor = typeDocUtils._convertMethod(
- entity, isConstructor, docsInfo.sections, sectionName,
+ entity,
+ isConstructor,
+ docsInfo.sections,
+ sectionName,
+ docsInfo.subPackageName,
);
docSection.constructors.push(constructor);
break;
@@ -112,7 +117,11 @@ export const typeDocUtils = {
if (entity.flags.isPublic) {
isConstructor = false;
const method = typeDocUtils._convertMethod(
- entity, isConstructor, docsInfo.sections, sectionName,
+ entity,
+ isConstructor,
+ docsInfo.sections,
+ sectionName,
+ docsInfo.subPackageName,
);
docSection.methods.push(method);
}
@@ -120,7 +129,12 @@ export const typeDocUtils = {
case KindString.Property:
if (!typeDocUtils.isPrivateOrProtectedProperty(entity.name)) {
- const property = typeDocUtils._convertProperty(entity, docsInfo.sections, sectionName);
+ const property = typeDocUtils._convertProperty(
+ entity,
+ docsInfo.sections,
+ sectionName,
+ docsInfo.subPackageName,
+ );
docSection.properties.push(property);
}
break;
@@ -129,9 +143,14 @@ 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);
+ const customType = typeDocUtils._convertCustomType(
+ entity,
+ docsInfo.sections,
+ sectionName,
+ docsInfo.subPackageName,
+ );
docSection.types.push(customType);
}
break;
@@ -142,34 +161,40 @@ export const typeDocUtils = {
});
return docSection;
},
- _convertCustomType(entity: TypeDocNode, sections: SectionsMap, sectionName: string): CustomType {
- const typeIfExists = !_.isUndefined(entity.type) ?
- typeDocUtils._convertType(entity.type, sections, sectionName) :
- undefined;
+ _convertCustomType(
+ entity: TypeDocNode,
+ sections: SectionsMap,
+ sectionName: string,
+ subPackageName: string,
+ ): CustomType {
+ const typeIfExists = !_.isUndefined(entity.type)
+ ? typeDocUtils._convertType(entity.type, sections, sectionName, subPackageName)
+ : undefined;
const isConstructor = false;
- const methodIfExists = !_.isUndefined(entity.declaration) ?
- typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName) :
- undefined;
- const indexSignatureIfExists = !_.isUndefined(entity.indexSignature) ?
- typeDocUtils._convertIndexSignature(entity.indexSignature[0], sections, sectionName) :
- undefined;
- const commentIfExists = !_.isUndefined(entity.comment) && !_.isUndefined(entity.comment.shortText) ?
- entity.comment.shortText :
- undefined;
+ const methodIfExists = !_.isUndefined(entity.declaration)
+ ? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, subPackageName)
+ : undefined;
+ const indexSignatureIfExists = !_.isUndefined(entity.indexSignature)
+ ? typeDocUtils._convertIndexSignature(entity.indexSignature[0], sections, sectionName, subPackageName)
+ : undefined;
+ const commentIfExists =
+ !_.isUndefined(entity.comment) && !_.isUndefined(entity.comment.shortText)
+ ? entity.comment.shortText
+ : undefined;
- const childrenIfExist = !_.isUndefined(entity.children) ?
- _.map(entity.children, (child: TypeDocNode) => {
- const childTypeIfExists = !_.isUndefined(child.type) ?
- typeDocUtils._convertType(child.type, sections, sectionName) :
- undefined;
- const c: CustomTypeChild = {
- name: child.name,
- type: childTypeIfExists,
- defaultValue: child.defaultValue,
- };
- return c;
- }) :
- undefined;
+ const childrenIfExist = !_.isUndefined(entity.children)
+ ? _.map(entity.children, (child: TypeDocNode) => {
+ const childTypeIfExists = !_.isUndefined(child.type)
+ ? typeDocUtils._convertType(child.type, sections, sectionName, subPackageName)
+ : undefined;
+ const c: CustomTypeChild = {
+ name: child.name,
+ type: childTypeIfExists,
+ defaultValue: child.defaultValue,
+ };
+ return c;
+ })
+ : undefined;
const customType = {
name: entity.name,
@@ -183,21 +208,31 @@ export const typeDocUtils = {
};
return customType;
},
- _convertIndexSignature(entity: TypeDocNode, sections: SectionsMap, sectionName: string): IndexSignature {
+ _convertIndexSignature(
+ entity: TypeDocNode,
+ sections: SectionsMap,
+ sectionName: string,
+ subPackageName: string,
+ ): IndexSignature {
const key = entity.parameters[0];
const indexSignature = {
keyName: key.name,
- keyType: typeDocUtils._convertType(key.type, sections, sectionName),
+ keyType: typeDocUtils._convertType(key.type, sections, sectionName, subPackageName),
valueName: entity.type.name,
};
return indexSignature;
},
- _convertProperty(entity: TypeDocNode, sections: SectionsMap, sectionName: string): Property {
+ _convertProperty(
+ entity: TypeDocNode,
+ sections: SectionsMap,
+ sectionName: string,
+ subPackageName: string,
+ ): Property {
const source = entity.sources[0];
const commentIfExists = !_.isUndefined(entity.comment) ? entity.comment.shortText : undefined;
const property = {
name: entity.name,
- type: typeDocUtils._convertType(entity.type, sections, sectionName),
+ type: typeDocUtils._convertType(entity.type, sections, sectionName, subPackageName),
source: {
fileName: source.fileName,
line: source.line,
@@ -207,28 +242,39 @@ export const typeDocUtils = {
return property;
},
_convertMethod(
- entity: TypeDocNode, isConstructor: boolean, sections: SectionsMap, sectionName: string,
+ entity: TypeDocNode,
+ isConstructor: boolean,
+ sections: SectionsMap,
+ sectionName: string,
+ subPackageName: string,
): TypescriptMethod {
const signature = entity.signatures[0];
const source = entity.sources[0];
const hasComment = !_.isUndefined(signature.comment);
const isStatic = _.isUndefined(entity.flags.isStatic) ? false : entity.flags.isStatic;
- const topLevelInterface = isStatic ? 'ZeroEx.' : 'zeroEx.';
// HACK: we use the fact that the sectionName is the same as the property name at the top-level
// of the public interface. In the future, we shouldn't use this hack but rather get it from the JSON.
- let callPath = (!_.isUndefined(sections.zeroEx) && sectionName !== sections.zeroEx) ?
- `${topLevelInterface}${sectionName}.` :
- topLevelInterface;
- callPath = isConstructor || entity.name === '__type' ? '' : callPath;
+ let callPath;
+ if (isConstructor || entity.name === '__type') {
+ callPath = '';
+ } else if (subPackageName === '0x.js') {
+ const topLevelInterface = isStatic ? 'ZeroEx.' : 'zeroEx.';
+ callPath =
+ !_.isUndefined(sections.zeroEx) && sectionName !== sections.zeroEx
+ ? `${topLevelInterface}${sectionName}.`
+ : topLevelInterface;
+ } else {
+ callPath = `${sectionName}.`;
+ }
const parameters = _.map(signature.parameters, param => {
- return typeDocUtils._convertParameter(param, sections, sectionName);
+ return typeDocUtils._convertParameter(param, sections, sectionName, subPackageName);
});
- const returnType = typeDocUtils._convertType(signature.type, sections, sectionName);
- const typeParameter = _.isUndefined(signature.typeParameter) ?
- undefined :
- typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName);
+ const returnType = typeDocUtils._convertType(signature.type, sections, sectionName, subPackageName);
+ const typeParameter = _.isUndefined(signature.typeParameter)
+ ? undefined
+ : typeDocUtils._convertTypeParameter(signature.typeParameter[0], sections, sectionName, subPackageName);
const method = {
isConstructor,
@@ -247,15 +293,25 @@ export const typeDocUtils = {
};
return method;
},
- _convertTypeParameter(entity: TypeDocNode, sections: SectionsMap, sectionName: string): TypeParameter {
- const type = typeDocUtils._convertType(entity.type, sections, sectionName);
+ _convertTypeParameter(
+ entity: TypeDocNode,
+ sections: SectionsMap,
+ sectionName: string,
+ subPackageName: string,
+ ): TypeParameter {
+ const type = typeDocUtils._convertType(entity.type, sections, sectionName, subPackageName);
const parameter = {
name: entity.name,
type,
};
return parameter;
},
- _convertParameter(entity: TypeDocNode, sections: SectionsMap, sectionName: string): Parameter {
+ _convertParameter(
+ entity: TypeDocNode,
+ sections: SectionsMap,
+ sectionName: string,
+ subPackageName: string,
+ ): Parameter {
let comment = '<No comment>';
if (entity.comment && entity.comment.shortText) {
comment = entity.comment.shortText;
@@ -263,11 +319,9 @@ export const typeDocUtils = {
comment = entity.comment.text;
}
- const isOptional = !_.isUndefined(entity.flags.isOptional) ?
- entity.flags.isOptional :
- false;
+ const isOptional = !_.isUndefined(entity.flags.isOptional) ? entity.flags.isOptional : false;
- const type = typeDocUtils._convertType(entity.type, sections, sectionName);
+ const type = typeDocUtils._convertType(entity.type, sections, sectionName, subPackageName);
const parameter = {
name: entity.name,
@@ -277,25 +331,25 @@ export const typeDocUtils = {
};
return parameter;
},
- _convertType(entity: TypeDocType, sections: SectionsMap, sectionName: string): Type {
+ _convertType(entity: TypeDocType, sections: SectionsMap, sectionName: string, subPackageName: string): Type {
const typeArguments = _.map(entity.typeArguments, typeArgument => {
- return typeDocUtils._convertType(typeArgument, sections, sectionName);
+ return typeDocUtils._convertType(typeArgument, sections, sectionName, subPackageName);
});
const types = _.map(entity.types, t => {
- return typeDocUtils._convertType(t, sections, sectionName);
+ return typeDocUtils._convertType(t, sections, sectionName, subPackageName);
});
const isConstructor = false;
- const methodIfExists = !_.isUndefined(entity.declaration) ?
- typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName) :
- undefined;
+ const methodIfExists = !_.isUndefined(entity.declaration)
+ ? typeDocUtils._convertMethod(entity.declaration, isConstructor, sections, sectionName, subPackageName)
+ : undefined;
- const elementTypeIfExists = !_.isUndefined(entity.elementType) ?
- {
- name: entity.elementType.name,
- typeDocType: entity.elementType.type,
- } :
- undefined;
+ const elementTypeIfExists = !_.isUndefined(entity.elementType)
+ ? {
+ name: entity.elementType.name,
+ typeDocType: entity.elementType.type,
+ }
+ : undefined;
const type = {
name: entity.name,
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index 8b23b6a40..13a6d6ae2 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -1,7 +1,6 @@
-import {ExchangeContractErrs, ZeroExError} from '0x.js';
-import BigNumber from 'bignumber.js';
+import { ExchangeContractErrs, ZeroExError } from '0x.js';
+import { BigNumber } from '@0xproject/utils';
import deepEqual = require('deep-equal');
-import ethUtil = require('ethereumjs-util');
import isMobile = require('is-mobile');
import * as _ from 'lodash';
import * as moment from 'moment';
@@ -9,7 +8,6 @@ import {
EtherscanLinkSuffixes,
Networks,
Order,
- OrderParty,
ScreenWidths,
Side,
SideToAssetToken,
@@ -17,7 +15,8 @@ import {
Token,
TokenByAddress,
} from 'ts/types';
-import {constants} from 'ts/utils/constants';
+import { configs } from 'ts/utils/configs';
+import { constants } from 'ts/utils/constants';
import * as u2f from 'ts/vendor/u2f_api';
const LG_MIN_EM = 64;
@@ -59,12 +58,22 @@ export const utils = {
const formattedDate: string = m.format('h:MMa MMMM D YYYY');
return formattedDate;
},
- generateOrder(networkId: number, exchangeContract: string, sideToAssetToken: SideToAssetToken,
- 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];
+ generateOrder(
+ networkId: number,
+ exchangeContract: string,
+ sideToAssetToken: SideToAssetToken,
+ 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 order = {
maker: {
address: orderMakerAddress,
@@ -74,7 +83,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: {
@@ -85,7 +94,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(),
@@ -105,14 +114,14 @@ export const utils = {
async sleepAsync(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
},
- deepEqual(actual: any, expected: any, opts?: {strict: boolean}) {
+ deepEqual(actual: any, expected: any, opts?: { strict: boolean }) {
return deepEqual(actual, expected, opts);
},
getColSize(items: number) {
const bassCssGridSize = 12; // Source: http://basscss.com/#basscss-grid
- const colSize = 12 / items;
+ const colSize = bassCssGridSize / items;
if (!_.isInteger(colSize)) {
- throw new Error('Number of cols must be divisible by 12');
+ throw new Error(`Number of cols must be divisible by ${bassCssGridSize}`);
}
return colSize;
},
@@ -126,11 +135,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 {
@@ -138,7 +147,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;
}
@@ -149,7 +158,7 @@ export const utils = {
window.location.hash = anchorId;
},
async isU2FSupportedAsync(): Promise<boolean> {
- const w = (window as any);
+ const w = window as any;
return new Promise((resolve: (isSupported: boolean) => void) => {
if (w.u2f && !w.u2f.getApiVersion) {
// u2f object was found (Firefox with extension)
@@ -177,18 +186,19 @@ export const utils = {
const metamaskDenialErrMsg = 'User denied message';
const paritySignerDenialErrMsg = 'Request has been rejected';
const ledgerDenialErrMsg = 'Invalid status 6985';
- const isUserDeniedErrMsg = _.includes(errMsg, metamaskDenialErrMsg) ||
- _.includes(errMsg, paritySignerDenialErrMsg) ||
- _.includes(errMsg, ledgerDenialErrMsg);
+ const isUserDeniedErrMsg =
+ _.includes(errMsg, metamaskDenialErrMsg) ||
+ _.includes(errMsg, paritySignerDenialErrMsg) ||
+ _.includes(errMsg, ledgerDenialErrMsg);
return isUserDeniedErrMsg;
},
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';
@@ -207,14 +217,18 @@ export const utils = {
return true; // Since it's registered, it is the canonical token
}
const registeredTokens = _.filter(tokens, t => t.isRegistered);
- const tokenWithSameNameIfExists = _.find(registeredTokens, {name: token.name});
+ const tokenWithSameNameIfExists = _.find(registeredTokens, {
+ name: token.name,
+ });
const isUniqueName = _.isUndefined(tokenWithSameNameIfExists);
- const tokenWithSameSymbolIfExists = _.find(registeredTokens, {name: token.symbol});
+ const tokenWithSameSymbolIfExists = _.find(registeredTokens, {
+ name: token.symbol,
+ });
const isUniqueSymbol = _.isUndefined(tokenWithSameSymbolIfExists);
return isUniqueName && isUniqueSymbol;
},
- zeroExErrToHumanReadableErrMsg(error: ZeroExError|ExchangeContractErrs, takerAddress: string): string {
- const ZeroExErrorToHumanReadableError: {[error: string]: string} = {
+ zeroExErrToHumanReadableErrMsg(error: ZeroExError | ExchangeContractErrs, takerAddress: string): string {
+ const ZeroExErrorToHumanReadableError: { [error: string]: string } = {
[ZeroExError.ExchangeContractDoesNotExist]: 'Exchange contract does not exist',
[ZeroExError.EtherTokenContractDoesNotExist]: 'EtherToken contract does not exist',
[ZeroExError.TokenTransferProxyContractDoesNotExist]: 'TokenTransferProxy contract does not exist',
@@ -229,37 +243,37 @@ export const utils = {
[ZeroExError.OutOfGas]: 'Transaction ran out of gas',
[ZeroExError.NoNetworkId]: 'No network id detected',
};
- const exchangeContractErrorToHumanReadableError: {[error: string]: string} = {
+ const exchangeContractErrorToHumanReadableError: {
+ [error: string]: string;
+ } = {
[ExchangeContractErrs.OrderFillExpired]: 'This order has expired',
[ExchangeContractErrs.OrderCancelExpired]: 'This order has expired',
- [ExchangeContractErrs.OrderCancelAmountZero]: 'Order cancel amount can\'t be 0',
+ [ExchangeContractErrs.OrderCancelAmountZero]: "Order cancel amount can't be 0",
[ExchangeContractErrs.OrderAlreadyCancelledOrFilled]:
- 'This order has already been completely filled or cancelled',
- [ExchangeContractErrs.OrderFillAmountZero]: 'Order fill amount can\'t be 0',
+ 'This order has already been completely filled or cancelled',
+ [ExchangeContractErrs.OrderFillAmountZero]: "Order fill amount can't be 0",
[ExchangeContractErrs.OrderRemainingFillAmountZero]:
- 'This order has already been completely filled or cancelled',
+ 'This order has already been completely filled or cancelled',
[ExchangeContractErrs.OrderFillRoundingError]: 'Rounding error will occur when filling this order',
[ExchangeContractErrs.InsufficientTakerBalance]:
- 'Taker no longer has a sufficient balance to complete this order',
+ 'Taker no longer has a sufficient balance to complete this order',
[ExchangeContractErrs.InsufficientTakerAllowance]:
- 'Taker no longer has a sufficient allowance to complete this order',
+ 'Taker no longer has a sufficient allowance to complete this order',
[ExchangeContractErrs.InsufficientMakerBalance]:
- 'Maker no longer has a sufficient balance to complete this order',
+ 'Maker no longer has a sufficient balance to complete this order',
[ExchangeContractErrs.InsufficientMakerAllowance]:
- 'Maker no longer has a sufficient allowance to complete this order',
+ 'Maker no longer has a sufficient allowance to complete this order',
[ExchangeContractErrs.InsufficientTakerFeeBalance]: 'Taker no longer has a sufficient balance to pay fees',
[ExchangeContractErrs.InsufficientTakerFeeAllowance]:
- 'Taker no longer has a sufficient allowance to pay fees',
+ 'Taker no longer has a sufficient allowance to pay fees',
[ExchangeContractErrs.InsufficientMakerFeeBalance]: 'Maker no longer has a sufficient balance to pay fees',
[ExchangeContractErrs.InsufficientMakerFeeAllowance]:
- 'Maker no longer has a sufficient allowance to pay fees',
- [ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker]:
- `This order can only be filled by ${takerAddress}`,
- [ExchangeContractErrs.InsufficientRemainingFillAmount]:
- 'Insufficient remaining fill amount',
+ 'Maker no longer has a sufficient allowance to pay fees',
+ [ExchangeContractErrs.TransactionSenderIsNotFillOrderTaker]: `This order can only be filled by ${takerAddress}`,
+ [ExchangeContractErrs.InsufficientRemainingFillAmount]: 'Insufficient remaining fill amount',
};
- const humanReadableErrorMsg = exchangeContractErrorToHumanReadableError[error] ||
- ZeroExErrorToHumanReadableError[error];
+ const humanReadableErrorMsg =
+ exchangeContractErrorToHumanReadableError[error] || ZeroExErrorToHumanReadableError[error];
return humanReadableErrorMsg;
},
};
diff --git a/packages/website/ts/web3_wrapper.ts b/packages/website/ts/web3_wrapper.ts
index b713f8a33..415df6e8b 100644
--- a/packages/website/ts/web3_wrapper.ts
+++ b/packages/website/ts/web3_wrapper.ts
@@ -1,34 +1,38 @@
-import {promisify} from '@0xproject/utils';
-import BigNumber from 'bignumber.js';
+import { BigNumber, intervalUtils, promisify } from '@0xproject/utils';
import * as _ from 'lodash';
-import {Dispatcher} from 'ts/redux/dispatcher';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { utils } from 'ts/utils/utils';
import * as Web3 from 'web3';
export class Web3Wrapper {
- private dispatcher: Dispatcher;
- private web3: Web3;
- private prevNetworkId: number;
- private shouldPollUserAddress: boolean;
- private watchNetworkAndBalanceIntervalId: number;
- private prevUserEtherBalanceInEth: BigNumber;
- private prevUserAddress: string;
- constructor(dispatcher: Dispatcher, provider: Web3.Provider, networkIdIfExists: number,
- shouldPollUserAddress: boolean) {
- this.dispatcher = dispatcher;
- this.prevNetworkId = networkIdIfExists;
- this.shouldPollUserAddress = shouldPollUserAddress;
+ private _dispatcher: Dispatcher;
+ private _web3: Web3;
+ private _prevNetworkId: number;
+ private _shouldPollUserAddress: boolean;
+ private _watchNetworkAndBalanceIntervalId: NodeJS.Timer;
+ private _prevUserEtherBalanceInEth: BigNumber;
+ private _prevUserAddress: string;
+ constructor(
+ dispatcher: Dispatcher,
+ provider: Web3.Provider,
+ networkIdIfExists: number,
+ shouldPollUserAddress: boolean,
+ ) {
+ this._dispatcher = dispatcher;
+ this._prevNetworkId = networkIdIfExists;
+ this._shouldPollUserAddress = shouldPollUserAddress;
- this.web3 = new Web3();
- this.web3.setProvider(provider);
+ this._web3 = new Web3();
+ this._web3.setProvider(provider);
// tslint:disable-next-line:no-floating-promises
- this.startEmittingNetworkConnectionAndUserBalanceStateAsync();
+ this._startEmittingNetworkConnectionAndUserBalanceStateAsync();
}
public isAddress(address: string) {
- return this.web3.isAddress(address);
+ return this._web3.isAddress(address);
}
public async getAccountsAsync(): Promise<string[]> {
- const addresses = await promisify<string[]>(this.web3.eth.getAccounts)();
+ const addresses = await promisify<string[]>(this._web3.eth.getAccounts)();
return addresses;
}
public async getFirstAccountIfExistsAsync() {
@@ -36,112 +40,119 @@ export class Web3Wrapper {
if (_.isEmpty(addresses)) {
return '';
}
- return (addresses)[0];
+ return addresses[0];
}
public async getNodeVersionAsync(): Promise<string> {
- const nodeVersion = await promisify<string>(this.web3.version.getNode)();
+ const nodeVersion = await promisify<string>(this._web3.version.getNode)();
return nodeVersion;
}
public getProviderObj() {
- return this.web3.currentProvider;
+ return this._web3.currentProvider;
}
public async getNetworkIdIfExists() {
try {
- const networkId = await this.getNetworkAsync();
+ const networkId = await this._getNetworkAsync();
return Number(networkId);
} catch (err) {
return undefined;
}
}
public async getBalanceInEthAsync(owner: string): Promise<BigNumber> {
- const balanceInWei: BigNumber = await promisify<BigNumber>(this.web3.eth.getBalance)(owner);
- const balanceEthOldBigNumber = this.web3.fromWei(balanceInWei, 'ether');
+ const balanceInWei: BigNumber = await promisify<BigNumber>(this._web3.eth.getBalance)(owner);
+ const balanceEthOldBigNumber = this._web3.fromWei(balanceInWei, 'ether');
const balanceEth = new BigNumber(balanceEthOldBigNumber);
return balanceEth;
}
public async doesContractExistAtAddressAsync(address: string): Promise<boolean> {
- const code = await promisify<string>(this.web3.eth.getCode)(address);
+ const code = await promisify<string>(this._web3.eth.getCode)(address);
// Regex matches 0x0, 0x00, 0x in order to accomodate poorly implemented clients
const zeroHexAddressRegex = /^0[xX][0]*$/;
const didFindCode = _.isNull(code.match(zeroHexAddressRegex));
return didFindCode;
}
public async signTransactionAsync(address: string, message: string): Promise<string> {
- const signData = await promisify<string>(this.web3.eth.sign)(address, message);
+ const signData = await promisify<string>(this._web3.eth.sign)(address, message);
return signData;
}
public async getBlockTimestampAsync(blockHash: string): Promise<number> {
- const {timestamp} = await promisify<Web3.BlockWithoutTransactionData>(this.web3.eth.getBlock)(blockHash);
+ const { timestamp } = await promisify<Web3.BlockWithoutTransactionData>(this._web3.eth.getBlock)(blockHash);
return timestamp;
}
public destroy() {
- this.stopEmittingNetworkConnectionAndUserBalanceStateAsync();
+ this._stopEmittingNetworkConnectionAndUserBalanceStateAsync();
// HACK: stop() is only available on providerEngine instances
- const provider = this.web3.currentProvider;
+ const provider = this._web3.currentProvider;
if (!_.isUndefined((provider as any).stop)) {
(provider as any).stop();
}
}
// This should only be called from the LedgerConfigDialog
public updatePrevUserAddress(userAddress: string) {
- this.prevUserAddress = userAddress;
+ this._prevUserAddress = userAddress;
}
- private async getNetworkAsync() {
- const networkId = await promisify(this.web3.version.getNetwork)();
+ private async _getNetworkAsync() {
+ const networkId = await promisify(this._web3.version.getNetwork)();
return networkId;
}
- private async startEmittingNetworkConnectionAndUserBalanceStateAsync() {
- if (!_.isUndefined(this.watchNetworkAndBalanceIntervalId)) {
+ private async _startEmittingNetworkConnectionAndUserBalanceStateAsync() {
+ if (!_.isUndefined(this._watchNetworkAndBalanceIntervalId)) {
return; // we are already emitting the state
}
let prevNodeVersion: string;
- this.prevUserEtherBalanceInEth = new BigNumber(0);
- this.dispatcher.updateNetworkId(this.prevNetworkId);
- this.watchNetworkAndBalanceIntervalId = window.setInterval(async () => {
- // Check for network state changes
- const currentNetworkId = await this.getNetworkIdIfExists();
- if (currentNetworkId !== this.prevNetworkId) {
- this.prevNetworkId = currentNetworkId;
- this.dispatcher.updateNetworkId(currentNetworkId);
- }
-
- // Check for node version changes
- const currentNodeVersion = await this.getNodeVersionAsync();
- if (currentNodeVersion !== prevNodeVersion) {
- prevNodeVersion = currentNodeVersion;
- this.dispatcher.updateNodeVersion(currentNodeVersion);
- }
-
- if (this.shouldPollUserAddress) {
- const userAddressIfExists = await this.getFirstAccountIfExistsAsync();
- // Update makerAddress on network change
- if (this.prevUserAddress !== userAddressIfExists) {
- this.prevUserAddress = userAddressIfExists;
- this.dispatcher.updateUserAddress(userAddressIfExists);
+ this._prevUserEtherBalanceInEth = new BigNumber(0);
+ this._dispatcher.updateNetworkId(this._prevNetworkId);
+ this._watchNetworkAndBalanceIntervalId = intervalUtils.setAsyncExcludingInterval(
+ async () => {
+ // Check for network state changes
+ const currentNetworkId = await this.getNetworkIdIfExists();
+ if (currentNetworkId !== this._prevNetworkId) {
+ this._prevNetworkId = currentNetworkId;
+ this._dispatcher.updateNetworkId(currentNetworkId);
}
- // Check for user ether balance changes
- if (userAddressIfExists !== '') {
- await this.updateUserEtherBalanceAsync(userAddressIfExists);
+ // Check for node version changes
+ const currentNodeVersion = await this.getNodeVersionAsync();
+ if (currentNodeVersion !== prevNodeVersion) {
+ prevNodeVersion = currentNodeVersion;
+ this._dispatcher.updateNodeVersion(currentNodeVersion);
}
- } else {
- // This logic is primarily for the Ledger, since we don't regularly poll for the address
- // we simply update the balance for the last fetched address.
- if (!_.isEmpty(this.prevUserAddress)) {
- await this.updateUserEtherBalanceAsync(this.prevUserAddress);
+
+ if (this._shouldPollUserAddress) {
+ const userAddressIfExists = await this.getFirstAccountIfExistsAsync();
+ // Update makerAddress on network change
+ if (this._prevUserAddress !== userAddressIfExists) {
+ this._prevUserAddress = userAddressIfExists;
+ this._dispatcher.updateUserAddress(userAddressIfExists);
+ }
+
+ // Check for user ether balance changes
+ if (userAddressIfExists !== '') {
+ await this._updateUserEtherBalanceAsync(userAddressIfExists);
+ }
+ } else {
+ // This logic is primarily for the Ledger, since we don't regularly poll for the address
+ // we simply update the balance for the last fetched address.
+ if (!_.isEmpty(this._prevUserAddress)) {
+ await this._updateUserEtherBalanceAsync(this._prevUserAddress);
+ }
}
- }
- }, 5000);
- }
- private async updateUserEtherBalanceAsync(userAddress: string) {
+ },
+ 5000,
+ (err: Error) => {
+ utils.consoleLog(`Watching network and balances failed: ${err}`);
+ this._stopEmittingNetworkConnectionAndUserBalanceStateAsync();
+ },
+ );
+ }
+ private async _updateUserEtherBalanceAsync(userAddress: string) {
const balance = await this.getBalanceInEthAsync(userAddress);
- if (!balance.eq(this.prevUserEtherBalanceInEth)) {
- this.prevUserEtherBalanceInEth = balance;
- this.dispatcher.updateUserEtherBalance(balance);
+ if (!balance.eq(this._prevUserEtherBalanceInEth)) {
+ this._prevUserEtherBalanceInEth = balance;
+ this._dispatcher.updateUserEtherBalance(balance);
}
}
- private stopEmittingNetworkConnectionAndUserBalanceStateAsync() {
- clearInterval(this.watchNetworkAndBalanceIntervalId);
+ private _stopEmittingNetworkConnectionAndUserBalanceStateAsync() {
+ intervalUtils.clearAsyncExcludingInterval(this._watchNetworkAndBalanceIntervalId);
}
}
diff --git a/packages/website/tsconfig.json b/packages/website/tsconfig.json
index 5b3510c26..38b177d0b 100644
--- a/packages/website/tsconfig.json
+++ b/packages/website/tsconfig.json
@@ -1,21 +1,17 @@
{
+ "extends": "../../tsconfig",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"outDir": "./transpiled/",
- "sourceMap": true,
- "lib": [ "es2015", "dom" ],
- "noImplicitAny": true,
- "module": "commonjs",
- "target": "es5",
"jsx": "react",
"baseUrl": "./",
"allowJs": true,
+ "strictNullChecks": false,
+ "noImplicitThis": false,
+ "declaration": false,
"paths": {
- "*": [ "node_modules/@types/*", "*"]
+ "*": ["node_modules/@types/*", "*"]
}
},
- "include": [
- "./ts/**/*",
- "../../node_modules/web3-typescript-typings/index.d.ts"
- ]
+ "include": ["./ts/**/*", "../../node_modules/web3-typescript-typings/index.d.ts"]
}
diff --git a/packages/website/tslint.json b/packages/website/tslint.json
index 957c0e11d..d6a5f5031 100644
--- a/packages/website/tslint.json
+++ b/packages/website/tslint.json
@@ -1,11 +1,9 @@
{
- "extends": [
- "@0xproject/tslint-config"
- ],
- "rules": {
- "no-implicit-dependencies": false,
- "no-object-literal-type-assertion": false,
- "completed-docs": false,
- "prefer-function-over-method": false
- }
+ "extends": ["@0xproject/tslint-config"],
+ "rules": {
+ "no-implicit-dependencies": false,
+ "no-object-literal-type-assertion": false,
+ "completed-docs": false,
+ "prefer-function-over-method": false
+ }
}