From 7ae38906926dc09bc10670c361af0d2bf0050426 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Sat, 19 Jan 2019 18:42:04 +0800 Subject: Update dependency packages --- packages/instant/.DS_Store | Bin 8196 -> 0 bytes packages/instant/.dogfood.discharge.json | 13 - packages/instant/.env_example | 7 - packages/instant/.gitignore | 4 - packages/instant/.npmignore | 6 - packages/instant/.production.discharge.json | 13 - packages/instant/.staging.discharge.json | 13 - packages/instant/CHANGELOG.json | 29 -- packages/instant/CHANGELOG.md | 10 - packages/instant/README.md | 110 -------- packages/instant/jest.config.js | 10 - packages/instant/package.json | 104 -------- packages/instant/public/external.css | 29 -- packages/instant/public/index.html | 207 -------------- packages/instant/src/assets/icons/ae.svg | 4 - packages/instant/src/assets/icons/agi.svg | 5 - packages/instant/src/assets/icons/ant.svg | 5 - packages/instant/src/assets/icons/ast.svg | 4 - packages/instant/src/assets/icons/bat.svg | 3 - packages/instant/src/assets/icons/cvc.svg | 4 - packages/instant/src/assets/icons/dai.svg | 5 - packages/instant/src/assets/icons/dgd.svg | 5 - packages/instant/src/assets/icons/dgx.svg | 4 - packages/instant/src/assets/icons/dnt.svg | 4 - packages/instant/src/assets/icons/fun.svg | 4 - packages/instant/src/assets/icons/gno.svg | 6 - packages/instant/src/assets/icons/gnt.svg | 3 - packages/instant/src/assets/icons/knc.svg | 6 - packages/instant/src/assets/icons/link.svg | 6 - packages/instant/src/assets/icons/lpt.svg | 8 - packages/instant/src/assets/icons/mana.svg | 8 - packages/instant/src/assets/icons/mkr.svg | 4 - packages/instant/src/assets/icons/mln.svg | 4 - packages/instant/src/assets/icons/omg.svg | 3 - packages/instant/src/assets/icons/powr.svg | 6 - packages/instant/src/assets/icons/ren.svg | 12 - packages/instant/src/assets/icons/rep.svg | 7 - packages/instant/src/assets/icons/req.svg | 3 - packages/instant/src/assets/icons/salt.svg | 3 - packages/instant/src/assets/icons/snt.svg | 4 - packages/instant/src/assets/icons/spank.svg | 6 - packages/instant/src/assets/icons/wax.svg | 4 - packages/instant/src/assets/icons/zil.svg | 3 - packages/instant/src/assets/icons/zrx.svg | 6 - packages/instant/src/assets/powered_by_0x.svg | 17 -- .../instant/src/components/amount_placeholder.tsx | 34 --- .../src/components/animations/full_rotation.tsx | 21 -- .../components/animations/position_animation.tsx | 107 -------- .../instant/src/components/animations/pulse.tsx | 15 -- .../src/components/animations/slide_animation.tsx | 34 --- packages/instant/src/components/buy_button.tsx | 120 --------- .../instant/src/components/buy_order_progress.tsx | 35 --- .../src/components/buy_order_state_buttons.tsx | 75 ------ .../src/components/coinbase_wallet_logo.tsx | 23 -- packages/instant/src/components/css_reset.tsx | 32 --- .../src/components/erc20_asset_amount_input.tsx | 166 ------------ .../src/components/erc20_token_selector.tsx | 176 ------------ .../components/install_wallet_panel_content.tsx | 75 ------ .../instant/src/components/instant_heading.tsx | 149 ----------- packages/instant/src/components/meta_mask_logo.tsx | 80 ------ packages/instant/src/components/order_details.tsx | 230 ---------------- packages/instant/src/components/payment_method.tsx | 110 -------- .../src/components/payment_method_dropdown.tsx | 60 ----- .../src/components/placing_order_button.tsx | 18 -- .../src/components/scaling_amount_input.tsx | 92 ------- packages/instant/src/components/scaling_input.tsx | 165 ------------ packages/instant/src/components/search_input.tsx | 29 -- .../instant/src/components/secondary_button.tsx | 27 -- packages/instant/src/components/section_header.tsx | 21 -- packages/instant/src/components/sliding_error.tsx | 100 ------- packages/instant/src/components/sliding_panel.tsx | 73 ----- .../src/components/standard_panel_content.tsx | 75 ------ .../src/components/standard_sliding_panel.tsx | 29 -- packages/instant/src/components/time_counter.tsx | 78 ------ .../instant/src/components/timed_progress_bar.tsx | 106 -------- packages/instant/src/components/ui/button.tsx | 87 ------ packages/instant/src/components/ui/circle.tsx | 26 -- packages/instant/src/components/ui/container.tsx | 104 -------- packages/instant/src/components/ui/dropdown.tsx | 147 ---------- packages/instant/src/components/ui/flex.tsx | 38 --- packages/instant/src/components/ui/icon.tsx | 129 --------- packages/instant/src/components/ui/input.tsx | 46 ---- packages/instant/src/components/ui/overlay.tsx | 36 --- packages/instant/src/components/ui/spinner.tsx | 30 --- packages/instant/src/components/ui/text.tsx | 71 ----- packages/instant/src/components/wallet_prompt.tsx | 49 ---- .../instant/src/components/zero_ex_instant.tsx | 21 -- .../src/components/zero_ex_instant_container.tsx | 112 -------- .../src/components/zero_ex_instant_overlay.tsx | 53 ---- .../src/components/zero_ex_instant_provider.tsx | 156 ----------- packages/instant/src/constants.ts | 79 ------ .../containers/available_erc20_token_selector.ts | 45 ---- .../containers/connected_account_payment_method.ts | 94 ------- ...nected_buy_order_progress_or_payment_method.tsx | 35 --- .../containers/current_standard_sliding_panel.ts | 31 --- .../containers/latest_buy_quote_order_details.ts | 41 --- packages/instant/src/containers/latest_error.tsx | 68 ----- .../selected_asset_buy_order_progress.ts | 13 - .../selected_asset_buy_order_state_buttons.ts | 113 -------- .../containers/selected_asset_instant_heading.ts | 34 --- .../containers/selected_asset_theme_provider.ts | 32 --- .../selected_erc20_asset_amount_input.ts | 122 --------- .../instant/src/data/asset_data_network_mapping.ts | 66 ----- packages/instant/src/data/asset_meta_data_map.ts | 202 -------------- packages/instant/src/globals.d.ts | 12 - packages/instant/src/index.ts | 2 - packages/instant/src/index.umd.ts | 169 ------------ packages/instant/src/redux/actions.ts | 76 ------ packages/instant/src/redux/analytics_middleware.ts | 108 -------- packages/instant/src/redux/async_data.ts | 120 --------- packages/instant/src/redux/reducer.ts | 297 --------------------- packages/instant/src/redux/store.ts | 15 -- packages/instant/src/style/fonts.ts | 10 - packages/instant/src/style/media.ts | 51 ---- packages/instant/src/style/theme.ts | 56 ---- packages/instant/src/style/util.ts | 11 - packages/instant/src/style/z_index.ts | 9 - packages/instant/src/types.ts | 206 -------------- packages/instant/src/util/address.ts | 6 - packages/instant/src/util/analytics.ts | 248 ----------------- packages/instant/src/util/assert.ts | 55 ---- packages/instant/src/util/asset.ts | 146 ---------- packages/instant/src/util/asset_buyer_factory.ts | 17 -- packages/instant/src/util/buy_quote_updater.ts | 61 ----- packages/instant/src/util/coinbase_api.ts | 11 - packages/instant/src/util/env.ts | 77 ------ packages/instant/src/util/error_flasher.ts | 26 -- packages/instant/src/util/error_reporter.ts | 79 ------ packages/instant/src/util/etherscan.ts | 30 --- packages/instant/src/util/format.ts | 76 ------ packages/instant/src/util/gas_price_estimator.ts | 65 ----- packages/instant/src/util/heap.ts | 116 -------- packages/instant/src/util/heartbeater.ts | 35 --- packages/instant/src/util/heartbeater_factory.ts | 30 --- packages/instant/src/util/maybe_big_number.ts | 25 -- packages/instant/src/util/provider_factory.ts | 34 --- .../instant/src/util/provider_state_factory.ts | 90 ------- packages/instant/src/util/time.ts | 39 --- packages/instant/src/util/util.ts | 6 - .../test/components/zero_ex_instant.test.tsx | 15 -- packages/instant/test/util/asset.test.ts | 114 -------- packages/instant/test/util/format.test.ts | 117 -------- packages/instant/test/util/time.test.ts | 48 ---- packages/instant/tsconfig.json | 14 - packages/instant/tslint.json | 9 - packages/instant/typedoc-tsconfig.json | 7 - packages/instant/webpack.config.js | 176 ------------ 147 files changed, 8070 deletions(-) delete mode 100644 packages/instant/.DS_Store delete mode 100644 packages/instant/.dogfood.discharge.json delete mode 100644 packages/instant/.env_example delete mode 100644 packages/instant/.gitignore delete mode 100644 packages/instant/.npmignore delete mode 100644 packages/instant/.production.discharge.json delete mode 100644 packages/instant/.staging.discharge.json delete mode 100644 packages/instant/CHANGELOG.json delete mode 100644 packages/instant/CHANGELOG.md delete mode 100644 packages/instant/README.md delete mode 100644 packages/instant/jest.config.js delete mode 100644 packages/instant/package.json delete mode 100644 packages/instant/public/external.css delete mode 100644 packages/instant/public/index.html delete mode 100644 packages/instant/src/assets/icons/ae.svg delete mode 100644 packages/instant/src/assets/icons/agi.svg delete mode 100644 packages/instant/src/assets/icons/ant.svg delete mode 100644 packages/instant/src/assets/icons/ast.svg delete mode 100644 packages/instant/src/assets/icons/bat.svg delete mode 100644 packages/instant/src/assets/icons/cvc.svg delete mode 100644 packages/instant/src/assets/icons/dai.svg delete mode 100644 packages/instant/src/assets/icons/dgd.svg delete mode 100644 packages/instant/src/assets/icons/dgx.svg delete mode 100644 packages/instant/src/assets/icons/dnt.svg delete mode 100644 packages/instant/src/assets/icons/fun.svg delete mode 100644 packages/instant/src/assets/icons/gno.svg delete mode 100644 packages/instant/src/assets/icons/gnt.svg delete mode 100644 packages/instant/src/assets/icons/knc.svg delete mode 100644 packages/instant/src/assets/icons/link.svg delete mode 100644 packages/instant/src/assets/icons/lpt.svg delete mode 100644 packages/instant/src/assets/icons/mana.svg delete mode 100644 packages/instant/src/assets/icons/mkr.svg delete mode 100644 packages/instant/src/assets/icons/mln.svg delete mode 100644 packages/instant/src/assets/icons/omg.svg delete mode 100644 packages/instant/src/assets/icons/powr.svg delete mode 100644 packages/instant/src/assets/icons/ren.svg delete mode 100644 packages/instant/src/assets/icons/rep.svg delete mode 100644 packages/instant/src/assets/icons/req.svg delete mode 100644 packages/instant/src/assets/icons/salt.svg delete mode 100644 packages/instant/src/assets/icons/snt.svg delete mode 100644 packages/instant/src/assets/icons/spank.svg delete mode 100644 packages/instant/src/assets/icons/wax.svg delete mode 100644 packages/instant/src/assets/icons/zil.svg delete mode 100644 packages/instant/src/assets/icons/zrx.svg delete mode 100644 packages/instant/src/assets/powered_by_0x.svg delete mode 100644 packages/instant/src/components/amount_placeholder.tsx delete mode 100644 packages/instant/src/components/animations/full_rotation.tsx delete mode 100644 packages/instant/src/components/animations/position_animation.tsx delete mode 100644 packages/instant/src/components/animations/pulse.tsx delete mode 100644 packages/instant/src/components/animations/slide_animation.tsx delete mode 100644 packages/instant/src/components/buy_button.tsx delete mode 100644 packages/instant/src/components/buy_order_progress.tsx delete mode 100644 packages/instant/src/components/buy_order_state_buttons.tsx delete mode 100644 packages/instant/src/components/coinbase_wallet_logo.tsx delete mode 100644 packages/instant/src/components/css_reset.tsx delete mode 100644 packages/instant/src/components/erc20_asset_amount_input.tsx delete mode 100644 packages/instant/src/components/erc20_token_selector.tsx delete mode 100644 packages/instant/src/components/install_wallet_panel_content.tsx delete mode 100644 packages/instant/src/components/instant_heading.tsx delete mode 100644 packages/instant/src/components/meta_mask_logo.tsx delete mode 100644 packages/instant/src/components/order_details.tsx delete mode 100644 packages/instant/src/components/payment_method.tsx delete mode 100644 packages/instant/src/components/payment_method_dropdown.tsx delete mode 100644 packages/instant/src/components/placing_order_button.tsx delete mode 100644 packages/instant/src/components/scaling_amount_input.tsx delete mode 100644 packages/instant/src/components/scaling_input.tsx delete mode 100644 packages/instant/src/components/search_input.tsx delete mode 100644 packages/instant/src/components/secondary_button.tsx delete mode 100644 packages/instant/src/components/section_header.tsx delete mode 100644 packages/instant/src/components/sliding_error.tsx delete mode 100644 packages/instant/src/components/sliding_panel.tsx delete mode 100644 packages/instant/src/components/standard_panel_content.tsx delete mode 100644 packages/instant/src/components/standard_sliding_panel.tsx delete mode 100644 packages/instant/src/components/time_counter.tsx delete mode 100644 packages/instant/src/components/timed_progress_bar.tsx delete mode 100644 packages/instant/src/components/ui/button.tsx delete mode 100644 packages/instant/src/components/ui/circle.tsx delete mode 100644 packages/instant/src/components/ui/container.tsx delete mode 100644 packages/instant/src/components/ui/dropdown.tsx delete mode 100644 packages/instant/src/components/ui/flex.tsx delete mode 100644 packages/instant/src/components/ui/icon.tsx delete mode 100644 packages/instant/src/components/ui/input.tsx delete mode 100644 packages/instant/src/components/ui/overlay.tsx delete mode 100644 packages/instant/src/components/ui/spinner.tsx delete mode 100644 packages/instant/src/components/ui/text.tsx delete mode 100644 packages/instant/src/components/wallet_prompt.tsx delete mode 100644 packages/instant/src/components/zero_ex_instant.tsx delete mode 100644 packages/instant/src/components/zero_ex_instant_container.tsx delete mode 100644 packages/instant/src/components/zero_ex_instant_overlay.tsx delete mode 100644 packages/instant/src/components/zero_ex_instant_provider.tsx delete mode 100644 packages/instant/src/constants.ts delete mode 100644 packages/instant/src/containers/available_erc20_token_selector.ts delete mode 100644 packages/instant/src/containers/connected_account_payment_method.ts delete mode 100644 packages/instant/src/containers/connected_buy_order_progress_or_payment_method.tsx delete mode 100644 packages/instant/src/containers/current_standard_sliding_panel.ts delete mode 100644 packages/instant/src/containers/latest_buy_quote_order_details.ts delete mode 100644 packages/instant/src/containers/latest_error.tsx delete mode 100644 packages/instant/src/containers/selected_asset_buy_order_progress.ts delete mode 100644 packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts delete mode 100644 packages/instant/src/containers/selected_asset_instant_heading.ts delete mode 100644 packages/instant/src/containers/selected_asset_theme_provider.ts delete mode 100644 packages/instant/src/containers/selected_erc20_asset_amount_input.ts delete mode 100644 packages/instant/src/data/asset_data_network_mapping.ts delete mode 100644 packages/instant/src/data/asset_meta_data_map.ts delete mode 100644 packages/instant/src/globals.d.ts delete mode 100644 packages/instant/src/index.ts delete mode 100644 packages/instant/src/index.umd.ts delete mode 100644 packages/instant/src/redux/actions.ts delete mode 100644 packages/instant/src/redux/analytics_middleware.ts delete mode 100644 packages/instant/src/redux/async_data.ts delete mode 100644 packages/instant/src/redux/reducer.ts delete mode 100644 packages/instant/src/redux/store.ts delete mode 100644 packages/instant/src/style/fonts.ts delete mode 100644 packages/instant/src/style/media.ts delete mode 100644 packages/instant/src/style/theme.ts delete mode 100644 packages/instant/src/style/util.ts delete mode 100644 packages/instant/src/style/z_index.ts delete mode 100644 packages/instant/src/types.ts delete mode 100644 packages/instant/src/util/address.ts delete mode 100644 packages/instant/src/util/analytics.ts delete mode 100644 packages/instant/src/util/assert.ts delete mode 100644 packages/instant/src/util/asset.ts delete mode 100644 packages/instant/src/util/asset_buyer_factory.ts delete mode 100644 packages/instant/src/util/buy_quote_updater.ts delete mode 100644 packages/instant/src/util/coinbase_api.ts delete mode 100644 packages/instant/src/util/env.ts delete mode 100644 packages/instant/src/util/error_flasher.ts delete mode 100644 packages/instant/src/util/error_reporter.ts delete mode 100644 packages/instant/src/util/etherscan.ts delete mode 100644 packages/instant/src/util/format.ts delete mode 100644 packages/instant/src/util/gas_price_estimator.ts delete mode 100644 packages/instant/src/util/heap.ts delete mode 100644 packages/instant/src/util/heartbeater.ts delete mode 100644 packages/instant/src/util/heartbeater_factory.ts delete mode 100644 packages/instant/src/util/maybe_big_number.ts delete mode 100644 packages/instant/src/util/provider_factory.ts delete mode 100644 packages/instant/src/util/provider_state_factory.ts delete mode 100644 packages/instant/src/util/time.ts delete mode 100644 packages/instant/src/util/util.ts delete mode 100644 packages/instant/test/components/zero_ex_instant.test.tsx delete mode 100644 packages/instant/test/util/asset.test.ts delete mode 100644 packages/instant/test/util/format.test.ts delete mode 100644 packages/instant/test/util/time.test.ts delete mode 100644 packages/instant/tsconfig.json delete mode 100644 packages/instant/tslint.json delete mode 100644 packages/instant/typedoc-tsconfig.json delete mode 100644 packages/instant/webpack.config.js (limited to 'packages/instant') diff --git a/packages/instant/.DS_Store b/packages/instant/.DS_Store deleted file mode 100644 index c86c5cbcd..000000000 Binary files a/packages/instant/.DS_Store and /dev/null differ diff --git a/packages/instant/.dogfood.discharge.json b/packages/instant/.dogfood.discharge.json deleted file mode 100644 index 651b3daa6..000000000 --- a/packages/instant/.dogfood.discharge.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "domain": "0x-instant-dogfood", - "build_command": "WEBPACK_OUTPUT_PATH=public dotenv yarn build -- --env.discharge_target=dogfood", - "upload_directory": "public", - "index_key": "index.html", - "error_key": "index.html", - "trailing_slashes": true, - "cache": 3600, - "aws_profile": "0xproject", - "aws_region": "us-east-1", - "cdn": false, - "dns_configured": true -} diff --git a/packages/instant/.env_example b/packages/instant/.env_example deleted file mode 100644 index 234e64bbe..000000000 --- a/packages/instant/.env_example +++ /dev/null @@ -1,7 +0,0 @@ -INSTANT_ROLLBAR_PUBLISH_TOKEN= -INSTANT_ROLLBAR_CLIENT_TOKEN= -INSTANT_HEAP_ANALYTICS_ID_PRODUCTION= -INSTANT_HEAP_ANALYTICS_ID_DEVELOPMENT= -# if you want to report to heap or rollbar when building in development mode, you can use the following: -# INSTANT_HEAP_FORCE_DEVELOPMENT=true -# INSTANT_ROLLBAR_FORCE_DEVELOPMENT=true \ No newline at end of file diff --git a/packages/instant/.gitignore b/packages/instant/.gitignore deleted file mode 100644 index 2e65f192d..000000000 --- a/packages/instant/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -public/instant.js -public/instant.js.map -umd/* -.env \ No newline at end of file diff --git a/packages/instant/.npmignore b/packages/instant/.npmignore deleted file mode 100644 index 563923652..000000000 --- a/packages/instant/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -.* -* -*/ -!lib/**/* -!umd/**/* -.env \ No newline at end of file diff --git a/packages/instant/.production.discharge.json b/packages/instant/.production.discharge.json deleted file mode 100644 index c87f8b187..000000000 --- a/packages/instant/.production.discharge.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "domain": "instant.0x.org", - "build_command": "dotenv yarn build -- --env.discharge_target=production", - "upload_directory": "umd", - "index_key": "instant.js", - "error_key": "404.html", - "trailing_slashes": true, - "cache": 3600, - "aws_profile": "0xproject", - "aws_region": "us-east-1", - "cdn": true, - "dns_configured": true -} diff --git a/packages/instant/.staging.discharge.json b/packages/instant/.staging.discharge.json deleted file mode 100644 index 844e3ca4e..000000000 --- a/packages/instant/.staging.discharge.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "domain": "0x-instant-staging", - "build_command": "WEBPACK_OUTPUT_PATH=public dotenv yarn build -- --env.discharge_target=staging", - "upload_directory": "public", - "index_key": "index.html", - "error_key": "index.html", - "trailing_slashes": true, - "cache": 3600, - "aws_profile": "0xproject", - "aws_region": "us-east-1", - "cdn": false, - "dns_configured": true -} diff --git a/packages/instant/CHANGELOG.json b/packages/instant/CHANGELOG.json deleted file mode 100644 index c7348c3c0..000000000 --- a/packages/instant/CHANGELOG.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "version": "3.0.0", - "changes": [ - { - "note": "Upgrade the bignumber.js to v8.0.2", - "pr": 1517 - } - ] - }, - { - "version": "2.0.0", - "changes": [ - { - "note": "Renamed ActionTypes enum members to PascalCase to conform with tslint enum-naming rule", - "pr": 1474 - } - ] - }, - { - "timestamp": 1542821676, - "version": "1.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - } -] diff --git a/packages/instant/CHANGELOG.md b/packages/instant/CHANGELOG.md deleted file mode 100644 index c8be0c644..000000000 --- a/packages/instant/CHANGELOG.md +++ /dev/null @@ -1,10 +0,0 @@ - - -CHANGELOG - -## v1.0.1 - _November 21, 2018_ - - * Dependencies updated diff --git a/packages/instant/README.md b/packages/instant/README.md deleted file mode 100644 index 8832e562d..000000000 --- a/packages/instant/README.md +++ /dev/null @@ -1,110 +0,0 @@ -## @0x/instant - -## Integration - -Looking to integrate 0x Instant into your web application or site? Check out the dedicated [instant documentation](https://0xproject.com/wiki#Get-Started-With-Instant) to get started. The documentation covers instant and related topics in depth. For a more "drag and drop" experience, check out our [configurator tool](https://0xproject.com/instant#configure). For on demand developer support, join our [Discord](https://discordapp.com/invite/d3FTX3M). - -Check out a live sample integration [here](https://www.rexrelay.com/instant). - -## Installation - -The package is available as a UMD module named `zeroExInstant` at https://instant.0xproject.com/instant.js. - -```html - - - - -
- - -``` - -## Deploying - -To run any of the following commands you need to configure your `.env` file. There is an example `.env_example` file to show you what values are required. - -You can deploy a work-in-progress version of 0x Instant at http://0x-instant-dogfood.s3-website-us-east-1.amazonaws.com/instant.js for easy sharing. - -To build and deploy the bundle run - -``` -yarn deploy_dogfood -``` - -We also have a staging bucket that is to be updated less frequently can be used to share a beta version of instant externally: http://0x-instant-staging.s3-website-us-east-1.amazonaws.com/instant.js - -To build and deploy to this bundle, run - -``` -yarn deploy_staging -``` - -Finally, we have our live production bundle that is only meant to be updated with stable, polished releases: https://instant.0xproject.com/instant.js - -To build and deploy to this bundle, run - -``` -yarn deploy_production -``` - -**NOTE: On deploying the site to staging and dogfood, it will say the site is available at a non-existent URL. Please ignore and use the (now updated) URL above.** - -## Contributing - -We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository. - -Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. - -### Install dependencies - -If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: - -```bash -yarn config set workspaces-experimental true -``` - -Then install dependencies - -```bash -yarn install -``` - -### Build - -To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory: - -```bash -PKG=@0x/instant yarn build -``` - -Or continuously rebuild on change: - -```bash -PKG=@0x/instant yarn watch -``` - -### Clean - -```bash -yarn clean -``` - -### Lint - -```bash -yarn lint -``` - -### Run Tests - -```bash -yarn test -``` diff --git a/packages/instant/jest.config.js b/packages/instant/jest.config.js deleted file mode 100644 index 29c365835..000000000 --- a/packages/instant/jest.config.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - roots: ['/test'], - coverageDirectory: 'coverage', - transform: { - '.*.tsx?$': 'ts-jest', - }, - testRegex: '(/__test__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/index.tsx'], -}; diff --git a/packages/instant/package.json b/packages/instant/package.json deleted file mode 100644 index 86fac9afe..000000000 --- a/packages/instant/package.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "name": "@0x/instant", - "version": "1.0.8", - "engines": { - "node": ">=6.12" - }, - "private": true, - "description": "0x Instant React Component", - "main": "umd/instant.js", - "scripts": { - "build": "webpack --mode production", - "build:ci": "yarn build", - "dev": "dotenv webpack-dev-server -- --mode development", - "lint": "tslint --format stylish --project .", - "test": "jest", - "test:coverage": "jest --coverage", - "rebuild_and_test": "run-s clean build test", - "test:circleci": "yarn test:coverage", - "clean": "shx rm -rf lib coverage scripts", - "deploy_dogfood": "discharge deploy -c .dogfood.discharge.json", - "deploy_staging": "discharge deploy -c .staging.discharge.json", - "deploy_production": "discharge deploy -c .production.discharge.json", - "manual:postpublish": "yarn build; node ./scripts/postpublish.js" - }, - "config": { - "postpublish": { - "assets": [ - "packages/instant/umd/instant.js", - "packages/instant/umd/instant.js.map" - ] - } - }, - "repository": { - "type": "git", - "url": "https://github.com/0xProject/0x-monorepo.git" - }, - "author": "Francesco Agosti", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/0xProject/0x-monorepo/issues" - }, - "homepage": "https://github.com/0xProject/0x-monorepo/packages/instant/README.md", - "dependencies": { - "@0x/assert": "^1.0.23", - "@0x/asset-buyer": "^4.0.2", - "@0x/json-schemas": "^2.1.7", - "@0x/order-utils": "^3.1.2", - "@0x/subproviders": "^2.1.11", - "@0x/types": "^1.5.2", - "@0x/typescript-typings": "^3.0.8", - "@0x/utils": "^3.0.1", - "@0x/web3-wrapper": "^3.2.4", - "bowser": "^1.9.4", - "copy-to-clipboard": "^3.0.8", - "ethereum-types": "^1.1.6", - "lodash": "^4.17.5", - "polished": "^2.2.0", - "react": "^16.5.2", - "react-dom": "^16.5.2", - "react-redux": "^5.0.7", - "redux": "^4.0.0", - "redux-devtools-extension": "^2.13.5", - "rollbar": "^2.5.0", - "styled-components": "^4.0.2", - "ts-optchain": "^0.1.1" - }, - "devDependencies": { - "@0x/tslint-config": "^2.0.2", - "@static/discharge": "https://github.com/0xProject/discharge.git", - "@types/enzyme": "^3.1.14", - "@types/enzyme-adapter-react-16": "^1.0.3", - "@types/jest": "^23.3.5", - "@types/lodash": "^4.14.116", - "@types/node": "*", - "@types/react": "^16.4.16", - "@types/react-dom": "^16.0.8", - "@types/react-redux": "^6.0.9", - "@types/redux": "^3.6.0", - "@types/styled-components": "4.0.1", - "awesome-typescript-loader": "^5.2.1", - "dotenv-cli": "^1.4.0", - "enzyme": "^3.6.0", - "enzyme-adapter-react-16": "^1.5.0", - "ip": "^1.1.5", - "jest": "^23.6.0", - "make-promises-safe": "^1.1.0", - "npm-run-all": "^4.1.2", - "nyc": "^11.0.1", - "rollbar-sourcemap-webpack-plugin": "^2.4.0", - "shx": "^0.2.2", - "source-map-loader": "^0.2.4", - "svg-react-loader": "^0.4.6", - "ts-jest": "^23.10.3", - "tslint": "5.11.0", - "typedoc": "0.13.0", - "typescript": "3.0.1", - "webpack": "^4.20.2", - "webpack-cli": "^3.1.1", - "webpack-dev-server": "^3.1.9" - }, - "publishConfig": { - "access": "private" - } -} diff --git a/packages/instant/public/external.css b/packages/instant/public/external.css deleted file mode 100644 index 21278577e..000000000 --- a/packages/instant/public/external.css +++ /dev/null @@ -1,29 +0,0 @@ -/* - CSS file meant to represent an external (integrators) stylesheet and - help ensure that instant looks consistent across environments. -*/ - -button { - font-size: 50px; - height: 200px; - background-color: red; -} - -input { - padding: 100px; - font-size: 50px; - height: 100px; -} - -input::-webkit-input-placeholder { - color: #b4b4b4 !important; -} - -div { - padding: 3px; -} - -p { - background-color: green; - margin: 10px; -} diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html deleted file mode 100644 index d10618c58..000000000 --- a/packages/instant/public/index.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - 0x Instant Dev Environment - - - - - - - - - -
-
-
- - - -
-
-
- - - diff --git a/packages/instant/src/assets/icons/ae.svg b/packages/instant/src/assets/icons/ae.svg deleted file mode 100644 index 592400d1a..000000000 --- a/packages/instant/src/assets/icons/ae.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/agi.svg b/packages/instant/src/assets/icons/agi.svg deleted file mode 100644 index 9ed9784a4..000000000 --- a/packages/instant/src/assets/icons/agi.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/instant/src/assets/icons/ant.svg b/packages/instant/src/assets/icons/ant.svg deleted file mode 100644 index ed7e1491a..000000000 --- a/packages/instant/src/assets/icons/ant.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/instant/src/assets/icons/ast.svg b/packages/instant/src/assets/icons/ast.svg deleted file mode 100644 index 8136fb688..000000000 --- a/packages/instant/src/assets/icons/ast.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/bat.svg b/packages/instant/src/assets/icons/bat.svg deleted file mode 100644 index 9b69ddf9d..000000000 --- a/packages/instant/src/assets/icons/bat.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/instant/src/assets/icons/cvc.svg b/packages/instant/src/assets/icons/cvc.svg deleted file mode 100644 index bddc90e16..000000000 --- a/packages/instant/src/assets/icons/cvc.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/dai.svg b/packages/instant/src/assets/icons/dai.svg deleted file mode 100644 index 901d522ca..000000000 --- a/packages/instant/src/assets/icons/dai.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/instant/src/assets/icons/dgd.svg b/packages/instant/src/assets/icons/dgd.svg deleted file mode 100644 index 371f89584..000000000 --- a/packages/instant/src/assets/icons/dgd.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/instant/src/assets/icons/dgx.svg b/packages/instant/src/assets/icons/dgx.svg deleted file mode 100644 index 2e4a90a5d..000000000 --- a/packages/instant/src/assets/icons/dgx.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/dnt.svg b/packages/instant/src/assets/icons/dnt.svg deleted file mode 100644 index 7d5459343..000000000 --- a/packages/instant/src/assets/icons/dnt.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/fun.svg b/packages/instant/src/assets/icons/fun.svg deleted file mode 100644 index bb4347df2..000000000 --- a/packages/instant/src/assets/icons/fun.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/gno.svg b/packages/instant/src/assets/icons/gno.svg deleted file mode 100644 index ebf6290cf..000000000 --- a/packages/instant/src/assets/icons/gno.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/instant/src/assets/icons/gnt.svg b/packages/instant/src/assets/icons/gnt.svg deleted file mode 100644 index 7315ce459..000000000 --- a/packages/instant/src/assets/icons/gnt.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/instant/src/assets/icons/knc.svg b/packages/instant/src/assets/icons/knc.svg deleted file mode 100644 index 70d35bc2f..000000000 --- a/packages/instant/src/assets/icons/knc.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/instant/src/assets/icons/link.svg b/packages/instant/src/assets/icons/link.svg deleted file mode 100644 index 2fddf7ef1..000000000 --- a/packages/instant/src/assets/icons/link.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/instant/src/assets/icons/lpt.svg b/packages/instant/src/assets/icons/lpt.svg deleted file mode 100644 index cbe4f2202..000000000 --- a/packages/instant/src/assets/icons/lpt.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/packages/instant/src/assets/icons/mana.svg b/packages/instant/src/assets/icons/mana.svg deleted file mode 100644 index 45be622e4..000000000 --- a/packages/instant/src/assets/icons/mana.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/packages/instant/src/assets/icons/mkr.svg b/packages/instant/src/assets/icons/mkr.svg deleted file mode 100644 index e09d47444..000000000 --- a/packages/instant/src/assets/icons/mkr.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/mln.svg b/packages/instant/src/assets/icons/mln.svg deleted file mode 100644 index a0b821c57..000000000 --- a/packages/instant/src/assets/icons/mln.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/omg.svg b/packages/instant/src/assets/icons/omg.svg deleted file mode 100644 index a906509af..000000000 --- a/packages/instant/src/assets/icons/omg.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/instant/src/assets/icons/powr.svg b/packages/instant/src/assets/icons/powr.svg deleted file mode 100644 index eb48342e1..000000000 --- a/packages/instant/src/assets/icons/powr.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/instant/src/assets/icons/ren.svg b/packages/instant/src/assets/icons/ren.svg deleted file mode 100644 index fe563dee2..000000000 --- a/packages/instant/src/assets/icons/ren.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/packages/instant/src/assets/icons/rep.svg b/packages/instant/src/assets/icons/rep.svg deleted file mode 100644 index 1be1a6a88..000000000 --- a/packages/instant/src/assets/icons/rep.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/packages/instant/src/assets/icons/req.svg b/packages/instant/src/assets/icons/req.svg deleted file mode 100644 index d9eb89634..000000000 --- a/packages/instant/src/assets/icons/req.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/instant/src/assets/icons/salt.svg b/packages/instant/src/assets/icons/salt.svg deleted file mode 100644 index f2892c981..000000000 --- a/packages/instant/src/assets/icons/salt.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/instant/src/assets/icons/snt.svg b/packages/instant/src/assets/icons/snt.svg deleted file mode 100644 index 34b2c432b..000000000 --- a/packages/instant/src/assets/icons/snt.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/spank.svg b/packages/instant/src/assets/icons/spank.svg deleted file mode 100644 index 1d7320770..000000000 --- a/packages/instant/src/assets/icons/spank.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/instant/src/assets/icons/wax.svg b/packages/instant/src/assets/icons/wax.svg deleted file mode 100644 index 8bcb73015..000000000 --- a/packages/instant/src/assets/icons/wax.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/packages/instant/src/assets/icons/zil.svg b/packages/instant/src/assets/icons/zil.svg deleted file mode 100644 index 1a9218201..000000000 --- a/packages/instant/src/assets/icons/zil.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/instant/src/assets/icons/zrx.svg b/packages/instant/src/assets/icons/zrx.svg deleted file mode 100644 index da623710b..000000000 --- a/packages/instant/src/assets/icons/zrx.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/instant/src/assets/powered_by_0x.svg b/packages/instant/src/assets/powered_by_0x.svg deleted file mode 100644 index e3d007d0b..000000000 --- a/packages/instant/src/assets/powered_by_0x.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/packages/instant/src/components/amount_placeholder.tsx b/packages/instant/src/components/amount_placeholder.tsx deleted file mode 100644 index 290e34a07..000000000 --- a/packages/instant/src/components/amount_placeholder.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; - -import { Pulse } from './animations/pulse'; - -import { Text } from './ui/text'; - -interface PlainPlaceholder { - color: ColorOption; -} -const PlainPlaceholder: React.StatelessComponent = props => ( - - — - -); - -export interface AmountPlaceholderProps { - color: ColorOption; - isPulsating: boolean; -} -export const AmountPlaceholder: React.StatelessComponent = props => { - if (props.isPulsating) { - return ( - - - - ); - } else { - return ; - } -}; - -AmountPlaceholder.displayName = 'AmountPlaceholder'; diff --git a/packages/instant/src/components/animations/full_rotation.tsx b/packages/instant/src/components/animations/full_rotation.tsx deleted file mode 100644 index 1dff1b1fc..000000000 --- a/packages/instant/src/components/animations/full_rotation.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { keyframes, styled } from '../../style/theme'; - -interface FullRotationProps { - height: string; - width: string; -} -const rotatingKeyframes = keyframes` -from { - transform: rotate(0deg); -} - -to { - transform: rotate(360deg); -} -`; - -export const FullRotation = styled.div` - animation: ${rotatingKeyframes} 2s linear infinite; - height: ${props => props.height}; - width: ${props => props.width}; -`; diff --git a/packages/instant/src/components/animations/position_animation.tsx b/packages/instant/src/components/animations/position_animation.tsx deleted file mode 100644 index 4f8f25679..000000000 --- a/packages/instant/src/components/animations/position_animation.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { InterpolationValue } from 'styled-components'; - -import { media, OptionallyScreenSpecific, stylesForMedia } from '../../style/media'; -import { css, keyframes, styled } from '../../style/theme'; - -export interface TransitionInfo { - from: string; - to: string; -} - -const generateTransitionInfoCss = ( - key: keyof TransitionInfo, - top?: TransitionInfo, - bottom?: TransitionInfo, - left?: TransitionInfo, - right?: TransitionInfo, -): string => { - const topStringIfExists = top ? `top: ${top[key]};` : ''; - const bottomStringIfExists = bottom ? `bottom: ${bottom[key]};` : ''; - const leftStringIfExists = left ? `left: ${left[key]};` : ''; - const rightStringIfExists = right ? `right: ${right[key]};` : ''; - return ` - ${topStringIfExists} - ${bottomStringIfExists} - ${leftStringIfExists} - ${rightStringIfExists} - `; -}; - -const slideKeyframeGenerator = ( - position: string, - top?: TransitionInfo, - bottom?: TransitionInfo, - left?: TransitionInfo, - right?: TransitionInfo, -) => keyframes` - from { - position: ${position}; - ${generateTransitionInfoCss('from', top, bottom, left, right)} - } - - to { - position: ${position}; - ${generateTransitionInfoCss('to', top, bottom, left, right)} - } -`; - -export interface PositionAnimationSettings { - top?: TransitionInfo; - bottom?: TransitionInfo; - left?: TransitionInfo; - right?: TransitionInfo; - timingFunction: string; - duration?: string; - position?: string; -} - -const generatePositionAnimationCss = (positionSettings: PositionAnimationSettings) => { - return css` - animation-name: ${slideKeyframeGenerator( - positionSettings.position || 'relative', - positionSettings.top, - positionSettings.bottom, - positionSettings.left, - positionSettings.right, - )}; - animation-duration: ${positionSettings.duration || '0.3s'}; - animation-timing-function: ${positionSettings.timingFunction}; - animation-delay: 0s; - animation-iteration-count: 1; - animation-fill-mode: forwards; - position: ${positionSettings.position || 'relative'}; - width: 100%; - `; -}; - -export interface PositionAnimationProps { - positionSettings: OptionallyScreenSpecific; - zIndex?: OptionallyScreenSpecific; - height?: string; -} - -const defaultAnimation = (positionSettings: OptionallyScreenSpecific) => { - const bestDefault = 'default' in positionSettings ? positionSettings.default : positionSettings; - return generatePositionAnimationCss(bestDefault); -}; -const animationForSize = ( - positionSettings: OptionallyScreenSpecific, - sizeKey: 'sm' | 'md' | 'lg', - mediaFn: (...args: any[]) => InterpolationValue[], -) => { - // checking default makes sure we have a PositionAnimationSettings object - // and then we check to see if we have a setting for the specific `sizeKey` - const animationSettingsForSize = 'default' in positionSettings && positionSettings[sizeKey]; - return animationSettingsForSize && mediaFn`${generatePositionAnimationCss(animationSettingsForSize)}`; -}; - -export const PositionAnimation = styled.div` - && { - ${props => props.zIndex && stylesForMedia('z-index', props.zIndex)} - ${props => defaultAnimation(props.positionSettings)} - ${props => animationForSize(props.positionSettings, 'sm', media.small)} - ${props => animationForSize(props.positionSettings, 'md', media.medium)} - ${props => animationForSize(props.positionSettings, 'lg', media.large)} - ${props => (props.height ? `height: ${props.height};` : '')} - } -`; diff --git a/packages/instant/src/components/animations/pulse.tsx b/packages/instant/src/components/animations/pulse.tsx deleted file mode 100644 index 01d6ea070..000000000 --- a/packages/instant/src/components/animations/pulse.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { keyframes, styled } from '../../style/theme'; - -const pulsingKeyframes = keyframes` - 0%, 100% { - opacity: 0.2; - } - 50% { - opacity: 100; - } -`; -export const Pulse = styled.div` - animation-name: ${pulsingKeyframes} - animation-duration: 2s; - animation-iteration-count: infinite; -`; diff --git a/packages/instant/src/components/animations/slide_animation.tsx b/packages/instant/src/components/animations/slide_animation.tsx deleted file mode 100644 index 6ac47e9a6..000000000 --- a/packages/instant/src/components/animations/slide_animation.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import * as React from 'react'; - -import { OptionallyScreenSpecific } from '../../style/media'; -import { SlideAnimationState } from '../../types'; - -import { PositionAnimation, PositionAnimationSettings } from './position_animation'; - -export interface SlideAnimationProps { - animationState: SlideAnimationState; - slideInSettings: OptionallyScreenSpecific; - slideOutSettings: OptionallyScreenSpecific; - zIndex?: OptionallyScreenSpecific; - height?: string; - onAnimationEnd?: () => void; -} - -export const SlideAnimation: React.StatelessComponent = props => { - if (props.animationState === 'none') { - return {props.children}; - } - const positionSettings = props.animationState === 'slidIn' ? props.slideInSettings : props.slideOutSettings; - return ( - - {props.children} - - ); -}; - -SlideAnimation.displayName = 'SlideAnimation'; diff --git a/packages/instant/src/components/buy_button.tsx b/packages/instant/src/components/buy_button.tsx deleted file mode 100644 index 551e857a5..000000000 --- a/packages/instant/src/components/buy_button.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer'; -import { AssetProxyId } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { oc } from 'ts-optchain'; - -import { WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX } from '../constants'; -import { ColorOption } from '../style/theme'; -import { AffiliateInfo, Asset, ZeroExInstantError } from '../types'; -import { analytics } from '../util/analytics'; -import { errorReporter } from '../util/error_reporter'; -import { gasPriceEstimator } from '../util/gas_price_estimator'; -import { util } from '../util/util'; - -import { Button } from './ui/button'; - -export interface BuyButtonProps { - accountAddress?: string; - accountEthBalanceInWei?: BigNumber; - buyQuote?: BuyQuote; - assetBuyer: AssetBuyer; - web3Wrapper: Web3Wrapper; - affiliateInfo?: AffiliateInfo; - selectedAsset?: Asset; - onValidationPending: (buyQuote: BuyQuote) => void; - onValidationFail: (buyQuote: BuyQuote, errorMessage: AssetBuyerError | ZeroExInstantError) => void; - onSignatureDenied: (buyQuote: BuyQuote) => void; - onBuyProcessing: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => void; - onBuySuccess: (buyQuote: BuyQuote, txHash: string) => void; - onBuyFailure: (buyQuote: BuyQuote, txHash: string) => void; -} - -export class BuyButton extends React.PureComponent { - public static defaultProps = { - onClick: util.boundNoop, - onBuySuccess: util.boundNoop, - onBuyFailure: util.boundNoop, - }; - public render(): React.ReactNode { - const { buyQuote, accountAddress, selectedAsset } = this.props; - const shouldDisableButton = _.isUndefined(buyQuote) || _.isUndefined(accountAddress); - const buttonText = - !_.isUndefined(selectedAsset) && selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20 - ? `Buy ${selectedAsset.metaData.symbol.toUpperCase()}` - : 'Buy Now'; - return ( - - ); - } - private readonly _handleClick = async () => { - // The button is disabled when there is no buy quote anyway. - const { buyQuote, assetBuyer, affiliateInfo, accountAddress, accountEthBalanceInWei, web3Wrapper } = this.props; - if (_.isUndefined(buyQuote) || _.isUndefined(accountAddress)) { - return; - } - this.props.onValidationPending(buyQuote); - const ethNeededForBuy = buyQuote.worstCaseQuoteInfo.totalEthAmount; - // if we don't have a balance for the user, let the transaction through, it will be handled by the wallet - const hasSufficientEth = _.isUndefined(accountEthBalanceInWei) || accountEthBalanceInWei.gte(ethNeededForBuy); - if (!hasSufficientEth) { - analytics.trackBuyNotEnoughEth(buyQuote); - this.props.onValidationFail(buyQuote, ZeroExInstantError.InsufficientETH); - return; - } - let txHash: string | undefined; - const gasInfo = await gasPriceEstimator.getGasInfoAsync(); - const feeRecipient = oc(affiliateInfo).feeRecipient(); - try { - analytics.trackBuyStarted(buyQuote); - txHash = await assetBuyer.executeBuyQuoteAsync(buyQuote, { - feeRecipient, - takerAddress: accountAddress, - gasPrice: gasInfo.gasPriceInWei, - }); - } catch (e) { - if (e instanceof Error) { - if (e.message === AssetBuyerError.TransactionValueTooLow) { - analytics.trackBuySimulationFailed(buyQuote); - this.props.onValidationFail(buyQuote, AssetBuyerError.TransactionValueTooLow); - return; - } else if (e.message === AssetBuyerError.SignatureRequestDenied) { - analytics.trackBuySignatureDenied(buyQuote); - this.props.onSignatureDenied(buyQuote); - return; - } else { - errorReporter.report(e); - analytics.trackBuyUnknownError(buyQuote, e.message); - this.props.onValidationFail(buyQuote, ZeroExInstantError.CouldNotSubmitTransaction); - return; - } - } - throw e; - } - const startTimeUnix = new Date().getTime(); - const expectedEndTimeUnix = startTimeUnix + gasInfo.estimatedTimeMs; - this.props.onBuyProcessing(buyQuote, txHash, startTimeUnix, expectedEndTimeUnix); - try { - analytics.trackBuyTxSubmitted(buyQuote, txHash, startTimeUnix, expectedEndTimeUnix); - await web3Wrapper.awaitTransactionSuccessAsync(txHash); - } catch (e) { - if (e instanceof Error && e.message.startsWith(WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX)) { - analytics.trackBuyTxFailed(buyQuote, txHash, startTimeUnix, expectedEndTimeUnix); - this.props.onBuyFailure(buyQuote, txHash); - return; - } - throw e; - } - analytics.trackBuyTxSucceeded(buyQuote, txHash, startTimeUnix, expectedEndTimeUnix); - this.props.onBuySuccess(buyQuote, txHash); - }; -} diff --git a/packages/instant/src/components/buy_order_progress.tsx b/packages/instant/src/components/buy_order_progress.tsx deleted file mode 100644 index 11ac5d5e0..000000000 --- a/packages/instant/src/components/buy_order_progress.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; - -import { TimedProgressBar } from '../components/timed_progress_bar'; - -import { TimeCounter } from '../components/time_counter'; -import { Container } from '../components/ui/container'; -import { OrderProcessState, OrderState } from '../types'; - -export interface BuyOrderProgressProps { - buyOrderState: OrderState; -} - -export const BuyOrderProgress: React.StatelessComponent = props => { - const { buyOrderState } = props; - if ( - buyOrderState.processState === OrderProcessState.Processing || - buyOrderState.processState === OrderProcessState.Success || - buyOrderState.processState === OrderProcessState.Failure - ) { - const progress = buyOrderState.progress; - const hasEnded = buyOrderState.processState !== OrderProcessState.Processing; - const expectedTimeMs = progress.expectedEndTimeUnix - progress.startTimeUnix; - return ( - - - - - - - ); - } - return null; -}; - -BuyOrderProgress.displayName = 'BuyOrderProgress'; diff --git a/packages/instant/src/components/buy_order_state_buttons.tsx b/packages/instant/src/components/buy_order_state_buttons.tsx deleted file mode 100644 index 1214559d1..000000000 --- a/packages/instant/src/components/buy_order_state_buttons.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; -import { AffiliateInfo, Asset, OrderProcessState, ZeroExInstantError } from '../types'; - -import { BuyButton } from './buy_button'; -import { PlacingOrderButton } from './placing_order_button'; -import { SecondaryButton } from './secondary_button'; - -import { Button } from './ui/button'; -import { Flex } from './ui/flex'; - -export interface BuyOrderStateButtonProps { - accountAddress?: string; - accountEthBalanceInWei?: BigNumber; - buyQuote?: BuyQuote; - buyOrderProcessingState: OrderProcessState; - assetBuyer: AssetBuyer; - web3Wrapper: Web3Wrapper; - affiliateInfo?: AffiliateInfo; - selectedAsset?: Asset; - onViewTransaction: () => void; - onValidationPending: (buyQuote: BuyQuote) => void; - onValidationFail: (buyQuote: BuyQuote, errorMessage: AssetBuyerError | ZeroExInstantError) => void; - onSignatureDenied: (buyQuote: BuyQuote) => void; - onBuyProcessing: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => void; - onBuySuccess: (buyQuote: BuyQuote, txHash: string) => void; - onBuyFailure: (buyQuote: BuyQuote, txHash: string) => void; - onRetry: () => void; -} - -export const BuyOrderStateButtons: React.StatelessComponent = props => { - if (props.buyOrderProcessingState === OrderProcessState.Failure) { - return ( - - - - Details - - - ); - } else if ( - props.buyOrderProcessingState === OrderProcessState.Success || - props.buyOrderProcessingState === OrderProcessState.Processing - ) { - return View Transaction; - } else if (props.buyOrderProcessingState === OrderProcessState.Validating) { - return ; - } - - return ( - - ); -}; - -BuyOrderStateButtons.displayName = 'BuyOrderStateButtons'; diff --git a/packages/instant/src/components/coinbase_wallet_logo.tsx b/packages/instant/src/components/coinbase_wallet_logo.tsx deleted file mode 100644 index 845b96d73..000000000 --- a/packages/instant/src/components/coinbase_wallet_logo.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react'; - -export interface CoinbaseWalletLogoProps { - width?: number; -} - -export const CoinbaseWalletLogo: React.StatelessComponent = ({ width }) => ( - - - - -); - -CoinbaseWalletLogo.displayName = 'CoinbaseWalletLogo'; - -CoinbaseWalletLogo.defaultProps = { - width: 164, -}; diff --git a/packages/instant/src/components/css_reset.tsx b/packages/instant/src/components/css_reset.tsx deleted file mode 100644 index d1b20f4c9..000000000 --- a/packages/instant/src/components/css_reset.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { INJECTED_DIV_CLASS } from '../constants'; -import { createGlobalStyle } from '../style/theme'; - -export interface CSSResetProps {} - -/* - * Derived from - * https://github.com/jtrost/Complete-CSS-Reset - */ -export const CSSReset = createGlobalStyle` - .${INJECTED_DIV_CLASS} { - a, abbr, area, article, aside, audio, b, bdo, blockquote, body, button, - canvas, caption, cite, code, col, colgroup, command, datalist, dd, del, - details, dialog, dfn, div, dl, dt, em, embed, fieldset, figure, form, - h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html, i, iframe, img, - input, ins, keygen, kbd, label, legend, li, map, mark, menu, meter, nav, - noscript, object, ol, optgroup, option, output, p, param, pre, progress, - q, rp, rt, ruby, samp, section, select, small, span, strong, sub, sup, - table, tbody, td, textarea, tfoot, th, thead, time, tr, ul, var, video { - background: transparent; - border: 0; - font-size: 100%; - font: inherit; - margin: 0; - outline: none; - padding: 0; - text-align: left; - text-decoration: none; - vertical-align: baseline; - } - } -`; diff --git a/packages/instant/src/components/erc20_asset_amount_input.tsx b/packages/instant/src/components/erc20_asset_amount_input.tsx deleted file mode 100644 index 0418f9165..000000000 --- a/packages/instant/src/components/erc20_asset_amount_input.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; - -import { ColorOption, transparentWhite } from '../style/theme'; -import { ERC20Asset, SimpleHandler } from '../types'; -import { assetUtils } from '../util/asset'; -import { util } from '../util/util'; - -import { ScalingAmountInput } from './scaling_amount_input'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Icon } from './ui/icon'; -import { Text } from './ui/text'; - -// Asset amounts only apply to ERC20 assets -export interface ERC20AssetAmountInputProps { - asset?: ERC20Asset; - value?: BigNumber; - onChange: (value?: BigNumber, asset?: ERC20Asset) => void; - onSelectAssetClick?: (asset?: ERC20Asset) => void; - startingFontSizePx: number; - fontColor?: ColorOption; - isInputDisabled: boolean; - canSelectOtherAsset: boolean; - numberOfAssetsAvailable?: number; -} - -export interface ERC20AssetAmountInputState { - currentFontSizePx: number; -} - -export class ERC20AssetAmountInput extends React.PureComponent { - public static defaultProps = { - onChange: util.boundNoop, - isDisabled: false, - }; - constructor(props: ERC20AssetAmountInputProps) { - super(props); - this.state = { - currentFontSizePx: props.startingFontSizePx, - }; - } - public render(): React.ReactNode { - const { asset } = this.props; - return ( - - {_.isUndefined(asset) ? this._renderTokenSelectionContent() : this._renderContentForAsset(asset)} - - ); - } - private readonly _renderContentForAsset = (asset: ERC20Asset): React.ReactNode => { - const { onChange, isInputDisabled, ...rest } = this.props; - const amountBorderBottom = isInputDisabled ? '' : `1px solid ${transparentWhite}`; - const onSymbolClick = this._generateSelectAssetClickHandler(); - return ( - - - - - - - - {assetUtils.formattedSymbolForAsset(asset)} - - {this.props.canSelectOtherAsset && this._renderChevronIcon()} - - - - ); - }; - private readonly _renderTokenSelectionContent = (): React.ReactNode => { - const { numberOfAssetsAvailable } = this.props; - let text = 'Select Token'; - if (_.isUndefined(numberOfAssetsAvailable)) { - text = 'Loading...'; - } else if (numberOfAssetsAvailable === 0) { - text = 'Assets Unavailable'; - } - return ( - - - {text} - - {this._renderChevronIcon()} - - ); - }; - private readonly _renderChevronIcon = (): React.ReactNode => { - if (!this._areAnyAssetsAvailable()) { - return null; - } - return ( - - - - ); - }; - private readonly _handleChange = (value?: BigNumber): void => { - this.props.onChange(value, this.props.asset); - }; - private readonly _handleFontSizeChange = (fontSizePx: number): void => { - this.setState({ - currentFontSizePx: fontSizePx, - }); - }; - private readonly _generateSelectAssetClickHandler = (): SimpleHandler | undefined => { - // We don't want to allow opening the token selection panel if there are no assets. - // Since styles are inferred from the presence of a click handler, we want to return undefined - // instead of providing a noop. - if (!this._areAnyAssetsAvailable() || _.isUndefined(this.props.onSelectAssetClick)) { - return undefined; - } - return this._handleSelectAssetClick; - }; - private readonly _areAnyAssetsAvailable = (): boolean => { - const { numberOfAssetsAvailable } = this.props; - return !_.isUndefined(numberOfAssetsAvailable) && numberOfAssetsAvailable > 0; - }; - private readonly _handleSelectAssetClick = (): void => { - if (this.props.onSelectAssetClick) { - this.props.onSelectAssetClick(); - } - }; - // For assets with symbols of different length, - // start scaling the input at different character lengths - private readonly _textLengthThresholdForAsset = (asset?: ERC20Asset): number => { - if (_.isUndefined(asset)) { - return 3; - } - const symbol = asset.metaData.symbol; - if (symbol.length <= 3) { - return 5; - } - if (symbol.length === 5) { - return 3; - } - return 4; - }; -} diff --git a/packages/instant/src/components/erc20_token_selector.tsx b/packages/instant/src/components/erc20_token_selector.tsx deleted file mode 100644 index a26fb5cf5..000000000 --- a/packages/instant/src/components/erc20_token_selector.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; -import { ERC20Asset } from '../types'; -import { analytics } from '../util/analytics'; -import { assetUtils } from '../util/asset'; - -import { SearchInput } from './search_input'; -import { Circle } from './ui/circle'; -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text } from './ui/text'; - -export interface ERC20TokenSelectorProps { - tokens: ERC20Asset[]; - onTokenSelect: (token: ERC20Asset) => void; -} - -export interface ERC20TokenSelectorState { - searchQuery: string; -} - -export class ERC20TokenSelector extends React.PureComponent { - public state: ERC20TokenSelectorState = { - searchQuery: '', - }; - public render(): React.ReactNode { - const { tokens } = this.props; - return ( - - - - Select Token - - - - - - - - ); - } - private readonly _handleSearchInputChange = (event: React.ChangeEvent): void => { - const searchQuery = event.target.value; - this.setState({ - searchQuery, - }); - analytics.trackTokenSelectorSearched(searchQuery); - }; - private readonly _handleTokenClick = (token: ERC20Asset): void => { - this.props.onTokenSelect(token); - }; -} - -interface TokenRowFilterProps { - tokens: ERC20Asset[]; - onClick: (token: ERC20Asset) => void; - searchQuery: string; -} - -class TokenRowFilter extends React.Component { - public render(): React.ReactNode { - return _.map(this.props.tokens, token => { - if (!this._isTokenQueryMatch(token)) { - return null; - } - return ; - }); - } - public shouldComponentUpdate(nextProps: TokenRowFilterProps): boolean { - const arePropsDeeplyEqual = _.isEqual(nextProps, this.props); - return !arePropsDeeplyEqual; - } - private readonly _isTokenQueryMatch = (token: ERC20Asset): boolean => { - const { searchQuery } = this.props; - const searchQueryLowerCase = searchQuery.toLowerCase().trim(); - if (searchQueryLowerCase === '') { - return true; - } - const tokenName = token.metaData.name.toLowerCase(); - const tokenSymbol = token.metaData.symbol.toLowerCase(); - return _.startsWith(tokenSymbol, searchQueryLowerCase) || _.startsWith(tokenName, searchQueryLowerCase); - }; -} - -interface TokenSelectorRowProps { - token: ERC20Asset; - onClick: (token: ERC20Asset) => void; -} - -class TokenSelectorRow extends React.PureComponent { - public render(): React.ReactNode { - const { token } = this.props; - const circleColor = token.metaData.primaryColor || 'black'; - const displaySymbol = assetUtils.bestNameForAsset(token); - return ( - - - - - - - - - - - - {displaySymbol} - - - - - - {token.metaData.name} - - - - ); - } - private readonly _handleClick = (): void => { - this.props.onClick(this.props.token); - }; -} - -interface TokenSelectorRowIconProps { - token: ERC20Asset; -} - -const getTokenIcon = (symbol: string): React.StatelessComponent | undefined => { - try { - return require(`../assets/icons/${symbol}.svg`) as React.StatelessComponent; - } catch (e) { - // Can't find icon - return undefined; - } -}; - -class TokenSelectorRowIcon extends React.PureComponent { - public render(): React.ReactNode { - const { token } = this.props; - const iconUrlIfExists = token.metaData.iconUrl; - - const TokenIcon = getTokenIcon(token.metaData.symbol); - const displaySymbol = assetUtils.bestNameForAsset(token); - if (!_.isUndefined(iconUrlIfExists)) { - return ; - } else if (!_.isUndefined(TokenIcon)) { - return ; - } else { - return ( - - {displaySymbol} - - ); - } - } -} diff --git a/packages/instant/src/components/install_wallet_panel_content.tsx b/packages/instant/src/components/install_wallet_panel_content.tsx deleted file mode 100644 index 1af3dafbb..000000000 --- a/packages/instant/src/components/install_wallet_panel_content.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import * as React from 'react'; - -import { - META_MASK_CHROME_STORE_URL, - META_MASK_FIREFOX_STORE_URL, - META_MASK_OPERA_STORE_URL, - META_MASK_SITE_URL, -} from '../constants'; -import { ColorOption } from '../style/theme'; -import { Browser } from '../types'; -import { analytics } from '../util/analytics'; -import { envUtil } from '../util/env'; -import { util } from '../util/util'; - -import { MetaMaskLogo } from './meta_mask_logo'; -import { StandardPanelContent, StandardPanelContentProps } from './standard_panel_content'; -import { Button } from './ui/button'; - -export interface InstallWalletPanelContentProps {} - -export class InstallWalletPanelContent extends React.PureComponent { - public render(): React.ReactNode { - const panelProps = this._getStandardPanelContentProps(); - return ; - } - private readonly _getStandardPanelContentProps = (): StandardPanelContentProps => { - const browser = envUtil.getBrowser(); - let description = 'Please install the MetaMask wallet browser extension.'; - let actionText = 'Learn More'; - let actionUrl = META_MASK_SITE_URL; - switch (browser) { - case Browser.Chrome: - description = 'Please install the MetaMask wallet browser extension from the Chrome Store.'; - actionText = 'Get Chrome Extension'; - actionUrl = META_MASK_CHROME_STORE_URL; - break; - case Browser.Firefox: - description = 'Please install the MetaMask wallet browser extension from the Firefox Store.'; - actionText = 'Get Firefox Extension'; - actionUrl = META_MASK_FIREFOX_STORE_URL; - break; - case Browser.Opera: - description = 'Please install the MetaMask wallet browser extension from the Opera Store.'; - actionText = 'Get Opera Add-on'; - actionUrl = META_MASK_OPERA_STORE_URL; - break; - default: - break; - } - const onActionClick = () => { - analytics.trackInstallWalletModalClickedGet(); - util.createOpenUrlInNewWindow(actionUrl)(); - }; - return { - image: , - title: 'Install MetaMask', - description, - moreInfoSettings: { - href: META_MASK_SITE_URL, - text: 'What is MetaMask?', - onClick: analytics.trackInstallWalletModalClickedExplanation, - }, - action: ( - - ), - }; - }; -} diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx deleted file mode 100644 index e943f68d7..000000000 --- a/packages/instant/src/components/instant_heading.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; - -import { SelectedERC20AssetAmountInput } from '../containers/selected_erc20_asset_amount_input'; -import { ColorOption } from '../style/theme'; -import { AsyncProcessState, ERC20Asset, OrderProcessState, OrderState } from '../types'; -import { format } from '../util/format'; - -import { AmountPlaceholder } from './amount_placeholder'; -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Icon } from './ui/icon'; -import { Spinner } from './ui/spinner'; -import { Text } from './ui/text'; - -export interface InstantHeadingProps { - selectedAssetUnitAmount?: BigNumber; - totalEthBaseUnitAmount?: BigNumber; - ethUsdPrice?: BigNumber; - quoteRequestState: AsyncProcessState; - buyOrderState: OrderState; - onSelectAssetClick?: (asset?: ERC20Asset) => void; -} - -const PLACEHOLDER_COLOR = ColorOption.white; -const ICON_WIDTH = 34; -const ICON_HEIGHT = 34; -const ICON_COLOR = ColorOption.white; - -export class InstantHeading extends React.PureComponent { - public render(): React.ReactNode { - const iconOrAmounts = this._renderIcon() || this._renderAmountsSection(); - return ( - - - - {this._renderTopText()} - - - - - - - - {iconOrAmounts} - - - - ); - } - - private _renderAmountsSection(): React.ReactNode { - if ( - _.isUndefined(this.props.totalEthBaseUnitAmount) && - this.props.quoteRequestState !== AsyncProcessState.Pending - ) { - return null; - } else { - return ( - - {this._renderPlaceholderOrAmount(this._renderEthAmount)} - {this._renderPlaceholderOrAmount(this._renderDollarAmount)} - - ); - } - } - - private _renderIcon(): React.ReactNode { - const processState = this.props.buyOrderState.processState; - - if (processState === OrderProcessState.Failure) { - return ; - } else if (processState === OrderProcessState.Processing) { - return ; - } else if (processState === OrderProcessState.Success) { - return ; - } - return undefined; - } - - private _renderTopText(): React.ReactNode { - const processState = this.props.buyOrderState.processState; - if (processState === OrderProcessState.Failure) { - return 'Order failed'; - } else if (processState === OrderProcessState.Processing) { - return 'Processing Order...'; - } else if (processState === OrderProcessState.Success) { - return 'Tokens received!'; - } - - return 'I want to buy'; - } - - private _renderPlaceholderOrAmount(amountFunction: () => React.ReactNode): React.ReactNode { - if (this.props.quoteRequestState === AsyncProcessState.Pending) { - return ; - } - if (_.isUndefined(this.props.selectedAssetUnitAmount)) { - return ; - } - return amountFunction(); - } - - private readonly _renderEthAmount = (): React.ReactNode => { - const ethAmount = format.ethBaseUnitAmount( - this.props.totalEthBaseUnitAmount, - 4, - , - ); - - const fontSize = _.isString(ethAmount) && ethAmount.length >= 13 ? '14px' : '16px'; - return ( - - {ethAmount} - - ); - }; - - private readonly _renderDollarAmount = (): React.ReactNode => { - return ( - - {format.ethBaseUnitAmountInUsd( - this.props.totalEthBaseUnitAmount, - this.props.ethUsdPrice, - 2, - , - )} - - ); - }; -} diff --git a/packages/instant/src/components/meta_mask_logo.tsx b/packages/instant/src/components/meta_mask_logo.tsx deleted file mode 100644 index bfbc67270..000000000 --- a/packages/instant/src/components/meta_mask_logo.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import * as React from 'react'; - -export interface MetaMaskLogoProps { - width?: number; - height?: number; -} - -export const MetaMaskLogo: React.StatelessComponent = ({ width, height }) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); - -MetaMaskLogo.displayName = 'MetaMaskLogo'; - -MetaMaskLogo.defaultProps = { - width: 85, - height: 80, -}; diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx deleted file mode 100644 index 3ded50652..000000000 --- a/packages/instant/src/components/order_details.tsx +++ /dev/null @@ -1,230 +0,0 @@ -import { BuyQuoteInfo } from '@0x/asset-buyer'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { oc } from 'ts-optchain'; - -import { BIG_NUMBER_ZERO, DEFAULT_UNKOWN_ASSET_NAME } from '../constants'; -import { ColorOption } from '../style/theme'; -import { BaseCurrency } from '../types'; -import { format } from '../util/format'; - -import { AmountPlaceholder } from './amount_placeholder'; -import { SectionHeader } from './section_header'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text, TextProps } from './ui/text'; - -export interface OrderDetailsProps { - buyQuoteInfo?: BuyQuoteInfo; - selectedAssetUnitAmount?: BigNumber; - ethUsdPrice?: BigNumber; - isLoading: boolean; - assetName?: string; - baseCurrency: BaseCurrency; - onBaseCurrencySwitchEth: () => void; - onBaseCurrencySwitchUsd: () => void; -} -export class OrderDetails extends React.PureComponent { - public render(): React.ReactNode { - const shouldShowUsdError = this.props.baseCurrency === BaseCurrency.USD && this._hadErrorFetchingUsdPrice(); - return ( - - {this._renderHeader()} - {shouldShowUsdError ? this._renderErrorFetchingUsdPrice() : this._renderRows()} - - ); - } - - private _renderRows(): React.ReactNode { - const { buyQuoteInfo } = this.props; - return ( - - - - - - ); - } - - private _renderErrorFetchingUsdPrice(): React.ReactNode { - return ( - - There was an error fetching the USD price. - - Click here - - {' to view ETH prices'} - - ); - } - - private _hadErrorFetchingUsdPrice(): boolean { - return this.props.ethUsdPrice ? this.props.ethUsdPrice.isEqualTo(BIG_NUMBER_ZERO) : false; - } - - private _totalCostSecondaryValue(): React.ReactNode { - const secondaryCurrency = this.props.baseCurrency === BaseCurrency.USD ? BaseCurrency.ETH : BaseCurrency.USD; - - const canDisplayCurrency = - secondaryCurrency === BaseCurrency.ETH || - (secondaryCurrency === BaseCurrency.USD && this.props.ethUsdPrice && !this._hadErrorFetchingUsdPrice()); - - if (this.props.buyQuoteInfo && canDisplayCurrency) { - return this._displayAmount(secondaryCurrency, this.props.buyQuoteInfo.totalEthAmount); - } else { - return undefined; - } - } - - private _displayAmountOrPlaceholder(weiAmount?: BigNumber): React.ReactNode { - const { baseCurrency, isLoading } = this.props; - - if (_.isUndefined(weiAmount)) { - return ( - - - - ); - } - - return this._displayAmount(baseCurrency, weiAmount); - } - - private _displayAmount(currency: BaseCurrency, weiAmount: BigNumber): React.ReactNode { - switch (currency) { - case BaseCurrency.USD: - return format.ethBaseUnitAmountInUsd(weiAmount, this.props.ethUsdPrice, 2, ''); - case BaseCurrency.ETH: - return format.ethBaseUnitAmount(weiAmount, 4, ''); - } - } - - private _assetAmountLabel(): React.ReactNode { - const { assetName, baseCurrency } = this.props; - const numTokens = this.props.selectedAssetUnitAmount; - - // Display as 0 if we have a selected asset - const displayNumTokens = - assetName && assetName !== DEFAULT_UNKOWN_ASSET_NAME && _.isUndefined(numTokens) - ? new BigNumber(0) - : numTokens; - if (!_.isUndefined(displayNumTokens)) { - let numTokensWithSymbol: React.ReactNode = displayNumTokens.toString(); - if (assetName) { - numTokensWithSymbol += ` ${assetName}`; - } - const pricePerTokenWei = this._pricePerTokenWei(); - if (pricePerTokenWei) { - const atPriceDisplay = ( - - @ {this._displayAmount(baseCurrency, pricePerTokenWei)} - - ); - numTokensWithSymbol = ( - - {numTokensWithSymbol} {atPriceDisplay} - - ); - } - return numTokensWithSymbol; - } - return 'Token Amount'; - } - - private _pricePerTokenWei(): BigNumber | undefined { - const buyQuoteAccessor = oc(this.props.buyQuoteInfo); - const assetTotalInWei = buyQuoteAccessor.assetEthAmount(); - const selectedAssetUnitAmount = this.props.selectedAssetUnitAmount; - return !_.isUndefined(assetTotalInWei) && - !_.isUndefined(selectedAssetUnitAmount) && - !selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO) - ? assetTotalInWei.div(selectedAssetUnitAmount).integerValue(BigNumber.ROUND_CEIL) - : undefined; - } - - private _baseCurrencyChoice(choice: BaseCurrency): React.ReactNode { - const onClick = - choice === BaseCurrency.ETH ? this.props.onBaseCurrencySwitchEth : this.props.onBaseCurrencySwitchUsd; - const isSelected = this.props.baseCurrency === choice; - - const textStyle: TextProps = { onClick, fontSize: '12px' }; - if (isSelected) { - textStyle.fontColor = ColorOption.primaryColor; - textStyle.fontWeight = 700; - } else { - textStyle.fontColor = ColorOption.lightGrey; - } - return {choice}; - } - - private _renderHeader(): React.ReactNode { - return ( - - Order Details - - {this._baseCurrencyChoice(BaseCurrency.ETH)} - - - / - - - {this._baseCurrencyChoice(BaseCurrency.USD)} - - - ); - } -} - -export interface OrderDetailsRowProps { - labelText: React.ReactNode; - isLabelBold?: boolean; - isPrimaryValueBold?: boolean; - primaryValue: React.ReactNode; - secondaryValue?: React.ReactNode; -} -export class OrderDetailsRow extends React.PureComponent { - public render(): React.ReactNode { - return ( - - - - {this.props.labelText} - - {this._renderValues()} - - - ); - } - - private _renderValues(): React.ReactNode { - const secondaryValueNode: React.ReactNode = this.props.secondaryValue && ( - - ({this.props.secondaryValue}) - - ); - return ( - - {secondaryValueNode} - {this.props.primaryValue} - - ); - } -} diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx deleted file mode 100644 index ada9f7bab..000000000 --- a/packages/instant/src/components/payment_method.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; -import { Account, AccountState, Network } from '../types'; -import { envUtil } from '../util/env'; - -import { CoinbaseWalletLogo } from './coinbase_wallet_logo'; -import { MetaMaskLogo } from './meta_mask_logo'; -import { PaymentMethodDropdown } from './payment_method_dropdown'; -import { SectionHeader } from './section_header'; -import { Circle } from './ui/circle'; -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Icon } from './ui/icon'; -import { Text } from './ui/text'; -import { WalletPrompt } from './wallet_prompt'; - -export interface PaymentMethodProps { - account: Account; - network: Network; - walletDisplayName: string; - onInstallWalletClick: () => void; - onUnlockWalletClick: () => void; -} - -export class PaymentMethod extends React.PureComponent { - public render(): React.ReactNode { - return ( - - - - {this._renderTitleText()} - {this._renderTitleLabel()} - - - {this._renderMainContent()} - - ); - } - private readonly _renderTitleText = (): string => { - const { account } = this.props; - switch (account.state) { - case AccountState.Loading: - return 'loading...'; - case AccountState.Locked: - case AccountState.None: - return 'connect your wallet'; - case AccountState.Ready: - return 'payment method'; - } - }; - private readonly _renderTitleLabel = (): React.ReactNode => { - const { account } = this.props; - if (account.state === AccountState.Ready || account.state === AccountState.Locked) { - const circleColor: ColorOption = account.state === AccountState.Ready ? ColorOption.green : ColorOption.red; - return ( - - - - - {this.props.walletDisplayName} - - - - ); - } - return null; - }; - private readonly _renderMainContent = (): React.ReactNode => { - const { account, network } = this.props; - const isMobile = envUtil.isMobileOperatingSystem(); - const logo = isMobile ? : ; - const primaryColor = isMobile ? ColorOption.darkBlue : ColorOption.darkOrange; - const secondaryColor = isMobile ? ColorOption.lightBlue : ColorOption.lightOrange; - const colors = { primaryColor, secondaryColor }; - switch (account.state) { - case AccountState.Loading: - return null; - case AccountState.Locked: - return ( - - - - } - {...colors} - > - Click to Connect {this.props.walletDisplayName} - - ); - case AccountState.None: - return ( - - {isMobile ? 'Install Coinbase Wallet' : 'Install MetaMask'} - - ); - case AccountState.Ready: - return ( - - ); - } - }; -} diff --git a/packages/instant/src/components/payment_method_dropdown.tsx b/packages/instant/src/components/payment_method_dropdown.tsx deleted file mode 100644 index e463e3eae..000000000 --- a/packages/instant/src/components/payment_method_dropdown.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as copy from 'copy-to-clipboard'; -import * as React from 'react'; - -import { Network } from '../types'; -import { analytics } from '../util/analytics'; -import { envUtil } from '../util/env'; -import { etherscanUtil } from '../util/etherscan'; -import { format } from '../util/format'; - -import { Dropdown, DropdownItemConfig } from './ui/dropdown'; - -export interface PaymentMethodDropdownProps { - accountAddress: string; - accountEthBalanceInWei?: BigNumber; - network: Network; -} - -export class PaymentMethodDropdown extends React.PureComponent { - public render(): React.ReactNode { - const { accountAddress, accountEthBalanceInWei } = this.props; - const value = format.ethAddress(accountAddress); - const label = format.ethBaseUnitAmount(accountEthBalanceInWei, 4, '') as string; - return ( - - ); - } - private readonly _getDropdownItemConfigs = (): DropdownItemConfig[] => { - if (envUtil.isMobileOperatingSystem()) { - return []; - } - const viewOnEtherscan = { - text: 'View on Etherscan', - onClick: this._handleEtherscanClick, - }; - const copyAddressToClipboard = { - text: 'Copy address to clipboard', - onClick: this._handleCopyToClipboardClick, - }; - return [viewOnEtherscan, copyAddressToClipboard]; - }; - private readonly _handleEtherscanClick = (): void => { - analytics.trackPaymentMethodOpenedEtherscan(); - - const { accountAddress, network } = this.props; - const etherscanUrl = etherscanUtil.getEtherScanEthAddressIfExists(accountAddress, network); - window.open(etherscanUrl, '_blank'); - }; - private readonly _handleCopyToClipboardClick = (): void => { - analytics.trackPaymentMethodCopiedAddress(); - - const { accountAddress } = this.props; - copy(accountAddress); - }; -} diff --git a/packages/instant/src/components/placing_order_button.tsx b/packages/instant/src/components/placing_order_button.tsx deleted file mode 100644 index 528a305dc..000000000 --- a/packages/instant/src/components/placing_order_button.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; - -import { Button } from './ui/button'; -import { Container } from './ui/container'; -import { Spinner } from './ui/spinner'; - -export const PlacingOrderButton: React.StatelessComponent<{}> = props => ( - -); - -PlacingOrderButton.displayName = 'PlacingOrderButton'; diff --git a/packages/instant/src/components/scaling_amount_input.tsx b/packages/instant/src/components/scaling_amount_input.tsx deleted file mode 100644 index 7dc1fdc0c..000000000 --- a/packages/instant/src/components/scaling_amount_input.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; - -import { Maybe } from '../types'; - -import { GIT_SHA, MAGIC_TRIGGER_ERROR_INPUT, MAGIC_TRIGGER_ERROR_MESSAGE, NPM_PACKAGE_VERSION } from '../constants'; -import { ColorOption } from '../style/theme'; -import { maybeBigNumberUtil } from '../util/maybe_big_number'; -import { util } from '../util/util'; - -import { ScalingInput } from './scaling_input'; - -export interface ScalingAmountInputProps { - isDisabled: boolean; - maxFontSizePx: number; - textLengthThreshold: number; - fontColor?: ColorOption; - value?: BigNumber; - onAmountChange: (value?: BigNumber) => void; - onFontSizeChange: (fontSizePx: number) => void; - hasAutofocus: boolean; -} -interface ScalingAmountInputState { - stringValue: string; -} - -const { stringToMaybeBigNumber, areMaybeBigNumbersEqual } = maybeBigNumberUtil; -export class ScalingAmountInput extends React.PureComponent { - public static defaultProps = { - onAmountChange: util.boundNoop, - onFontSizeChange: util.boundNoop, - isDisabled: false, - hasAutofocus: false, - }; - public constructor(props: ScalingAmountInputProps) { - super(props); - this.state = { - stringValue: _.isUndefined(props.value) ? '' : props.value.toString(), - }; - } - public componentDidUpdate(): void { - const parsedStateValue = stringToMaybeBigNumber(this.state.stringValue); - const currentValue = this.props.value; - - if (!areMaybeBigNumbersEqual(parsedStateValue, currentValue)) { - // we somehow got into the state in which the value passed in and the string value - // in state have differed, reset state - // we dont expect to ever get into this state, but let's make sure - // we reset if we do since we're dealing with important numbers - this.setState({ - stringValue: _.isUndefined(currentValue) ? '' : currentValue.toString(), - }); - } - } - - public render(): React.ReactNode { - const { textLengthThreshold, fontColor, maxFontSizePx, onFontSizeChange } = this.props; - return ( - - ); - } - private readonly _handleChange = (event: React.ChangeEvent): void => { - if (event.target.value === MAGIC_TRIGGER_ERROR_INPUT) { - throw new Error(`${MAGIC_TRIGGER_ERROR_MESSAGE} git: ${GIT_SHA}, npm: ${NPM_PACKAGE_VERSION}`); - } - - const sanitizedValue = event.target.value.replace(/[^0-9.]/g, ''); // only allow numbers and "." - this.setState({ - stringValue: sanitizedValue, - }); - - // Trigger onAmountChange with a valid BigNumber, or undefined if the sanitizedValue is invalid or empty - const bigNumberValue: Maybe = _.isEmpty(sanitizedValue) - ? undefined - : stringToMaybeBigNumber(sanitizedValue); - - this.props.onAmountChange(bigNumberValue); - }; -} diff --git a/packages/instant/src/components/scaling_input.tsx b/packages/instant/src/components/scaling_input.tsx deleted file mode 100644 index c31de1fb5..000000000 --- a/packages/instant/src/components/scaling_input.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { ObjectMap } from '@0x/types'; -import * as _ from 'lodash'; -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; -import { util } from '../util/util'; - -import { Input } from './ui/input'; - -export enum ScalingInputPhase { - FixedFontSize, - ScalingFontSize, -} - -export interface ScalingSettings { - percentageToReduceFontSizePerCharacter: number; - // 1ch = the width of the 0 chararacter. - // Allow to customize 'char' length for different characters. - characterWidthOverrides: ObjectMap; - // How much room to leave to the right of the scaling input. - additionalInputSpaceInCh: number; -} - -export interface ScalingInputProps { - type?: string; - textLengthThreshold: number; - maxFontSizePx: number; - value: string; - emptyInputWidthCh: number; - onChange: (event: React.ChangeEvent) => void; - onFontSizeChange: (fontSizePx: number) => void; - fontColor?: ColorOption; - placeholder?: string; - maxLength?: number; - scalingSettings: ScalingSettings; - isDisabled: boolean; - hasAutofocus: boolean; -} - -export interface ScalingInputSnapshot { - inputWidthPx: number; -} - -// These are magic numbers that were determined experimentally. -const defaultScalingSettings: ScalingSettings = { - percentageToReduceFontSizePerCharacter: 0.1, - characterWidthOverrides: { - '1': 0.7, - '.': 0.4, - }, - additionalInputSpaceInCh: 0.4, -}; - -export class ScalingInput extends React.PureComponent { - public static defaultProps = { - onChange: util.boundNoop, - onFontSizeChange: util.boundNoop, - maxLength: 9, - scalingSettings: defaultScalingSettings, - isDisabled: false, - hasAutofocus: false, - }; - private readonly _inputRef = React.createRef(); - public static getPhase(textLengthThreshold: number, value: string): ScalingInputPhase { - if (value.length <= textLengthThreshold) { - return ScalingInputPhase.FixedFontSize; - } - return ScalingInputPhase.ScalingFontSize; - } - public static getPhaseFromProps(props: ScalingInputProps): ScalingInputPhase { - const { value, textLengthThreshold } = props; - return ScalingInput.getPhase(textLengthThreshold, value); - } - public static calculateFontSize( - textLengthThreshold: number, - maxFontSizePx: number, - phase: ScalingInputPhase, - value: string, - percentageToReduceFontSizePerCharacter: number, - ): number { - if (phase !== ScalingInputPhase.ScalingFontSize) { - return maxFontSizePx; - } - const charactersOverMax = value.length - textLengthThreshold; - const scalingFactor = (1 - percentageToReduceFontSizePerCharacter) ** charactersOverMax; - const fontSize = scalingFactor * maxFontSizePx; - return fontSize; - } - public static calculateFontSizeFromProps(props: ScalingInputProps, phase: ScalingInputPhase): number { - const { textLengthThreshold, value, maxFontSizePx, scalingSettings } = props; - return ScalingInput.calculateFontSize( - textLengthThreshold, - maxFontSizePx, - phase, - value, - scalingSettings.percentageToReduceFontSizePerCharacter, - ); - } - public componentDidMount(): void { - // Trigger an initial notification of the calculated fontSize. - const currentPhase = ScalingInput.getPhaseFromProps(this.props); - const currentFontSize = ScalingInput.calculateFontSizeFromProps(this.props, currentPhase); - this.props.onFontSizeChange(currentFontSize); - } - public componentDidUpdate(prevProps: ScalingInputProps): void { - const prevPhase = ScalingInput.getPhaseFromProps(prevProps); - const curPhase = ScalingInput.getPhaseFromProps(this.props); - const prevFontSize = ScalingInput.calculateFontSizeFromProps(prevProps, prevPhase); - const curFontSize = ScalingInput.calculateFontSizeFromProps(this.props, curPhase); - // If font size has changed, notify. - if (prevFontSize !== curFontSize) { - this.props.onFontSizeChange(curFontSize); - } - } - public render(): React.ReactNode { - const { type, hasAutofocus, isDisabled, fontColor, placeholder, value, maxLength } = this.props; - const phase = ScalingInput.getPhaseFromProps(this.props); - return ( - - ); - } - private readonly _calculateWidth = (phase: ScalingInputPhase): string => { - const { value, scalingSettings } = this.props; - if (_.isEmpty(value)) { - return `${this.props.emptyInputWidthCh}ch`; - } - const lengthInCh = _.reduce( - value.split(''), - (sum, char) => { - const widthOverride = scalingSettings.characterWidthOverrides[char]; - if (!_.isUndefined(widthOverride)) { - // tslint is confused - // tslint:disable-next-line:restrict-plus-operands - return sum + widthOverride; - } - return sum + 1; - }, - scalingSettings.additionalInputSpaceInCh, - ); - return `${lengthInCh}ch`; - }; - private readonly _calculateFontSize = (phase: ScalingInputPhase): number => { - return ScalingInput.calculateFontSizeFromProps(this.props, phase); - }; - private readonly _handleChange = (event: React.ChangeEvent): void => { - const value = event.target.value; - const { maxLength } = this.props; - if (!_.isUndefined(value) && !_.isUndefined(maxLength) && value.length > maxLength) { - return; - } - this.props.onChange(event); - }; -} diff --git a/packages/instant/src/components/search_input.tsx b/packages/instant/src/components/search_input.tsx deleted file mode 100644 index 71bc18915..000000000 --- a/packages/instant/src/components/search_input.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Icon } from './ui/icon'; -import { Input, InputProps } from './ui/input'; - -export interface SearchInputProps extends InputProps { - backgroundColor?: ColorOption; -} - -export const SearchInput: React.StatelessComponent = props => ( - - - - - - -); - -SearchInput.displayName = 'SearchInput'; - -SearchInput.defaultProps = { - backgroundColor: ColorOption.lightestGrey, - fontColor: ColorOption.grey, -}; diff --git a/packages/instant/src/components/secondary_button.tsx b/packages/instant/src/components/secondary_button.tsx deleted file mode 100644 index 0714ce287..000000000 --- a/packages/instant/src/components/secondary_button.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; - -import { Button, ButtonProps } from './ui/button'; - -export interface SecondaryButtonProps extends ButtonProps {} - -export const SecondaryButton: React.StatelessComponent = props => { - const buttonProps = _.omit(props, 'text'); - return ( - - ); -}; -SecondaryButton.defaultProps = { - width: '100%', -}; -SecondaryButton.displayName = 'SecondaryButton'; diff --git a/packages/instant/src/components/section_header.tsx b/packages/instant/src/components/section_header.tsx deleted file mode 100644 index 2185b67ba..000000000 --- a/packages/instant/src/components/section_header.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; - -import { Text } from './ui/text'; - -export interface SectionHeaderProps {} -export const SectionHeader: React.StatelessComponent = props => { - return ( - - {props.children} - - ); -}; -SectionHeader.displayName = 'SectionHeader'; diff --git a/packages/instant/src/components/sliding_error.tsx b/packages/instant/src/components/sliding_error.tsx deleted file mode 100644 index c7c6732cf..000000000 --- a/packages/instant/src/components/sliding_error.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import * as React from 'react'; - -import { ScreenSpecification } from '../style/media'; -import { ColorOption } from '../style/theme'; -import { zIndex } from '../style/z_index'; -import { SlideAnimationState } from '../types'; - -import { PositionAnimationSettings } from './animations/position_animation'; -import { SlideAnimation } from './animations/slide_animation'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text } from './ui/text'; - -export interface ErrorProps { - icon: string; - message: string; -} - -export const Error: React.StatelessComponent = props => ( - - - - {props.icon} - - - {props.message} - - - -); - -Error.displayName = 'Error'; - -export interface SlidingErrorProps extends ErrorProps { - animationState: SlideAnimationState; -} -export const SlidingError: React.StatelessComponent = props => { - const slideAmount = '120px'; - - const desktopSlideIn: PositionAnimationSettings = { - timingFunction: 'ease-in', - top: { - from: slideAmount, - to: '0px', - }, - position: 'relative', - }; - const desktopSlideOut: PositionAnimationSettings = { - timingFunction: 'cubic-bezier(0.25, 0.1, 0.25, 1)', - top: { - from: '0px', - to: slideAmount, - }, - position: 'relative', - }; - - const mobileSlideIn: PositionAnimationSettings = { - duration: '0.5s', - timingFunction: 'ease-in', - top: { from: '-120px', to: '0px' }, - position: 'fixed', - }; - const moblieSlideOut: PositionAnimationSettings = { - duration: '0.5s', - timingFunction: 'ease-in', - top: { from: '0px', to: '-120px' }, - position: 'fixed', - }; - - const slideUpSettings: ScreenSpecification = { - default: desktopSlideIn, - sm: mobileSlideIn, - }; - const slideOutSettings: ScreenSpecification = { - default: desktopSlideOut, - sm: moblieSlideOut, - }; - - return ( - - - - ); -}; - -SlidingError.displayName = 'SlidingError'; diff --git a/packages/instant/src/components/sliding_panel.tsx b/packages/instant/src/components/sliding_panel.tsx deleted file mode 100644 index 9b09a0d80..000000000 --- a/packages/instant/src/components/sliding_panel.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; -import { zIndex } from '../style/z_index'; -import { SlideAnimationState } from '../types'; - -import { PositionAnimationSettings } from './animations/position_animation'; -import { SlideAnimation } from './animations/slide_animation'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Icon } from './ui/icon'; - -export interface PanelProps { - onClose?: () => void; -} - -export const Panel: React.StatelessComponent = ({ children, onClose }) => ( - - - - - - {children} - - -); - -Panel.displayName = 'Panel'; - -export interface SlidingPanelProps extends PanelProps { - animationState: SlideAnimationState; - onAnimationEnd?: () => void; -} - -export class SlidingPanel extends React.PureComponent { - public render(): React.ReactNode { - if (this.props.animationState === 'none') { - return null; - } - const { animationState, onAnimationEnd, ...rest } = this.props; - const slideAmount = '100%'; - const slideUpSettings: PositionAnimationSettings = { - duration: '0.3s', - timingFunction: 'ease-in-out', - top: { - from: slideAmount, - to: '0px', - }, - position: 'absolute', - }; - const slideDownSettings: PositionAnimationSettings = { - duration: '0.3s', - timingFunction: 'ease-out', - top: { - from: '0px', - to: slideAmount, - }, - position: 'absolute', - }; - return ( - - - - ); - } -} diff --git a/packages/instant/src/components/standard_panel_content.tsx b/packages/instant/src/components/standard_panel_content.tsx deleted file mode 100644 index f2987df82..000000000 --- a/packages/instant/src/components/standard_panel_content.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; -import { util } from '../util/util'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text } from './ui/text'; - -export interface MoreInfoSettings { - text: string; - href: string; - onClick?: () => void; -} - -export interface StandardPanelContentProps { - image: React.ReactNode; - title?: string; - description: string; - moreInfoSettings?: MoreInfoSettings; - action: React.ReactNode; -} - -const SPACING_BETWEEN_PX = '20px'; - -const onMoreInfoClick = (href: string, onClick?: () => void) => { - return () => { - if (onClick) { - onClick(); - } - util.createOpenUrlInNewWindow(href)(); - }; -}; - -export const StandardPanelContent: React.StatelessComponent = ({ - image, - title, - description, - moreInfoSettings, - action, -}) => ( - - - {image} - {title && ( - - - {title} - - - )} - - - {description} - - - - {moreInfoSettings && ( - - {moreInfoSettings.text} - - )} - - - {action} - -); - -StandardPanelContent.displayName = 'StandardPanelContent'; diff --git a/packages/instant/src/components/standard_sliding_panel.tsx b/packages/instant/src/components/standard_sliding_panel.tsx deleted file mode 100644 index bcc9d3dce..000000000 --- a/packages/instant/src/components/standard_sliding_panel.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as React from 'react'; - -import { StandardSlidingPanelContent, StandardSlidingPanelSettings } from '../types'; - -import { InstallWalletPanelContent } from './install_wallet_panel_content'; -import { SlidingPanel } from './sliding_panel'; - -export interface StandardSlidingPanelProps extends StandardSlidingPanelSettings { - onClose: () => void; -} - -export class StandardSlidingPanel extends React.PureComponent { - public render(): React.ReactNode { - const { animationState, content, onClose } = this.props; - return ( - - {this._getNodeForContent(content)} - - ); - } - private readonly _getNodeForContent = (content: StandardSlidingPanelContent): React.ReactNode => { - switch (content) { - case StandardSlidingPanelContent.InstallWallet: - return ; - case StandardSlidingPanelContent.None: - return null; - } - }; -} diff --git a/packages/instant/src/components/time_counter.tsx b/packages/instant/src/components/time_counter.tsx deleted file mode 100644 index 93dc497d5..000000000 --- a/packages/instant/src/components/time_counter.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import * as React from 'react'; - -import { ONE_SECOND_MS } from '../constants'; -import { ColorOption } from '../style/theme'; -import { timeUtil } from '../util/time'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text } from './ui/text'; - -export interface TimeCounterProps { - estimatedTimeMs: number; - hasEnded: boolean; -} -interface TimeCounterState { - elapsedSeconds: number; -} - -export class TimeCounter extends React.PureComponent { - public state = { - elapsedSeconds: 0, - }; - private _timerId?: number; - - public componentDidMount(): void { - this._setupTimerBasedOnProps(); - } - - public componentWillUnmount(): void { - this._clearTimer(); - } - - public componentDidUpdate(prevProps: TimeCounterProps): void { - if (prevProps.hasEnded !== this.props.hasEnded) { - this._setupTimerBasedOnProps(); - } - } - - public render(): React.ReactNode { - const estimatedTimeSeconds = this.props.estimatedTimeMs / ONE_SECOND_MS; - return ( - - - - - Est. Time - - - - ({timeUtil.secondsToHumanDescription(estimatedTimeSeconds)}) - - - - Time: {timeUtil.secondsToStopwatchTime(this.state.elapsedSeconds)} - - - ); - } - - private _setupTimerBasedOnProps(): void { - this.props.hasEnded ? this._clearTimer() : this._newTimer(); - } - - private _newTimer(): void { - this._clearTimer(); - this._timerId = window.setInterval(() => { - this.setState({ - elapsedSeconds: this.state.elapsedSeconds + 1, - }); - }, ONE_SECOND_MS); - } - - private _clearTimer(): void { - if (this._timerId) { - window.clearInterval(this._timerId); - } - } -} diff --git a/packages/instant/src/components/timed_progress_bar.tsx b/packages/instant/src/components/timed_progress_bar.tsx deleted file mode 100644 index 287269af7..000000000 --- a/packages/instant/src/components/timed_progress_bar.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import * as _ from 'lodash'; -import { transparentize } from 'polished'; -import * as React from 'react'; - -import { PROGRESS_FINISH_ANIMATION_TIME_MS, PROGRESS_STALL_AT_WIDTH } from '../constants'; -import { ColorOption, css, keyframes, styled, ThemeConsumer } from '../style/theme'; - -import { Container } from './ui/container'; - -export interface TimedProgressBarProps { - expectedTimeMs: number; - hasEnded: boolean; -} - -/** - * Timed Progress Bar - * Goes from 0% -> PROGRESS_STALL_AT_WIDTH over time of expectedTimeMs - * When hasEnded set to true, goes to 100% through animation of PROGRESS_FINISH_ANIMATION_TIME_MS length of time - */ -export class TimedProgressBar extends React.PureComponent { - private readonly _barRef = React.createRef(); - - public render(): React.ReactNode { - const widthAnimationSettings = this._calculateWidthAnimationSettings(); - return ; - } - - private _calculateWidthAnimationSettings(): WidthAnimationSettings { - if (this.props.hasEnded) { - if (!this._barRef.current) { - throw new Error('ended but no reference'); - } - const fromWidth = `${this._barRef.current.offsetWidth}px`; - return { - timeMs: PROGRESS_FINISH_ANIMATION_TIME_MS, - fromWidth, - toWidth: '100%', - }; - } - - return { - timeMs: this.props.expectedTimeMs, - fromWidth: '0px', - toWidth: PROGRESS_STALL_AT_WIDTH, - }; - } -} - -const expandingWidthKeyframes = (fromWidth: string, toWidth: string) => { - return keyframes` - from { - width: ${fromWidth}; - } - to { - width: ${toWidth}; - } - `; -}; - -export interface WidthAnimationSettings { - timeMs: number; - fromWidth: string; - toWidth: string; -} - -interface ProgressProps { - width?: string; - animationSettings?: WidthAnimationSettings; -} - -export const Progress = styled.div` - && { - background-color: ${props => props.theme[ColorOption.primaryColor]}; - border-radius: 6px; - height: 6px; - ${props => (props.width ? `width: ${props.width};` : '')} - ${props => - props.animationSettings - ? css` - animation: ${expandingWidthKeyframes( - props.animationSettings.fromWidth, - props.animationSettings.toWidth, - )} - ${props.animationSettings.timeMs}ms linear 1 forwards; - ` - : ''} - } -`; - -export interface ProgressBarProps extends ProgressProps {} - -export const ProgressBar: React.ComponentType> = React.forwardRef( - (props, ref) => ( - - {theme => ( - - - - )} - - ), -); diff --git a/packages/instant/src/components/ui/button.tsx b/packages/instant/src/components/ui/button.tsx deleted file mode 100644 index e77b1b5d1..000000000 --- a/packages/instant/src/components/ui/button.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { darken, saturate } from 'polished'; -import * as React from 'react'; - -import { ColorOption, styled } from '../../style/theme'; -import { util } from '../../util/util'; - -export type ButtonOnClickHandler = (event: React.MouseEvent) => void; - -export interface ButtonProps { - backgroundColor?: ColorOption; - borderColor?: ColorOption; - fontColor?: ColorOption; - fontSize?: string; - width?: string; - padding?: string; - type?: string; - isDisabled?: boolean; - href?: string; - onClick?: ButtonOnClickHandler; - className?: string; -} - -const PlainButton: React.StatelessComponent = ({ - children, - isDisabled, - onClick, - href, - type, - className, -}) => { - const computedOnClick = isDisabled ? undefined : href ? util.createOpenUrlInNewWindow(href) : onClick; - return ( - - ); -}; - -const darkenOnHoverAmount = 0.1; -const darkenOnActiveAmount = 0.2; -const saturateOnFocusAmount = 0.2; -export const Button = styled(PlainButton)` - && { - all: initial; - box-sizing: border-box; - font-size: ${props => props.fontSize}; - font-family: 'Inter UI', sans-serif; - font-weight: 500; - color: ${props => props.fontColor && props.theme[props.fontColor]}; - cursor: ${props => (props.isDisabled ? 'default' : 'pointer')}; - transition: background-color, opacity 0.5s ease; - padding: ${props => props.padding}; - border-radius: 3px; - text-align: center; - outline: none; - width: ${props => props.width}; - background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')}; - border: ${props => (props.borderColor ? `1px solid ${props.theme[props.borderColor]}` : 'none')}; - &:hover { - background-color: ${props => - !props.isDisabled - ? darken(darkenOnHoverAmount, props.theme[props.backgroundColor || 'white']) - : ''} !important; - } - &:active { - background-color: ${props => - !props.isDisabled ? darken(darkenOnActiveAmount, props.theme[props.backgroundColor || 'white']) : ''}; - } - &:disabled { - opacity: 0.5; - } - &:focus { - background-color: ${props => - saturate(saturateOnFocusAmount, props.theme[props.backgroundColor || 'white'])}; - } - } -`; - -Button.defaultProps = { - backgroundColor: ColorOption.primaryColor, - width: 'auto', - isDisabled: false, - padding: '.82em 1.2em', - fontSize: '16px', -}; - -Button.displayName = 'Button'; diff --git a/packages/instant/src/components/ui/circle.tsx b/packages/instant/src/components/ui/circle.tsx deleted file mode 100644 index e4f2c5260..000000000 --- a/packages/instant/src/components/ui/circle.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { ColorOption, styled, Theme, withTheme } from '../../style/theme'; - -export interface CircleProps { - diameter: number; - rawColor?: string; - color?: ColorOption; - theme: Theme; -} - -export const Circle = withTheme( - styled.div` - && { - width: ${props => props.diameter}px; - height: ${props => props.diameter}px; - background-color: ${props => - props.rawColor ? props.rawColor : props.theme[props.color || ColorOption.white]}; - border-radius: 50%; - } - `, -); - -Circle.displayName = 'Circle'; - -Circle.defaultProps = { - color: ColorOption.white, -}; diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx deleted file mode 100644 index 59b733f3e..000000000 --- a/packages/instant/src/components/ui/container.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { darken } from 'polished'; - -import { MediaChoice, stylesForMedia } from '../../style/media'; -import { ColorOption, styled } from '../../style/theme'; -import { cssRuleIfExists } from '../../style/util'; - -export interface ContainerProps { - display?: MediaChoice; - position?: string; - top?: string; - right?: string; - bottom?: string; - left?: string; - width?: MediaChoice; - height?: MediaChoice; - maxWidth?: string; - margin?: string; - marginTop?: string; - marginRight?: string; - marginBottom?: string; - marginLeft?: string; - padding?: string; - borderRadius?: MediaChoice; - border?: string; - borderColor?: ColorOption; - borderTop?: string; - borderBottom?: string; - className?: string; - backgroundColor?: ColorOption; - rawBackgroundColor?: string; - hasBoxShadow?: boolean; - isHidden?: boolean; - zIndex?: number; - whiteSpace?: string; - opacity?: number; - cursor?: string; - overflow?: string; - darkenOnHover?: boolean; - rawHoverColor?: string; - boxShadowOnHover?: boolean; - flexGrow?: string | number; -} - -const getBackgroundColor = (theme: any, backgroundColor?: ColorOption, rawBackgroundColor?: string): string => { - if (backgroundColor) { - return theme[backgroundColor] as string; - } - if (rawBackgroundColor) { - return rawBackgroundColor; - } - return 'none'; -}; - -export const Container = styled.div` - && { - box-sizing: border-box; - ${props => cssRuleIfExists(props, 'flex-grow')} - ${props => cssRuleIfExists(props, 'position')} - ${props => cssRuleIfExists(props, 'top')} - ${props => cssRuleIfExists(props, 'right')} - ${props => cssRuleIfExists(props, 'bottom')} - ${props => cssRuleIfExists(props, 'left')} - ${props => cssRuleIfExists(props, 'max-width')} - ${props => cssRuleIfExists(props, 'margin')} - ${props => cssRuleIfExists(props, 'margin-top')} - ${props => cssRuleIfExists(props, 'margin-right')} - ${props => cssRuleIfExists(props, 'margin-bottom')} - ${props => cssRuleIfExists(props, 'margin-left')} - ${props => cssRuleIfExists(props, 'padding')} - ${props => cssRuleIfExists(props, 'border')} - ${props => cssRuleIfExists(props, 'border-top')} - ${props => cssRuleIfExists(props, 'border-bottom')} - ${props => cssRuleIfExists(props, 'z-index')} - ${props => cssRuleIfExists(props, 'white-space')} - ${props => cssRuleIfExists(props, 'opacity')} - ${props => cssRuleIfExists(props, 'cursor')} - ${props => cssRuleIfExists(props, 'overflow')} - ${props => (props.overflow === 'scroll' ? `-webkit-overflow-scrolling: touch` : '')}; - ${props => (props.hasBoxShadow ? `box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)` : '')}; - ${props => props.display && stylesForMedia('display', props.display)} - ${props => props.width && stylesForMedia('width', props.width)} - ${props => props.height && stylesForMedia('height', props.height)} - ${props => props.borderRadius && stylesForMedia('border-radius', props.borderRadius)} - ${props => (props.isHidden ? 'visibility: hidden;' : '')} - background-color: ${props => getBackgroundColor(props.theme, props.backgroundColor, props.rawBackgroundColor)}; - border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')}; - &:hover { - ${props => (props.rawHoverColor ? `background-color: ${props.rawHoverColor}` : '')} - ${props => - props.darkenOnHover - ? `background-color: ${ - props.backgroundColor ? darken(0.05, props.theme[props.backgroundColor]) : 'none' - }` - : ''}; - ${props => (props.boxShadowOnHover ? 'box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)' : '')}; - } - } -`; - -Container.defaultProps = { - display: 'block', -}; - -Container.displayName = 'Container'; diff --git a/packages/instant/src/components/ui/dropdown.tsx b/packages/instant/src/components/ui/dropdown.tsx deleted file mode 100644 index 8788d3d59..000000000 --- a/packages/instant/src/components/ui/dropdown.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import * as _ from 'lodash'; -import { transparentize } from 'polished'; -import * as React from 'react'; - -import { ColorOption, completelyTransparent, ThemeConsumer } from '../../style/theme'; -import { zIndex } from '../../style/z_index'; - -import { Container } from './container'; -import { Flex } from './flex'; -import { Icon } from './icon'; -import { Overlay } from './overlay'; -import { Text } from './text'; - -export interface DropdownItemConfig { - text: string; - onClick?: () => void; -} - -export interface DropdownProps { - value: string; - label?: string; - items: DropdownItemConfig[]; - onOpen?: () => void; -} - -export interface DropdownState { - isOpen: boolean; -} - -export class Dropdown extends React.PureComponent { - public static defaultProps = { - items: [], - }; - public state: DropdownState = { - isOpen: false, - }; - public render(): React.ReactNode { - const { value, label, items } = this.props; - const { isOpen } = this.state; - const hasItems = !_.isEmpty(items); - const borderRadius = isOpen ? '4px 4px 0px 0px' : '4px'; - return ( - - {isOpen && ( - - )} - - - - - {value} - - - {label && ( - - {label} - - )} - {hasItems && ( - - - - )} - - - - {isOpen && ( - - {_.map(items, (item, index) => ( - - ))} - - )} - - - ); - } - private readonly _handleDropdownClick = (): void => { - if (_.isEmpty(this.props.items)) { - return; - } - const isOpen = !this.state.isOpen; - this.setState({ - isOpen, - }); - - if (isOpen && this.props.onOpen) { - this.props.onOpen(); - } - }; - private readonly _closeDropdown = (): void => { - this.setState({ - isOpen: false, - }); - }; -} - -export interface DropdownItemProps extends DropdownItemConfig { - text: string; - onClick?: () => void; - isLast: boolean; -} - -export const DropdownItem: React.StatelessComponent = ({ text, onClick, isLast }) => ( - - {theme => ( - - - {text} - - - )} - -); - -DropdownItem.displayName = 'DropdownItem'; diff --git a/packages/instant/src/components/ui/flex.tsx b/packages/instant/src/components/ui/flex.tsx deleted file mode 100644 index 145e654f1..000000000 --- a/packages/instant/src/components/ui/flex.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { MediaChoice, stylesForMedia } from '../../style/media'; -import { ColorOption, styled } from '../../style/theme'; -import { cssRuleIfExists } from '../../style/util'; - -export interface FlexProps { - direction?: 'row' | 'column'; - flexWrap?: 'wrap' | 'nowrap'; - justify?: 'flex-start' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'flex-end'; - align?: 'flex-start' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'flex-end'; - width?: MediaChoice; - height?: MediaChoice; - backgroundColor?: ColorOption; - inline?: boolean; - flexGrow?: number | string; -} - -export const Flex = styled.div` - && { - display: ${props => (props.inline ? 'inline-flex' : 'flex')}; - flex-direction: ${props => props.direction}; - flex-wrap: ${props => props.flexWrap}; - ${props => cssRuleIfExists(props, 'flexGrow')} - justify-content: ${props => props.justify}; - align-items: ${props => props.align}; - background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')}; - ${props => (props.width ? stylesForMedia('width', props.width) : '')} - ${props => (props.height ? stylesForMedia('height', props.height) : '')} - } -`; - -Flex.defaultProps = { - direction: 'row', - flexWrap: 'nowrap', - justify: 'center', - align: 'center', -}; - -Flex.displayName = 'Flex'; diff --git a/packages/instant/src/components/ui/icon.tsx b/packages/instant/src/components/ui/icon.tsx deleted file mode 100644 index 811142b5b..000000000 --- a/packages/instant/src/components/ui/icon.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; - -import { ColorOption, styled, Theme, withTheme } from '../../style/theme'; - -type svgRule = 'evenodd' | 'nonzero' | 'inherit'; -interface IconInfo { - viewBox: string; - path: string; - fillRule?: svgRule; - clipRule?: svgRule; - strokeOpacity?: number; - strokeWidth?: number; - strokeLinecap?: 'butt' | 'round' | 'square' | 'inherit'; - strokeLinejoin?: 'miter' | 'round' | 'bevel' | 'inherit'; -} -interface IconInfoMapping { - closeX: IconInfo; - failed: IconInfo; - success: IconInfo; - chevron: IconInfo; - search: IconInfo; - lock: IconInfo; -} -const ICONS: IconInfoMapping = { - closeX: { - viewBox: '0 0 11 11', - fillRule: 'evenodd', - clipRule: 'evenodd', - path: - 'M10.45 10.449C10.7539 10.1453 10.7539 9.65282 10.45 9.34909L6.60068 5.49999L10.45 1.65093C10.7538 1.3472 10.7538 0.854765 10.45 0.551038C10.1462 0.24731 9.65378 0.24731 9.34995 0.551038L5.50058 4.40006L1.65024 0.549939C1.34641 0.246212 0.853973 0.246212 0.550262 0.549939C0.246429 0.853667 0.246429 1.34611 0.550262 1.64983L4.40073 5.49995L0.55014 9.35019C0.246307 9.65392 0.246307 10.1464 0.55014 10.4501C0.853851 10.7538 1.34628 10.7538 1.65012 10.4501L5.5007 6.59987L9.35007 10.449C9.6539 10.7527 10.1463 10.7527 10.45 10.449Z', - }, - failed: { - viewBox: '0 0 34 34', - fillRule: 'evenodd', - clipRule: 'evenodd', - path: - 'M6.65771 26.4362C9.21777 29.2406 12.9033 31 17 31C24.7319 31 31 24.7319 31 17C31 14.4468 30.3164 12.0531 29.1226 9.99219L6.65771 26.4362ZM4.88281 24.0173C3.68555 21.9542 3 19.5571 3 17C3 9.26807 9.26807 3 17 3C21.1006 3 24.7891 4.76294 27.3496 7.57214L4.88281 24.0173ZM0 17C0 26.3888 7.61133 34 17 34C26.3887 34 34 26.3888 34 17C34 7.61121 26.3887 0 17 0C7.61133 0 0 7.61121 0 17Z', - }, - success: { - viewBox: '0 0 34 34', - fillRule: 'evenodd', - clipRule: 'evenodd', - path: - 'M17 34C26.3887 34 34 26.3888 34 17C34 7.61121 26.3887 0 17 0C7.61133 0 0 7.61121 0 17C0 26.3888 7.61133 34 17 34ZM25.7539 13.0977C26.2969 12.4718 26.2295 11.5244 25.6035 10.9817C24.9775 10.439 24.0303 10.5063 23.4878 11.1323L15.731 20.0771L12.3936 16.7438C11.8071 16.1583 10.8574 16.1589 10.272 16.7451C9.68652 17.3313 9.6875 18.281 10.2734 18.8665L14.75 23.3373L15.8887 24.4746L16.9434 23.2587L25.7539 13.0977Z', - }, - chevron: { - viewBox: '0 0 12 7', - path: 'M11 1L6 6L1 1', - strokeOpacity: 0.5, - strokeWidth: 1.5, - strokeLinecap: 'round', - strokeLinejoin: 'round', - }, - search: { - viewBox: '0 0 14 14', - fillRule: 'evenodd', - clipRule: 'evenodd', - path: - 'M8.39404 5.19727C8.39404 6.96289 6.96265 8.39453 5.19702 8.39453C3.4314 8.39453 2 6.96289 2 5.19727C2 3.43164 3.4314 2 5.19702 2C6.96265 2 8.39404 3.43164 8.39404 5.19727ZM8.09668 9.51074C7.26855 10.0684 6.27075 10.3945 5.19702 10.3945C2.3269 10.3945 0 8.06738 0 5.19727C0 2.32715 2.3269 0 5.19702 0C8.06738 0 10.394 2.32715 10.394 5.19727C10.394 6.27051 10.0686 7.26855 9.51074 8.09668L13.6997 12.2861L12.2854 13.7002L8.09668 9.51074Z', - }, - lock: { - viewBox: '0 0 13 16', - path: - 'M6.47619 0C3.79509 0 1.60489 2.21216 1.60489 4.92014V6.33135C0.717479 6.33135 0 7.05602 0 7.95232V14.379C0 15.2753 0.717479 16 1.60489 16H11.3475C12.2349 16 12.9524 15.2753 12.9524 14.379V7.95232C12.9524 7.05602 12.2349 6.33135 11.3475 6.33135V4.92014C11.3475 2.21216 9.1573 0 6.47619 0ZM9.6482 6.33135H3.30418V4.92014C3.30418 3.16567 4.72026 1.71633 6.47619 1.71633C8.23213 1.71633 9.6482 3.16567 9.6482 4.92014V6.33135Z', - }, -}; - -export interface IconProps { - className?: string; - width: number; - height?: number; - color?: ColorOption; - stroke?: ColorOption; - icon: keyof IconInfoMapping; - onClick?: (event: React.MouseEvent) => void; - padding?: string; - theme: Theme; -} -const PlainIcon: React.StatelessComponent = props => { - const iconInfo = ICONS[props.icon]; - const colorValue = _.isUndefined(props.color) ? undefined : props.theme[props.color]; - const strokeValue = _.isUndefined(props.stroke) ? undefined : props.theme[props.stroke]; - return ( -
- - - -
- ); -}; - -export const Icon = withTheme(styled(PlainIcon)` - && { - display: inline-block; - ${props => (!_.isUndefined(props.onClick) ? 'cursor: pointer' : '')}; - transition: opacity 0.5s ease; - padding: ${props => props.padding}; - opacity: ${props => (!_.isUndefined(props.onClick) ? 0.7 : 1)}; - &:hover { - opacity: 1; - } - &:active { - opacity: 1; - } - } -`); - -Icon.defaultProps = { - padding: '0em 0em', -}; - -Icon.displayName = 'Icon'; diff --git a/packages/instant/src/components/ui/input.tsx b/packages/instant/src/components/ui/input.tsx deleted file mode 100644 index 024e81b15..000000000 --- a/packages/instant/src/components/ui/input.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import * as React from 'react'; - -import { ColorOption, styled } from '../../style/theme'; - -export interface InputProps extends React.HTMLAttributes { - tabIndex?: number; - className?: string; - value?: string; - width?: string; - fontSize?: string; - fontColor?: ColorOption; - placeholder?: string; - type?: string; - onChange?: (event: React.ChangeEvent) => void; -} - -export const Input = styled.input` - && { - all: initial; - font-size: ${props => props.fontSize}; - width: ${props => props.width}; - padding: 0.1em 0em; - font-family: 'Inter UI'; - color: ${props => props.theme[props.fontColor || 'white']}; - background: transparent; - outline: none; - border: none; - &::placeholder { - color: ${props => props.theme[props.fontColor || 'white']} !important; - opacity: 0.5 !important; - } - &::-webkit-outer-spin-button, - &::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; - } - } -`; - -Input.defaultProps = { - width: 'auto', - fontColor: ColorOption.white, - fontSize: '12px', -}; - -Input.displayName = 'Input'; diff --git a/packages/instant/src/components/ui/overlay.tsx b/packages/instant/src/components/ui/overlay.tsx deleted file mode 100644 index 0b1be6a65..000000000 --- a/packages/instant/src/components/ui/overlay.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as _ from 'lodash'; - -import { generateMediaWrapper, ScreenWidths } from '../../style/media'; -import { generateOverlayBlack, styled } from '../../style/theme'; -import { zIndex } from '../../style/z_index'; - -export interface OverlayProps { - zIndex?: number; - backgroundColor?: string; - width?: string; - height?: string; - showMaxWidth?: ScreenWidths; -} - -export const Overlay = styled.div` - && { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: ${props => props.zIndex} - background-color: ${props => props.backgroundColor}; - ${props => props.width && `width: ${props.width};`} - ${props => props.height && `height: ${props.height};`} - display: ${props => (props.showMaxWidth ? 'none' : 'block')}; - ${props => props.showMaxWidth && generateMediaWrapper(props.showMaxWidth)`display: block;`} - } -`; - -Overlay.defaultProps = { - zIndex: zIndex.overlayDefault, - backgroundColor: generateOverlayBlack(0.7), -}; - -Overlay.displayName = 'Overlay'; diff --git a/packages/instant/src/components/ui/spinner.tsx b/packages/instant/src/components/ui/spinner.tsx deleted file mode 100644 index 28ebc2598..000000000 --- a/packages/instant/src/components/ui/spinner.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react'; - -import { FullRotation } from '../animations/full_rotation'; - -export interface SpinnerProps { - widthPx: number; - heightPx: number; -} -export const Spinner: React.StatelessComponent = props => { - return ( - - - - - - - ); -}; diff --git a/packages/instant/src/components/ui/text.tsx b/packages/instant/src/components/ui/text.tsx deleted file mode 100644 index ca120f3bd..000000000 --- a/packages/instant/src/components/ui/text.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import * as React from 'react'; - -import { ColorOption, styled } from '../../style/theme'; -import { util } from '../../util/util'; - -export interface TextProps { - fontColor?: ColorOption; - fontFamily?: string; - fontStyle?: string; - fontSize?: string; - opacity?: number; - letterSpacing?: string; - textAlign?: string; - textTransform?: string; - lineHeight?: string; - className?: string; - minHeight?: string; - center?: boolean; - fontWeight?: number | string; - textDecorationLine?: string; - onClick?: (event: React.MouseEvent) => void; - noWrap?: boolean; - display?: string; - href?: string; - width?: string; -} - -export const Text: React.StatelessComponent = ({ href, onClick, ...rest }) => { - const computedOnClick = href ? util.createOpenUrlInNewWindow(href) : onClick; - return ; -}; - -const opacityOnHoverAmount = 0.5; -export const StyledText = styled.div` - && { - font-family: 'Inter UI', sans-serif; - font-style: ${props => props.fontStyle}; - font-weight: ${props => props.fontWeight}; - font-size: ${props => props.fontSize}; - opacity: ${props => props.opacity}; - text-decoration-line: ${props => props.textDecorationLine}; - ${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')}; - ${props => (props.center ? 'text-align: center' : '')}; - color: ${props => props.fontColor && props.theme[props.fontColor]}; - ${props => (props.minHeight ? `min-height: ${props.minHeight}` : '')}; - ${props => (props.onClick ? 'cursor: pointer' : '')}; - transition: color 0.5s ease; - ${props => (props.noWrap ? 'white-space: nowrap' : '')}; - ${props => (props.display ? `display: ${props.display}` : '')}; - ${props => (props.letterSpacing ? `letter-spacing: ${props.letterSpacing}` : '')}; - ${props => (props.textTransform ? `text-transform: ${props.textTransform}` : '')}; - ${props => (props.textAlign ? `text-align: ${props.textAlign}` : '')}; - ${props => (props.width ? `width: ${props.width}` : '')}; - &:hover { - ${props => (props.onClick ? `opacity: ${opacityOnHoverAmount};` : '')}; - } - } -`; - -Text.defaultProps = { - fontFamily: 'Inter UI', - fontStyle: 'normal', - fontWeight: 400, - fontColor: ColorOption.black, - fontSize: '15px', - textDecorationLine: 'none', - noWrap: false, - display: 'inline-block', -}; - -Text.displayName = 'Text'; diff --git a/packages/instant/src/components/wallet_prompt.tsx b/packages/instant/src/components/wallet_prompt.tsx deleted file mode 100644 index 10433767f..000000000 --- a/packages/instant/src/components/wallet_prompt.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import * as React from 'react'; - -import { ColorOption } from '../style/theme'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text } from './ui/text'; - -export interface WalletPromptProps { - image: React.ReactNode; - onClick?: () => void; - primaryColor: ColorOption; - secondaryColor: ColorOption; -} - -export const WalletPrompt: React.StatelessComponent = ({ - onClick, - image, - children, - secondaryColor, - primaryColor, -}) => ( - - - {image} - - - {children} - - - - -); - -WalletPrompt.defaultProps = { - primaryColor: ColorOption.darkOrange, - secondaryColor: ColorOption.lightOrange, -}; - -WalletPrompt.displayName = 'WalletPrompt'; diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx deleted file mode 100644 index e9cb48e61..000000000 --- a/packages/instant/src/components/zero_ex_instant.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; - -import { ZeroExInstantContainer } from '../components/zero_ex_instant_container'; - -import { INJECTED_DIV_CLASS } from '../constants'; - -import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider'; - -export type ZeroExInstantProps = ZeroExInstantProviderProps; - -export const ZeroExInstant: React.StatelessComponent = props => { - return ( -
- - - -
- ); -}; - -ZeroExInstant.displayName = 'ZeroExInstant'; diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx deleted file mode 100644 index e8c64d5d1..000000000 --- a/packages/instant/src/components/zero_ex_instant_container.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import * as React from 'react'; - -import PoweredByLogo from '../assets/powered_by_0x.svg'; -import { ZERO_EX_SITE_URL } from '../constants'; -import { AvailableERC20TokenSelector } from '../containers/available_erc20_token_selector'; -import { ConnectedBuyOrderProgressOrPaymentMethod } from '../containers/connected_buy_order_progress_or_payment_method'; -import { CurrentStandardSlidingPanel } from '../containers/current_standard_sliding_panel'; -import { LatestBuyQuoteOrderDetails } from '../containers/latest_buy_quote_order_details'; -import { LatestError } from '../containers/latest_error'; -import { SelectedAssetBuyOrderStateButtons } from '../containers/selected_asset_buy_order_state_buttons'; -import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading'; -import { ColorOption } from '../style/theme'; -import { zIndex } from '../style/z_index'; -import { SlideAnimationState } from '../types'; -import { analytics, TokenSelectorClosedVia } from '../util/analytics'; - -import { CSSReset } from './css_reset'; -import { SlidingPanel } from './sliding_panel'; -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; - -export interface ZeroExInstantContainerProps {} -export interface ZeroExInstantContainerState { - tokenSelectionPanelAnimationState: SlideAnimationState; -} - -export class ZeroExInstantContainer extends React.PureComponent< - ZeroExInstantContainerProps, - ZeroExInstantContainerState -> { - public state = { - tokenSelectionPanelAnimationState: 'none' as SlideAnimationState, - }; - public render(): React.ReactNode { - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); - } - private readonly _handleSymbolClick = (): void => { - analytics.trackTokenSelectorOpened(); - this.setState({ - tokenSelectionPanelAnimationState: 'slidIn', - }); - }; - private readonly _handlePanelCloseClickedX = (): void => { - this._handlePanelClose(TokenSelectorClosedVia.ClickedX); - }; - private readonly _handlePanelCloseAfterChose = (): void => { - this._handlePanelClose(TokenSelectorClosedVia.TokenChose); - }; - private readonly _handlePanelClose = (closedVia: TokenSelectorClosedVia): void => { - analytics.trackTokenSelectorClosed(closedVia); - this.setState({ - tokenSelectionPanelAnimationState: 'slidOut', - }); - }; - private readonly _handleSlidingPanelAnimationEnd = (): void => { - if (this.state.tokenSelectionPanelAnimationState === 'slidOut') { - // When the slidOut animation completes, don't keep the panel mounted. - // Performance optimization - this.setState({ tokenSelectionPanelAnimationState: 'none' }); - } - }; -} diff --git a/packages/instant/src/components/zero_ex_instant_overlay.tsx b/packages/instant/src/components/zero_ex_instant_overlay.tsx deleted file mode 100644 index 38a716091..000000000 --- a/packages/instant/src/components/zero_ex_instant_overlay.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from 'react'; - -import { ZeroExInstantContainer } from '../components/zero_ex_instant_container'; -import { MAIN_CONTAINER_DIV_CLASS, OVERLAY_CLOSE_BUTTON_DIV_CLASS, OVERLAY_DIV_CLASS } from '../constants'; -import { ColorOption } from '../style/theme'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Icon } from './ui/icon'; -import { Overlay } from './ui/overlay'; -import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider'; - -export interface ZeroExInstantOverlayProps extends ZeroExInstantProviderProps { - onClose?: () => void; - zIndex?: number; -} - -export const ZeroExInstantOverlay: React.StatelessComponent = props => { - const { onClose, zIndex, ...rest } = props; - return ( - - - - - - - - - - - - - ); -}; - -ZeroExInstantOverlay.displayName = 'ZeroExInstantOverlay'; diff --git a/packages/instant/src/components/zero_ex_instant_provider.tsx b/packages/instant/src/components/zero_ex_instant_provider.tsx deleted file mode 100644 index ec8e82ee3..000000000 --- a/packages/instant/src/components/zero_ex_instant_provider.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { Provider as ReduxProvider } from 'react-redux'; - -import { ACCOUNT_UPDATE_INTERVAL_TIME_MS, BUY_QUOTE_UPDATE_INTERVAL_TIME_MS } from '../constants'; -import { SelectedAssetThemeProvider } from '../containers/selected_asset_theme_provider'; -import { asyncData } from '../redux/async_data'; -import { DEFAULT_STATE, DefaultState, State } from '../redux/reducer'; -import { store, Store } from '../redux/store'; -import { fonts } from '../style/fonts'; -import { AccountState, Network, QuoteFetchOrigin, ZeroExInstantBaseConfig } from '../types'; -import { analytics, disableAnalytics } from '../util/analytics'; -import { assetUtils } from '../util/asset'; -import { errorFlasher } from '../util/error_flasher'; -import { setupRollbar } from '../util/error_reporter'; -import { gasPriceEstimator } from '../util/gas_price_estimator'; -import { Heartbeater } from '../util/heartbeater'; -import { generateAccountHeartbeater, generateBuyQuoteHeartbeater } from '../util/heartbeater_factory'; -import { providerStateFactory } from '../util/provider_state_factory'; - -export type ZeroExInstantProviderProps = ZeroExInstantBaseConfig; - -export class ZeroExInstantProvider extends React.PureComponent { - private readonly _store: Store; - private _accountUpdateHeartbeat?: Heartbeater; - private _buyQuoteHeartbeat?: Heartbeater; - - // TODO(fragosti): Write tests for this beast once we inject a provider. - private static _mergeDefaultStateWithProps( - props: ZeroExInstantProviderProps, - defaultState: DefaultState = DEFAULT_STATE, - ): State { - // use the networkId passed in with the props, otherwise default to that of the default state (1, mainnet) - const networkId = props.networkId || defaultState.network; - // construct the ProviderState - const providerState = providerStateFactory.getInitialProviderState( - props.orderSource, - networkId, - props.provider, - props.walletDisplayName, - ); - // merge the additional additionalAssetMetaDataMap with our default map - const completeAssetMetaDataMap = { - // Make sure the passed in assetDatas are lower case - ..._.mapKeys(props.additionalAssetMetaDataMap || {}, (value, key) => key.toLowerCase()), - ...defaultState.assetMetaDataMap, - }; - // construct the final state - const storeStateFromProps: State = { - ...defaultState, - providerState, - network: networkId, - walletDisplayName: props.walletDisplayName, - selectedAsset: _.isUndefined(props.defaultSelectedAssetData) - ? undefined - : assetUtils.createAssetFromAssetDataOrThrow( - props.defaultSelectedAssetData, - completeAssetMetaDataMap, - networkId, - ), - selectedAssetUnitAmount: _.isUndefined(props.defaultAssetBuyAmount) - ? undefined - : new BigNumber(props.defaultAssetBuyAmount), - availableAssets: _.isUndefined(props.availableAssetDatas) - ? undefined - : assetUtils.createAssetsFromAssetDatas(props.availableAssetDatas, completeAssetMetaDataMap, networkId), - assetMetaDataMap: completeAssetMetaDataMap, - affiliateInfo: props.affiliateInfo, - }; - return storeStateFromProps; - } - constructor(props: ZeroExInstantProviderProps) { - super(props); - setupRollbar(); - fonts.include(); - const initialAppState = ZeroExInstantProvider._mergeDefaultStateWithProps(this.props); - this._store = store.create(initialAppState); - } - public componentDidMount(): void { - const state = this._store.getState(); - const dispatch = this._store.dispatch; - // tslint:disable-next-line:no-floating-promises - asyncData.fetchEthPriceAndDispatchToStore(dispatch); - // fetch available assets if none are specified - if (_.isUndefined(state.availableAssets)) { - // tslint:disable-next-line:no-floating-promises - asyncData.fetchAvailableAssetDatasAndDispatchToStore(state, dispatch); - } - if (state.providerState.account.state !== AccountState.None) { - this._accountUpdateHeartbeat = generateAccountHeartbeater({ - store: this._store, - shouldPerformImmediatelyOnStart: true, - }); - this._accountUpdateHeartbeat.start(ACCOUNT_UPDATE_INTERVAL_TIME_MS); - } - - this._buyQuoteHeartbeat = generateBuyQuoteHeartbeater({ - store: this._store, - shouldPerformImmediatelyOnStart: false, - }); - this._buyQuoteHeartbeat.start(BUY_QUOTE_UPDATE_INTERVAL_TIME_MS); - // Trigger first buyquote fetch - // tslint:disable-next-line:no-floating-promises - asyncData.fetchCurrentBuyQuoteAndDispatchToStore(state, dispatch, QuoteFetchOrigin.Manual, { - updateSilently: false, - }); - // warm up the gas price estimator cache just in case we can't - // grab the gas price estimate when submitting the transaction - // tslint:disable-next-line:no-floating-promises - gasPriceEstimator.getGasInfoAsync(); - // tslint:disable-next-line:no-floating-promises - this._flashErrorIfWrongNetwork(); - - // Analytics - disableAnalytics(this.props.shouldDisableAnalyticsTracking || false); - analytics.addEventProperties( - analytics.generateEventProperties( - state.network, - this.props.orderSource, - state.providerState, - window, - state.selectedAsset, - this.props.affiliateInfo, - state.baseCurrency, - ), - ); - analytics.trackInstantOpened(); - } - public componentWillUnmount(): void { - if (this._accountUpdateHeartbeat) { - this._accountUpdateHeartbeat.stop(); - } - if (this._buyQuoteHeartbeat) { - this._buyQuoteHeartbeat.stop(); - } - } - public render(): React.ReactNode { - return ( - - {this.props.children} - - ); - } - private readonly _flashErrorIfWrongNetwork = async (): Promise => { - const msToShowError = 30000; // 30 seconds - const state = this._store.getState(); - const network = state.network; - const web3Wrapper = state.providerState.web3Wrapper; - const networkOfProvider = await web3Wrapper.getNetworkIdAsync(); - if (network !== networkOfProvider) { - const errorMessage = `Wrong network detected. Try switching to ${Network[network]}.`; - errorFlasher.flashNewErrorMessage(this._store.dispatch, errorMessage, msToShowError); - } - }; -} diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts deleted file mode 100644 index d407925a3..000000000 --- a/packages/instant/src/constants.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { BigNumber } from '@0x/utils'; - -import { AccountNotReady, AccountState, Network, ProviderType } from './types'; - -export const BIG_NUMBER_ZERO = new BigNumber(0); -export const ETH_DECIMALS = 18; -export const DEFAULT_ZERO_EX_CONTAINER_SELECTOR = '#zeroExInstantContainer'; -export const INJECTED_DIV_CLASS = 'zeroExInstantResetRoot'; -export const INJECTED_DIV_ID = 'zeroExInstant'; -export const OVERLAY_DIV_CLASS = 'zeroExInstantOverlay'; -export const OVERLAY_CLOSE_BUTTON_DIV_CLASS = 'zeroExInstantOverlayCloseButton'; -export const MAIN_CONTAINER_DIV_CLASS = 'zeroExInstantMainContainer'; -export const WEB_3_WRAPPER_TRANSACTION_FAILED_ERROR_MSG_PREFIX = 'Transaction failed'; -export const GWEI_IN_WEI = new BigNumber(1000000000); -export const ONE_SECOND_MS = 1000; -export const ONE_MINUTE_MS = ONE_SECOND_MS * 60; -export const GIT_SHA = process.env.GIT_SHA; -export const NODE_ENV = process.env.NODE_ENV; -export const SLIPPAGE_PERCENTAGE = 0.2; -export const NPM_PACKAGE_VERSION = process.env.NPM_PACKAGE_VERSION; -export const DEFAULT_UNKOWN_ASSET_NAME = '???'; -export const ACCOUNT_UPDATE_INTERVAL_TIME_MS = ONE_SECOND_MS * 5; -export const BUY_QUOTE_UPDATE_INTERVAL_TIME_MS = ONE_SECOND_MS * 15; -export const DEFAULT_GAS_PRICE = GWEI_IN_WEI.multipliedBy(6); -export const DEFAULT_ESTIMATED_TRANSACTION_TIME_MS = ONE_MINUTE_MS * 2; -export const MAGIC_TRIGGER_ERROR_INPUT = '0€'; -export const MAGIC_TRIGGER_ERROR_MESSAGE = 'Triggered error'; -export const ETH_GAS_STATION_API_BASE_URL = 'https://ethgasstation.info'; -export const HEAP_ANALYTICS_ID = process.env.HEAP_ANALYTICS_ID; -export const HEAP_ENABLED = process.env.HEAP_ENABLED; -export const COINBASE_API_BASE_URL = 'https://api.coinbase.com/v2'; -export const PROGRESS_STALL_AT_WIDTH = '95%'; -export const PROGRESS_FINISH_ANIMATION_TIME_MS = 200; -export const HOST_DOMAINS_EXTERNAL = [ - '0x-instant-staging.s3-website-us-east-1.amazonaws.com', - '0x-instant-dogfood.s3-website-us-east-1.amazonaws.com', - 'instant.0xproject.com', -]; -export const HOST_DOMAINS_LOCAL = ['localhost', '127.0.0.1', '0.0.0.0']; -export const ROLLBAR_CLIENT_TOKEN = process.env.ROLLBAR_CLIENT_TOKEN; -export const ROLLBAR_ENABLED = process.env.ROLLBAR_ENABLED; -export const INSTANT_DISCHARGE_TARGET = process.env.INSTANT_DISCHARGE_TARGET as - | 'production' - | 'dogfood' - | 'staging' - | undefined; -export const COINBASE_WALLET_IOS_APP_STORE_URL = 'https://itunes.apple.com/us/app/coinbase-wallet/id1278383455?mt=8'; -export const COINBASE_WALLET_ANDROID_APP_STORE_URL = 'https://play.google.com/store/apps/details?id=org.toshi&hl=en'; -export const COINBASE_WALLET_SITE_URL = 'https://wallet.coinbase.com/'; -export const META_MASK_FIREFOX_STORE_URL = 'https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/'; -export const META_MASK_CHROME_STORE_URL = - 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en'; -export const META_MASK_OPERA_STORE_URL = 'https://addons.opera.com/en/extensions/details/metamask/'; -export const META_MASK_SITE_URL = 'https://metamask.io/'; -export const ETHEREUM_NODE_URL_BY_NETWORK = { - [Network.Mainnet]: 'https://mainnet.infura.io/', - [Network.Kovan]: 'https://kovan.infura.io/', -}; -export const ZERO_EX_SITE_URL = 'https://www.0xproject.com/'; -export const BLOCK_POLLING_INTERVAL_MS = 10000; // 10s -export const NO_ACCOUNT: AccountNotReady = { - state: AccountState.None, -}; -export const LOADING_ACCOUNT: AccountNotReady = { - state: AccountState.Loading, -}; -export const LOCKED_ACCOUNT: AccountNotReady = { - state: AccountState.Locked, -}; -export const PROVIDER_TYPE_TO_NAME: { [key in ProviderType]: string } = { - [ProviderType.Cipher]: 'Cipher', - [ProviderType.MetaMask]: 'MetaMask', - [ProviderType.Mist]: 'Mist', - [ProviderType.CoinbaseWallet]: 'Coinbase Wallet', - [ProviderType.Parity]: 'Parity', - [ProviderType.TrustWallet]: 'Trust Wallet', - [ProviderType.Opera]: 'Opera Wallet', - [ProviderType.Fallback]: 'Fallback', -}; diff --git a/packages/instant/src/containers/available_erc20_token_selector.ts b/packages/instant/src/containers/available_erc20_token_selector.ts deleted file mode 100644 index 4d4218d22..000000000 --- a/packages/instant/src/containers/available_erc20_token_selector.ts +++ /dev/null @@ -1,45 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; - -import { State } from '../redux/reducer'; -import { ERC20Asset } from '../types'; -import { assetUtils } from '../util/asset'; - -import { ERC20TokenSelector } from '../components/erc20_token_selector'; -import { Action, actions } from '../redux/actions'; - -export interface AvailableERC20TokenSelectorProps { - onTokenSelect?: (token: ERC20Asset) => void; -} - -interface ConnectedState { - tokens: ERC20Asset[]; -} - -interface ConnectedDispatch { - onTokenSelect: (token: ERC20Asset) => void; -} - -const mapStateToProps = (state: State, _ownProps: AvailableERC20TokenSelectorProps): ConnectedState => ({ - tokens: assetUtils.getERC20AssetsFromAssets(state.availableAssets || []), -}); - -const mapDispatchToProps = ( - dispatch: Dispatch, - ownProps: AvailableERC20TokenSelectorProps, -): ConnectedDispatch => ({ - onTokenSelect: (token: ERC20Asset) => { - dispatch(actions.updateSelectedAsset(token)); - dispatch(actions.resetAmount()); - if (ownProps.onTokenSelect) { - ownProps.onTokenSelect(token); - } - }, -}); - -export const AvailableERC20TokenSelector: React.ComponentClass = connect( - mapStateToProps, - mapDispatchToProps, -)(ERC20TokenSelector); diff --git a/packages/instant/src/containers/connected_account_payment_method.ts b/packages/instant/src/containers/connected_account_payment_method.ts deleted file mode 100644 index f648f0b54..000000000 --- a/packages/instant/src/containers/connected_account_payment_method.ts +++ /dev/null @@ -1,94 +0,0 @@ -import * as React from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; - -import { PaymentMethod, PaymentMethodProps } from '../components/payment_method'; -import { - COINBASE_WALLET_ANDROID_APP_STORE_URL, - COINBASE_WALLET_IOS_APP_STORE_URL, - COINBASE_WALLET_SITE_URL, -} from '../constants'; -import { Action, actions } from '../redux/actions'; -import { asyncData } from '../redux/async_data'; -import { State } from '../redux/reducer'; -import { Network, Omit, OperatingSystem, ProviderState, StandardSlidingPanelContent, WalletSuggestion } from '../types'; -import { analytics } from '../util/analytics'; -import { envUtil } from '../util/env'; - -export interface ConnectedAccountPaymentMethodProps {} - -interface ConnectedState { - network: Network; - providerState: ProviderState; - walletDisplayName?: string; -} - -interface ConnectedDispatch { - openInstallWalletPanel: () => void; - unlockWalletAndDispatchToStore: (providerState: ProviderState) => void; -} - -type ConnectedProps = Omit; - -type FinalProps = ConnectedProps & ConnectedAccountPaymentMethodProps; - -const mapStateToProps = (state: State, _ownProps: ConnectedAccountPaymentMethodProps): ConnectedState => ({ - network: state.network, - providerState: state.providerState, - walletDisplayName: state.walletDisplayName, -}); - -const mapDispatchToProps = ( - dispatch: Dispatch, - ownProps: ConnectedAccountPaymentMethodProps, -): ConnectedDispatch => ({ - openInstallWalletPanel: () => dispatch(actions.openStandardSlidingPanel(StandardSlidingPanelContent.InstallWallet)), - unlockWalletAndDispatchToStore: (providerState: ProviderState) => { - analytics.trackAccountUnlockRequested(); - // tslint:disable-next-line:no-floating-promises - asyncData.fetchAccountInfoAndDispatchToStore(providerState, dispatch, true); - }, -}); - -const mergeProps = ( - connectedState: ConnectedState, - connectedDispatch: ConnectedDispatch, - ownProps: ConnectedAccountPaymentMethodProps, -): FinalProps => ({ - ...ownProps, - network: connectedState.network, - account: connectedState.providerState.account, - walletDisplayName: connectedState.providerState.displayName, - onUnlockWalletClick: () => connectedDispatch.unlockWalletAndDispatchToStore(connectedState.providerState), - onInstallWalletClick: () => { - const isMobile = envUtil.isMobileOperatingSystem(); - const walletSuggestion: WalletSuggestion = isMobile - ? WalletSuggestion.CoinbaseWallet - : WalletSuggestion.MetaMask; - - analytics.trackInstallWalletClicked(walletSuggestion); - if (walletSuggestion === WalletSuggestion.MetaMask) { - connectedDispatch.openInstallWalletPanel(); - } else { - const operatingSystem = envUtil.getOperatingSystem(); - let url = COINBASE_WALLET_SITE_URL; - switch (operatingSystem) { - case OperatingSystem.Android: - url = COINBASE_WALLET_ANDROID_APP_STORE_URL; - break; - case OperatingSystem.iOS: - url = COINBASE_WALLET_IOS_APP_STORE_URL; - break; - default: - break; - } - window.open(url, '_blank'); - } - }, -}); - -export const ConnectedAccountPaymentMethod: React.ComponentClass = connect( - mapStateToProps, - mapDispatchToProps, - mergeProps, -)(PaymentMethod); diff --git a/packages/instant/src/containers/connected_buy_order_progress_or_payment_method.tsx b/packages/instant/src/containers/connected_buy_order_progress_or_payment_method.tsx deleted file mode 100644 index cace18e7e..000000000 --- a/packages/instant/src/containers/connected_buy_order_progress_or_payment_method.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; -import { connect } from 'react-redux'; - -import { State } from '../redux/reducer'; -import { OrderProcessState } from '../types'; - -import { ConnectedAccountPaymentMethod } from './connected_account_payment_method'; -import { SelectedAssetBuyOrderProgress } from './selected_asset_buy_order_progress'; - -interface BuyOrderProgressOrPaymentMethodProps { - orderProcessState: OrderProcessState; -} -export const BuyOrderProgressOrPaymentMethod = (props: BuyOrderProgressOrPaymentMethodProps) => { - const { orderProcessState } = props; - if ( - orderProcessState === OrderProcessState.Processing || - orderProcessState === OrderProcessState.Success || - orderProcessState === OrderProcessState.Failure - ) { - return ; - } else { - return ; - } - return null; -}; - -interface ConnectedState extends BuyOrderProgressOrPaymentMethodProps {} - -export interface ConnectedBuyOrderProgressOrPaymentMethodProps {} -const mapStateToProps = (state: State, _ownProps: ConnectedBuyOrderProgressOrPaymentMethodProps): ConnectedState => ({ - orderProcessState: state.buyOrderState.processState, -}); -export const ConnectedBuyOrderProgressOrPaymentMethod: React.ComponentClass< - ConnectedBuyOrderProgressOrPaymentMethodProps -> = connect(mapStateToProps)(BuyOrderProgressOrPaymentMethod); diff --git a/packages/instant/src/containers/current_standard_sliding_panel.ts b/packages/instant/src/containers/current_standard_sliding_panel.ts deleted file mode 100644 index 82ac7fa1b..000000000 --- a/packages/instant/src/containers/current_standard_sliding_panel.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; - -import { StandardSlidingPanel } from '../components/standard_sliding_panel'; -import { Action, actions } from '../redux/actions'; -import { State } from '../redux/reducer'; -import { StandardSlidingPanelSettings } from '../types'; - -export interface CurrentStandardSlidingPanelProps {} - -interface ConnectedState extends StandardSlidingPanelSettings {} - -interface ConnectedDispatch { - onClose: () => void; -} - -const mapStateToProps = (state: State, _ownProps: CurrentStandardSlidingPanelProps): ConnectedState => - state.standardSlidingPanelSettings; - -const mapDispatchToProps = ( - dispatch: Dispatch, - ownProps: CurrentStandardSlidingPanelProps, -): ConnectedDispatch => ({ - onClose: () => dispatch(actions.closeStandardSlidingPanel()), -}); - -export const CurrentStandardSlidingPanel: React.ComponentClass = connect( - mapStateToProps, - mapDispatchToProps, -)(StandardSlidingPanel); diff --git a/packages/instant/src/containers/latest_buy_quote_order_details.ts b/packages/instant/src/containers/latest_buy_quote_order_details.ts deleted file mode 100644 index 148735c47..000000000 --- a/packages/instant/src/containers/latest_buy_quote_order_details.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; -import { oc } from 'ts-optchain'; - -import { Action, actions } from '../redux/actions'; -import { State } from '../redux/reducer'; - -import { OrderDetails, OrderDetailsProps } from '../components/order_details'; -import { AsyncProcessState, BaseCurrency, Omit } from '../types'; -import { assetUtils } from '../util/asset'; - -type DispatchProperties = 'onBaseCurrencySwitchEth' | 'onBaseCurrencySwitchUsd'; - -interface ConnectedState extends Omit {} -const mapStateToProps = (state: State, _ownProps: LatestBuyQuoteOrderDetailsProps): ConnectedState => ({ - // use the worst case quote info - buyQuoteInfo: oc(state).latestBuyQuote.worstCaseQuoteInfo(), - selectedAssetUnitAmount: state.selectedAssetUnitAmount, - ethUsdPrice: state.ethUsdPrice, - isLoading: state.quoteRequestState === AsyncProcessState.Pending, - assetName: assetUtils.bestNameForAsset(state.selectedAsset), - baseCurrency: state.baseCurrency, -}); - -interface ConnectedDispatch extends Pick {} -const mapDispatchToProps = (dispatch: Dispatch): ConnectedDispatch => ({ - onBaseCurrencySwitchEth: () => { - dispatch(actions.updateBaseCurrency(BaseCurrency.ETH)); - }, - onBaseCurrencySwitchUsd: () => { - dispatch(actions.updateBaseCurrency(BaseCurrency.USD)); - }, -}); - -export interface LatestBuyQuoteOrderDetailsProps {} -export const LatestBuyQuoteOrderDetails: React.ComponentClass = connect( - mapStateToProps, - mapDispatchToProps, -)(OrderDetails); diff --git a/packages/instant/src/containers/latest_error.tsx b/packages/instant/src/containers/latest_error.tsx deleted file mode 100644 index 57a2dbdc2..000000000 --- a/packages/instant/src/containers/latest_error.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import * as React from 'react'; - -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; - -import { SlidingError } from '../components/sliding_error'; -import { Container } from '../components/ui/container'; -import { Overlay } from '../components/ui/overlay'; -import { Action } from '../redux/actions'; -import { State } from '../redux/reducer'; -import { ScreenWidths } from '../style/media'; -import { generateOverlayBlack } from '../style/theme'; -import { zIndex } from '../style/z_index'; -import { Asset, DisplayStatus, Omit, SlideAnimationState } from '../types'; -import { errorFlasher } from '../util/error_flasher'; - -interface LatestErrorComponentProps { - asset?: Asset; - latestErrorMessage?: string; - animationState: SlideAnimationState; - shouldRenderOverlay: boolean; - onOverlayClick: () => void; -} - -const LatestErrorComponent: React.StatelessComponent = props => { - if (!props.latestErrorMessage) { - // Render a hidden SlidingError such that instant does not move when a real error is rendered. - return ( - - - - ); - } - return ( - - - {props.shouldRenderOverlay && ( - - )} - - ); -}; - -export interface LatestErrorProps {} -interface ConnectedState extends Omit {} -const mapStateToProps = (state: State, _ownProps: LatestErrorProps): ConnectedState => ({ - asset: state.selectedAsset, - latestErrorMessage: state.latestErrorMessage, - animationState: state.latestErrorDisplayStatus === DisplayStatus.Present ? 'slidIn' : 'slidOut', - shouldRenderOverlay: state.latestErrorDisplayStatus === DisplayStatus.Present, -}); - -type ConnectedDispatch = Pick; -const mapDispatchToProps = (dispatch: Dispatch, _ownProps: LatestErrorProps): ConnectedDispatch => ({ - onOverlayClick: () => { - errorFlasher.clearError(dispatch); - }, -}); - -export const LatestError = connect( - mapStateToProps, - mapDispatchToProps, -)(LatestErrorComponent); diff --git a/packages/instant/src/containers/selected_asset_buy_order_progress.ts b/packages/instant/src/containers/selected_asset_buy_order_progress.ts deleted file mode 100644 index 7c8c24676..000000000 --- a/packages/instant/src/containers/selected_asset_buy_order_progress.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { connect } from 'react-redux'; - -import { BuyOrderProgress } from '../components/buy_order_progress'; -import { State } from '../redux/reducer'; -import { OrderState } from '../types'; - -interface ConnectedState { - buyOrderState: OrderState; -} -const mapStateToProps = (state: State, _ownProps: {}): ConnectedState => ({ - buyOrderState: state.buyOrderState, -}); -export const SelectedAssetBuyOrderProgress = connect(mapStateToProps)(BuyOrderProgress); diff --git a/packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts b/packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts deleted file mode 100644 index 4da99cf04..000000000 --- a/packages/instant/src/containers/selected_asset_buy_order_state_buttons.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; - -import { BuyOrderStateButtons } from '../components/buy_order_state_buttons'; -import { Action, actions } from '../redux/actions'; -import { State } from '../redux/reducer'; -import { AccountState, AffiliateInfo, Asset, OrderProcessState, ZeroExInstantError } from '../types'; -import { analytics } from '../util/analytics'; -import { errorFlasher } from '../util/error_flasher'; -import { etherscanUtil } from '../util/etherscan'; - -interface ConnectedState { - accountAddress?: string; - accountEthBalanceInWei?: BigNumber; - buyQuote?: BuyQuote; - buyOrderProcessingState: OrderProcessState; - assetBuyer: AssetBuyer; - web3Wrapper: Web3Wrapper; - affiliateInfo?: AffiliateInfo; - selectedAsset?: Asset; - onViewTransaction: () => void; -} - -interface ConnectedDispatch { - onValidationPending: (buyQuote: BuyQuote) => void; - onSignatureDenied: (buyQuote: BuyQuote) => void; - onBuyProcessing: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => void; - onBuySuccess: (buyQuote: BuyQuote, txHash: string) => void; - onBuyFailure: (buyQuote: BuyQuote, txHash: string) => void; - onRetry: () => void; - onValidationFail: (buyQuote: BuyQuote, errorMessage: AssetBuyerError | ZeroExInstantError) => void; -} -export interface SelectedAssetBuyOrderStateButtons {} -const mapStateToProps = (state: State, _ownProps: SelectedAssetBuyOrderStateButtons): ConnectedState => { - const assetBuyer = state.providerState.assetBuyer; - const web3Wrapper = state.providerState.web3Wrapper; - const account = state.providerState.account; - const accountAddress = account.state === AccountState.Ready ? account.address : undefined; - const accountEthBalanceInWei = account.state === AccountState.Ready ? account.ethBalanceInWei : undefined; - const selectedAsset = state.selectedAsset; - return { - accountAddress, - accountEthBalanceInWei, - buyOrderProcessingState: state.buyOrderState.processState, - assetBuyer, - web3Wrapper, - buyQuote: state.latestBuyQuote, - affiliateInfo: state.affiliateInfo, - selectedAsset, - onViewTransaction: () => { - if ( - state.buyOrderState.processState === OrderProcessState.Processing || - state.buyOrderState.processState === OrderProcessState.Success || - state.buyOrderState.processState === OrderProcessState.Failure - ) { - const etherscanUrl = etherscanUtil.getEtherScanTxnAddressIfExists( - state.buyOrderState.txHash, - assetBuyer.networkId, - ); - if (etherscanUrl) { - analytics.trackTransactionViewed(state.buyOrderState.processState); - - window.open(etherscanUrl, '_blank'); - return; - } - } - }, - }; -}; - -const mapDispatchToProps = ( - dispatch: Dispatch, - ownProps: SelectedAssetBuyOrderStateButtons, -): ConnectedDispatch => ({ - onValidationPending: (buyQuote: BuyQuote) => { - dispatch(actions.setBuyOrderStateValidating()); - }, - onBuyProcessing: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => { - dispatch(actions.setBuyOrderStateProcessing(txHash, startTimeUnix, expectedEndTimeUnix)); - }, - onBuySuccess: (buyQuote: BuyQuote, txHash: string) => dispatch(actions.setBuyOrderStateSuccess(txHash)), - onBuyFailure: (buyQuote: BuyQuote, txHash: string) => dispatch(actions.setBuyOrderStateFailure(txHash)), - onSignatureDenied: () => { - dispatch(actions.resetAmount()); - const errorMessage = 'You denied this transaction'; - errorFlasher.flashNewErrorMessage(dispatch, errorMessage); - }, - onValidationFail: (buyQuote, error) => { - dispatch(actions.setBuyOrderStateNone()); - if (error === ZeroExInstantError.InsufficientETH) { - const errorMessage = "You don't have enough ETH"; - errorFlasher.flashNewErrorMessage(dispatch, errorMessage); - } else if (error === ZeroExInstantError.CouldNotSubmitTransaction) { - const errorMessage = 'Could not submit transaction'; - errorFlasher.flashNewErrorMessage(dispatch, errorMessage); - } else { - errorFlasher.flashNewErrorMessage(dispatch); - } - }, - onRetry: () => { - dispatch(actions.resetAmount()); - }, -}); - -export const SelectedAssetBuyOrderStateButtons: React.ComponentClass = connect( - mapStateToProps, - mapDispatchToProps, -)(BuyOrderStateButtons); diff --git a/packages/instant/src/containers/selected_asset_instant_heading.ts b/packages/instant/src/containers/selected_asset_instant_heading.ts deleted file mode 100644 index 8dc127e1d..000000000 --- a/packages/instant/src/containers/selected_asset_instant_heading.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { connect } from 'react-redux'; -import { oc } from 'ts-optchain'; - -import { State } from '../redux/reducer'; -import { AsyncProcessState, ERC20Asset, OrderState } from '../types'; - -import { InstantHeading } from '../components/instant_heading'; - -export interface InstantHeadingProps { - onSelectAssetClick?: (asset?: ERC20Asset) => void; -} - -interface ConnectedState { - selectedAssetUnitAmount?: BigNumber; - totalEthBaseUnitAmount?: BigNumber; - ethUsdPrice?: BigNumber; - quoteRequestState: AsyncProcessState; - buyOrderState: OrderState; -} - -const mapStateToProps = (state: State, _ownProps: InstantHeadingProps): ConnectedState => ({ - selectedAssetUnitAmount: state.selectedAssetUnitAmount, - totalEthBaseUnitAmount: oc(state).latestBuyQuote.worstCaseQuoteInfo.totalEthAmount(), - ethUsdPrice: state.ethUsdPrice, - quoteRequestState: state.quoteRequestState, - buyOrderState: state.buyOrderState, -}); - -export const SelectedAssetInstantHeading: React.ComponentClass = connect(mapStateToProps)( - InstantHeading, -); diff --git a/packages/instant/src/containers/selected_asset_theme_provider.ts b/packages/instant/src/containers/selected_asset_theme_provider.ts deleted file mode 100644 index 6e6b83d73..000000000 --- a/packages/instant/src/containers/selected_asset_theme_provider.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import { connect } from 'react-redux'; - -import { State } from '../redux/reducer'; -import { Theme, theme as defaultTheme, ThemeProvider } from '../style/theme'; -import { Asset } from '../types'; - -export interface SelectedAssetThemeProviderProps {} - -interface ConnectedState { - theme: Theme; -} - -const getTheme = (asset?: Asset): Theme => { - if (!_.isUndefined(asset) && !_.isUndefined(asset.metaData.primaryColor)) { - return { - ...defaultTheme, - primaryColor: asset.metaData.primaryColor, - }; - } - return defaultTheme; -}; - -const mapStateToProps = (state: State, _ownProps: SelectedAssetThemeProviderProps): ConnectedState => { - const theme = getTheme(state.selectedAsset); - return { theme }; -}; - -export const SelectedAssetThemeProvider: React.ComponentClass = connect( - mapStateToProps, -)(ThemeProvider); diff --git a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts deleted file mode 100644 index 4b9993332..000000000 --- a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { AssetBuyer } from '@0x/asset-buyer'; -import { AssetProxyId } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; - -import { ERC20AssetAmountInput, ERC20AssetAmountInputProps } from '../components/erc20_asset_amount_input'; -import { Action, actions } from '../redux/actions'; -import { State } from '../redux/reducer'; -import { ColorOption } from '../style/theme'; -import { AffiliateInfo, ERC20Asset, Omit, OrderProcessState, QuoteFetchOrigin } from '../types'; -import { buyQuoteUpdater } from '../util/buy_quote_updater'; - -export interface SelectedERC20AssetAmountInputProps { - fontColor?: ColorOption; - startingFontSizePx: number; - onSelectAssetClick?: (asset?: ERC20Asset) => void; -} - -interface ConnectedState { - assetBuyer: AssetBuyer; - value?: BigNumber; - asset?: ERC20Asset; - isInputDisabled: boolean; - numberOfAssetsAvailable?: number; - affiliateInfo?: AffiliateInfo; - canSelectOtherAsset: boolean; -} - -interface ConnectedDispatch { - updateBuyQuote: ( - assetBuyer: AssetBuyer, - value?: BigNumber, - asset?: ERC20Asset, - affiliateInfo?: AffiliateInfo, - ) => void; -} - -type ConnectedProps = Omit; - -type FinalProps = ConnectedProps & SelectedERC20AssetAmountInputProps; - -const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputProps): ConnectedState => { - const processState = state.buyOrderState.processState; - const isInputEnabled = processState === OrderProcessState.None || processState === OrderProcessState.Failure; - const isInputDisabled = !isInputEnabled; - const selectedAsset = - !_.isUndefined(state.selectedAsset) && state.selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20 - ? (state.selectedAsset as ERC20Asset) - : undefined; - const numberOfAssetsAvailable = _.isUndefined(state.availableAssets) ? undefined : state.availableAssets.length; - const canSelectOtherAsset = - numberOfAssetsAvailable && numberOfAssetsAvailable > 1 - ? isInputEnabled || processState === OrderProcessState.Success - : false; - - const assetBuyer = state.providerState.assetBuyer; - return { - assetBuyer, - value: state.selectedAssetUnitAmount, - asset: selectedAsset, - isInputDisabled, - numberOfAssetsAvailable, - affiliateInfo: state.affiliateInfo, - canSelectOtherAsset, - }; -}; - -const debouncedUpdateBuyQuoteAsync = _.debounce(buyQuoteUpdater.updateBuyQuoteAsync.bind(buyQuoteUpdater), 200, { - trailing: true, -}) as typeof buyQuoteUpdater.updateBuyQuoteAsync; - -const mapDispatchToProps = ( - dispatch: Dispatch, - _ownProps: SelectedERC20AssetAmountInputProps, -): ConnectedDispatch => ({ - updateBuyQuote: (assetBuyer, value, asset, affiliateInfo) => { - // Update the input - dispatch(actions.updateSelectedAssetAmount(value)); - // invalidate the last buy quote. - dispatch(actions.updateLatestBuyQuote(undefined)); - // reset our buy state - dispatch(actions.setBuyOrderStateNone()); - - if (!_.isUndefined(value) && value.isGreaterThan(0) && !_.isUndefined(asset)) { - // even if it's debounced, give them the illusion it's loading - dispatch(actions.setQuoteRequestStatePending()); - // tslint:disable-next-line:no-floating-promises - debouncedUpdateBuyQuoteAsync(assetBuyer, dispatch, asset, value, QuoteFetchOrigin.Manual, { - setPending: true, - dispatchErrors: true, - affiliateInfo, - }); - } - }, -}); - -const mergeProps = ( - connectedState: ConnectedState, - connectedDispatch: ConnectedDispatch, - ownProps: SelectedERC20AssetAmountInputProps, -): FinalProps => { - return { - ...ownProps, - asset: connectedState.asset, - value: connectedState.value, - onChange: (value, asset) => { - connectedDispatch.updateBuyQuote(connectedState.assetBuyer, value, asset, connectedState.affiliateInfo); - }, - isInputDisabled: connectedState.isInputDisabled, - numberOfAssetsAvailable: connectedState.numberOfAssetsAvailable, - canSelectOtherAsset: connectedState.canSelectOtherAsset, - }; -}; - -export const SelectedERC20AssetAmountInput: React.ComponentClass = connect( - mapStateToProps, - mapDispatchToProps, - mergeProps, -)(ERC20AssetAmountInput); diff --git a/packages/instant/src/data/asset_data_network_mapping.ts b/packages/instant/src/data/asset_data_network_mapping.ts deleted file mode 100644 index 4fd0a25ed..000000000 --- a/packages/instant/src/data/asset_data_network_mapping.ts +++ /dev/null @@ -1,66 +0,0 @@ -import * as _ from 'lodash'; - -import { Network } from '../types'; - -interface AssetDataByNetwork { - [Network.Kovan]?: string; - [Network.Mainnet]?: string; -} - -export const assetDataNetworkMapping: AssetDataByNetwork[] = [ - // ZRX - { - [Network.Mainnet]: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498', - [Network.Kovan]: '0xf47261b00000000000000000000000002002d3812f58e35f0ea1ffbf80a75a38c32175fa', - }, - // SPANK - { - [Network.Mainnet]: '0xf47261b000000000000000000000000042d6622dece394b54999fbd73d108123806f6a18', - [Network.Kovan]: '0xf47261b00000000000000000000000007c9eee8448f3a7d1193389652d863b27e543272d', - }, - // OMG - { - [Network.Mainnet]: '0xf47261b0000000000000000000000000d26114cd6ee289accf82350c8d8487fedb8a0c07', - [Network.Kovan]: '0xf47261b000000000000000000000000046096d8ec059dbaae2950b30e01634ff0dc652ec', - }, - // MKR - { - [Network.Mainnet]: '0xf47261b00000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2', - // 0x Kovan MKR - [Network.Kovan]: '0xf47261b00000000000000000000000007b6b10caa9e8e9552ba72638ea5b47c25afea1f3', - }, - // BAT - { - [Network.Mainnet]: '0xf47261b00000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef', - [Network.Kovan]: '0xf47261b0000000000000000000000000c87faa7a58f0adf306bad9e7d892fb045a20e5af', - }, - // SNT - { - [Network.Mainnet]: '0xf47261b0000000000000000000000000744d70fdbe2ba4cf95131626614a1763df805b9e', - [Network.Kovan]: '0xf47261b00000000000000000000000009cfe76a718ea75e3e8ce4fc7ad0fef84be70919b', - }, - // MANA - { - [Network.Mainnet]: '0xf47261b00000000000000000000000000f5d2fb29fb7d3cfee444a200298f468908cc942', - [Network.Kovan]: '0xf47261b0000000000000000000000000c64edfc78321673435fbeebdaaa7f9d755963542', - }, - // GNT - { - [Network.Mainnet]: '0xf47261b0000000000000000000000000a74476443119a942de498590fe1f2454d7d4ac0d', - // 0x Kovan GNT - [Network.Kovan]: '0xf47261b000000000000000000000000031fb614e223706f15d0d3c5f4b08bdf0d5c78623', - }, - // SUB - { - [Network.Mainnet]: '0xf47261b000000000000000000000000012480e24eb5bec1a9d4369cab6a80cad3c0a377a', - }, - // Dentacoin - { - [Network.Mainnet]: '0xf47261b000000000000000000000000008d32b0da63e2C3bcF8019c9c5d849d7a9d791e6', - }, - // REP - { - [Network.Kovan]: '0xf47261b00000000000000000000000008cb3971b8eb709c14616bd556ff6683019e90d9c', - [Network.Mainnet]: '0xf47261b00000000000000000000000001985365e9f78359a9b6ad760e32412f4a445e862', - }, -]; diff --git a/packages/instant/src/data/asset_meta_data_map.ts b/packages/instant/src/data/asset_meta_data_map.ts deleted file mode 100644 index 88611a8c0..000000000 --- a/packages/instant/src/data/asset_meta_data_map.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { AssetProxyId, ObjectMap } from '@0x/types'; - -import { AssetMetaData } from '../types'; - -export const assetMetaDataMap: ObjectMap = { - '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#333333', - symbol: 'zrx', - name: '0x', - }, - '0xf47261b000000000000000000000000042d6622dece394b54999fbd73d108123806f6a18': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#EC4F81', - symbol: 'spank', - name: 'Spank', - }, - '0xf47261b0000000000000000000000000d26114cd6ee289accf82350c8d8487fedb8a0c07': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#2458E7', - symbol: 'omg', - name: 'OmiseGo', - }, - '0xf47261b00000000000000000000000009f8f72aa9304c8b593d555f12ef6589cc3a579a2': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#68CCBB', - symbol: 'mkr', - name: 'Maker', - }, - '0xf47261b00000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#FF5000', - symbol: 'bat', - name: 'Basic Attention Token', - }, - '0xf47261b0000000000000000000000000744d70fdbe2ba4cf95131626614a1763df805b9e': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#4763D7', - symbol: 'snt', - name: 'Status', - }, - '0xf47261b00000000000000000000000000f5d2fb29fb7d3cfee444a200298f468908cc942': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#f08839', - symbol: 'mana', - name: 'Decentraland', - }, - '0xf47261b00000000000000000000000001985365e9f78359a9b6ad760e32412f4a445e862': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#512D80', - symbol: 'rep', - name: 'Augur', - }, - '0xf47261b00000000000000000000000000abdace70d3790235af448c88547603b945604ea': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#2c3c8c', - symbol: 'dnt', - name: 'district0x', - }, - '0xf47261b000000000000000000000000005f4a42e251f2d52b8ed15e9fedaacfcef1fad27': { - assetProxyId: AssetProxyId.ERC20, - decimals: 12, - primaryColor: '#048998', - symbol: 'zil', - name: 'Zilliqa', - }, - '0xf47261b00000000000000000000000008f8221afbb33998d8584a2b05749ba73c37a938a': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#58BFD6', - symbol: 'req', - name: 'Request Network', - }, - '0xf47261b0000000000000000000000000e0b7927c4af23765cb51314a0e0521a9645f0e2a': { - assetProxyId: AssetProxyId.ERC20, - decimals: 9, - primaryColor: '#E1AA3E', - symbol: 'dgd', - name: 'DigixDao', - }, - '0xf47261b00000000000000000000000004f3afec4e5a3f2a6a1a411def7d7dfe50ee057bf': { - assetProxyId: AssetProxyId.ERC20, - decimals: 9, - primaryColor: '#E1AA3E', - symbol: 'dgx', - name: 'Digix Gold Token', - }, - '0xf47261b0000000000000000000000000419d0d8bdd9af5e606ae2232ed285aff190e711b': { - assetProxyId: AssetProxyId.ERC20, - decimals: 8, - primaryColor: '#E40057', - symbol: 'fun', - name: 'FunFair', - }, - '0xf47261b000000000000000000000000041e5560054824ea6b0732e656e3ad64e20e94e45': { - assetProxyId: AssetProxyId.ERC20, - decimals: 8, - primaryColor: '#04bc24', - symbol: 'cvc', - name: 'Civic', - }, - '0xf47261b00000000000000000000000005ca9a71b1d01849c0a95490cc00559717fcf0d1d': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#F7296E', - symbol: 'ae', - name: 'Aeternity', - }, - '0xf47261b0000000000000000000000000408e41876cccdc0f92210600ef50372656052a38': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#233C5A', - symbol: 'ren', - name: 'Republic Protocol', - }, - '0xf47261b0000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#325CD2', - symbol: 'link', - name: 'ChainLink', - }, - '0xf47261b00000000000000000000000006810e776880c02933d47db1b9fc05908e5386b96': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#48A4C0', - symbol: 'gno', - name: 'Gnosis', - }, - '0xf47261b0000000000000000000000000960b236a07cf122663c4303350609a66a7b288c0': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#04a29e', - symbol: 'ant', - name: 'Aragon', - }, - '0xf47261b00000000000000000000000004156d3342d5c385a87d264f90653733592000581': { - assetProxyId: AssetProxyId.ERC20, - decimals: 8, - primaryColor: '#4CABA7', - symbol: 'salt', - name: 'Salt', - }, - '0xf47261b0000000000000000000000000595832f8fc6bf59c85c527fec3740a1b7a361269': { - assetProxyId: AssetProxyId.ERC20, - decimals: 6, - primaryColor: '#5BC9D4', - symbol: 'powr', - name: 'PowerLedger', - }, - '0xf47261b00000000000000000000000008eb24319393716668d768dcec29356ae9cffe285': { - assetProxyId: AssetProxyId.ERC20, - decimals: 8, - primaryColor: '#523CE8', - symbol: 'agi', - name: 'SingularityNET', - }, - '0xf47261b000000000000000000000000039bb259f66e1c59d5abef88375979b4d20d98022': { - assetProxyId: AssetProxyId.ERC20, - decimals: 8, - primaryColor: '#EDB740', - symbol: 'wax', - name: 'WAX', - }, - '0xf47261b0000000000000000000000000beb9ef514a379b997e0798fdcc901ee474b6d9a1': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#333333', - symbol: 'mln', - name: 'Melon', - }, - '0xf47261b000000000000000000000000058b6a8a3302369daec383334672404ee733ab239': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#232D37', - symbol: 'lpt', - name: 'Livepeer', - }, - '0xf47261b000000000000000000000000027054b13b1b798b345b591a4d22e6562d47ea75a': { - assetProxyId: AssetProxyId.ERC20, - decimals: 4, - primaryColor: '#3A74F6', - symbol: 'ast', - name: 'AirSwap', - }, - '0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359': { - assetProxyId: AssetProxyId.ERC20, - decimals: 18, - primaryColor: '#DEA349', - symbol: 'dai', - name: 'Dai Stablecoin', - }, -}; diff --git a/packages/instant/src/globals.d.ts b/packages/instant/src/globals.d.ts deleted file mode 100644 index 1b5fa443d..000000000 --- a/packages/instant/src/globals.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -declare module '*.svg' { - const content: any; - /* tslint:disable */ - export default content; - /* tslint:enable */ -} -declare module '*.json' { - const json: any; - /* tslint:disable */ - export default json; - /* tslint:enable */ -} diff --git a/packages/instant/src/index.ts b/packages/instant/src/index.ts deleted file mode 100644 index 6e611dae8..000000000 --- a/packages/instant/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { ZeroExInstant, ZeroExInstantProps } from './components/zero_ex_instant'; -export { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './components/zero_ex_instant_overlay'; diff --git a/packages/instant/src/index.umd.ts b/packages/instant/src/index.umd.ts deleted file mode 100644 index 0acf3f2ad..000000000 --- a/packages/instant/src/index.umd.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { AssetBuyer, BigNumber } from '@0x/asset-buyer'; -import { assetDataUtils } from '@0x/order-utils'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; - -import { - DEFAULT_ZERO_EX_CONTAINER_SELECTOR, - GIT_SHA as GIT_SHA_FROM_CONSTANT, - INJECTED_DIV_CLASS, - INJECTED_DIV_ID, - NPM_PACKAGE_VERSION, -} from './constants'; -import { assetMetaDataMap } from './data/asset_meta_data_map'; -import { ZeroExInstantOverlay, ZeroExInstantOverlayProps } from './index'; -import { Network, OrderSource } from './types'; -import { analytics } from './util/analytics'; -import { assert } from './util/assert'; -import { providerFactory } from './util/provider_factory'; -import { util } from './util/util'; - -const isInstantRendered = (): boolean => !!document.getElementById(INJECTED_DIV_ID); - -const validateInstantRenderConfig = (config: ZeroExInstantConfig, selector: string) => { - assert.isValidOrderSource('orderSource', config.orderSource); - if (!_.isUndefined(config.defaultSelectedAssetData)) { - assert.isHexString('defaultSelectedAssetData', config.defaultSelectedAssetData); - } - if (!_.isUndefined(config.additionalAssetMetaDataMap)) { - assert.isValidAssetMetaDataMap('additionalAssetMetaDataMap', config.additionalAssetMetaDataMap); - } - if (!_.isUndefined(config.defaultAssetBuyAmount)) { - assert.isNumber('defaultAssetBuyAmount', config.defaultAssetBuyAmount); - } - if (!_.isUndefined(config.networkId)) { - assert.isNumber('networkId', config.networkId); - } - if (!_.isUndefined(config.availableAssetDatas)) { - assert.areValidAssetDatas('availableAssetDatas', config.availableAssetDatas); - } - if (!_.isUndefined(config.onClose)) { - assert.isFunction('onClose', config.onClose); - } - if (!_.isUndefined(config.zIndex)) { - assert.isNumber('zIndex', config.zIndex); - } - if (!_.isUndefined(config.affiliateInfo)) { - assert.isValidAffiliateInfo('affiliateInfo', config.affiliateInfo); - } - if (!_.isUndefined(config.provider)) { - assert.isWeb3Provider('provider', config.provider); - } - if (!_.isUndefined(config.walletDisplayName)) { - assert.isString('walletDisplayName', config.walletDisplayName); - } - if (!_.isUndefined(config.shouldDisablePushToHistory)) { - assert.isBoolean('shouldDisablePushToHistory', config.shouldDisablePushToHistory); - } - if (!_.isUndefined(config.shouldDisableAnalyticsTracking)) { - assert.isBoolean('shouldDisableAnalyticsTracking', config.shouldDisableAnalyticsTracking); - } - assert.isString('selector', selector); -}; - -// Render instant and return a callback that allows you to remove it from the DOM. -const renderInstant = (config: ZeroExInstantConfig, selector: string) => { - const appendToIfExists = document.querySelector(selector); - assert.assert(!_.isNull(appendToIfExists), `Could not find div with selector: ${selector}`); - const appendTo = appendToIfExists as Element; - const injectedDiv = document.createElement('div'); - injectedDiv.setAttribute('id', INJECTED_DIV_ID); - injectedDiv.setAttribute('class', INJECTED_DIV_CLASS); - appendTo.appendChild(injectedDiv); - const closeInstant = () => { - analytics.trackInstantClosed(); - if (!_.isUndefined(config.onClose)) { - config.onClose(); - } - appendTo.removeChild(injectedDiv); - }; - const instantOverlayProps = { - ...config, - // If we are using the history API, just go back to close - onClose: () => (config.shouldDisablePushToHistory ? closeInstant() : window.history.back()), - }; - ReactDOM.render(React.createElement(ZeroExInstantOverlay, instantOverlayProps), injectedDiv); - return closeInstant; -}; - -export interface ZeroExInstantConfig extends ZeroExInstantOverlayProps { - shouldDisablePushToHistory?: boolean; -} - -export const render = (config: ZeroExInstantConfig, selector: string = DEFAULT_ZERO_EX_CONTAINER_SELECTOR) => { - validateInstantRenderConfig(config, selector); - if (config.shouldDisablePushToHistory) { - if (!isInstantRendered()) { - renderInstant(config, selector); - } - return; - } - // Before we render, push to history saying that instant is showing for this part of the history. - window.history.pushState({ zeroExInstantShowing: true }, '0x Instant'); - let removeInstant = renderInstant(config, selector); - // If the integrator defined a popstate handler, save it to __zeroExInstantIntegratorsPopStateHandler - // unless we have already done so on a previous render. - const anyWindow = window as any; - const popStateExistsAndNotSetPreviously = window.onpopstate && !anyWindow.__zeroExInstantIntegratorsPopStateHandler; - anyWindow.__zeroExInstantIntegratorsPopStateHandler = popStateExistsAndNotSetPreviously - ? anyWindow.onpopstate.bind(window) - : util.boundNoop; - const onPopStateHandler = (e: PopStateEvent) => { - anyWindow.__zeroExInstantIntegratorsPopStateHandler(e); - const newState = e.state; - if (newState && newState.zeroExInstantShowing) { - // We have returned to a history state that expects instant to be rendered. - if (!isInstantRendered()) { - removeInstant = renderInstant(config, selector); - } - } else { - // History has changed to a different state. - if (isInstantRendered()) { - removeInstant(); - } - } - }; - window.onpopstate = onPopStateHandler; -}; - -export const assetDataForERC20TokenAddress = (tokenAddress: string): string => { - assert.isETHAddressHex('tokenAddress', tokenAddress); - return assetDataUtils.encodeERC20AssetData(tokenAddress); -}; - -export const hasMetaDataForAssetData = (assetData: string): boolean => { - assert.isHexString('assetData', assetData); - return assetMetaDataMap[assetData] !== undefined; -}; - -export const hasLiquidityForAssetDataAsync = async ( - assetData: string, - orderSource: OrderSource, - networkId: Network = Network.Mainnet, - provider?: Provider, -): Promise => { - assert.isHexString('assetData', assetData); - assert.isValidOrderSource('orderSource', orderSource); - assert.isNumber('networkId', networkId); - - if (provider !== undefined) { - assert.isWeb3Provider('provider', provider); - } - - const bestProvider: Provider = provider || providerFactory.getFallbackNoSigningProvider(networkId); - - const assetBuyerOptions = { networkId }; - - const assetBuyer = _.isString(orderSource) - ? AssetBuyer.getAssetBuyerForStandardRelayerAPIUrl(bestProvider, orderSource, assetBuyerOptions) - : AssetBuyer.getAssetBuyerForProvidedOrders(bestProvider, orderSource, assetBuyerOptions); - - const liquidity = await assetBuyer.getLiquidityForAssetDataAsync(assetData); - return liquidity.ethValueAvailableInWei.gt(new BigNumber(0)); -}; - -// Write version info to the exported object for debugging -export const GIT_SHA = GIT_SHA_FROM_CONSTANT; -export const NPM_VERSION = NPM_PACKAGE_VERSION; diff --git a/packages/instant/src/redux/actions.ts b/packages/instant/src/redux/actions.ts deleted file mode 100644 index ca0be543b..000000000 --- a/packages/instant/src/redux/actions.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { BuyQuote } from '@0x/asset-buyer'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { ActionsUnion, AddressAndEthBalanceInWei, Asset, BaseCurrency, StandardSlidingPanelContent } from '../types'; - -export interface PlainAction { - type: T; -} - -export interface ActionWithPayload extends PlainAction { - data: P; -} - -export type Action = ActionsUnion; - -function createAction(type: T): PlainAction; -function createAction(type: T, data: P): ActionWithPayload; -function createAction(type: T, data?: P): PlainAction | ActionWithPayload { - return _.isUndefined(data) ? { type } : { type, data }; -} - -export enum ActionTypes { - SetAccountStateLoading = 'SET_ACCOUNT_STATE_LOADING', - SetAccountStateLocked = 'SET_ACCOUNT_STATE_LOCKED', - SetAccountStateReady = 'SET_ACCOUNT_STATE_READY', - UpdateAccountEthBalance = 'UPDATE_ACCOUNT_ETH_BALANCE', - UpdateEthUsdPrice = 'UPDATE_ETH_USD_PRICE', - UpdateSelectedAssetUnitAmount = 'UPDATE_SELECTED_ASSET_UNIT_AMOUNT', - SetBuyOrderStateNone = 'SET_BUY_ORDER_STATE_NONE', - SetBuyOrderStateValidating = 'SET_BUY_ORDER_STATE_VALIDATING', - SetBuyOrderStateProcessing = 'SET_BUY_ORDER_STATE_PROCESSING', - SetBuyOrderStateFailure = 'SET_BUY_ORDER_STATE_FAILURE', - SetBuyOrderStateSuccess = 'SET_BUY_ORDER_STATE_SUCCESS', - UpdateLatestBuyQuote = 'UPDATE_LATEST_BUY_QUOTE', - UpdateSelectedAsset = 'UPDATE_SELECTED_ASSET', - SetAvailableAssets = 'SET_AVAILABLE_ASSETS', - SetQuoteRequestStatePending = 'SET_QUOTE_REQUEST_STATE_PENDING', - SetQuoteRequestStateFailure = 'SET_QUOTE_REQUEST_STATE_FAILURE', - SetErrorMessage = 'SET_ERROR_MESSAGE', - HideError = 'HIDE_ERROR', - ClearError = 'CLEAR_ERROR', - ResetAmount = 'RESET_AMOUNT', - OpenStandardSlidingPanel = 'OPEN_STANDARD_SLIDING_PANEL', - CloseStandardSlidingPanel = 'CLOSE_STANDARD_SLIDING_PANEL', - UpdateBaseCurrency = 'UPDATE_BASE_CURRENCY', -} - -export const actions = { - setAccountStateLoading: () => createAction(ActionTypes.SetAccountStateLoading), - setAccountStateLocked: () => createAction(ActionTypes.SetAccountStateLocked), - setAccountStateReady: (address: string) => createAction(ActionTypes.SetAccountStateReady, address), - updateAccountEthBalance: (addressAndBalance: AddressAndEthBalanceInWei) => - createAction(ActionTypes.UpdateAccountEthBalance, addressAndBalance), - updateEthUsdPrice: (price?: BigNumber) => createAction(ActionTypes.UpdateEthUsdPrice, price), - updateSelectedAssetAmount: (amount?: BigNumber) => createAction(ActionTypes.UpdateSelectedAssetUnitAmount, amount), - setBuyOrderStateNone: () => createAction(ActionTypes.SetBuyOrderStateNone), - setBuyOrderStateValidating: () => createAction(ActionTypes.SetBuyOrderStateValidating), - setBuyOrderStateProcessing: (txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => - createAction(ActionTypes.SetBuyOrderStateProcessing, { txHash, startTimeUnix, expectedEndTimeUnix }), - setBuyOrderStateFailure: (txHash: string) => createAction(ActionTypes.SetBuyOrderStateFailure, txHash), - setBuyOrderStateSuccess: (txHash: string) => createAction(ActionTypes.SetBuyOrderStateSuccess, txHash), - updateLatestBuyQuote: (buyQuote?: BuyQuote) => createAction(ActionTypes.UpdateLatestBuyQuote, buyQuote), - updateSelectedAsset: (asset: Asset) => createAction(ActionTypes.UpdateSelectedAsset, asset), - setAvailableAssets: (availableAssets: Asset[]) => createAction(ActionTypes.SetAvailableAssets, availableAssets), - setQuoteRequestStatePending: () => createAction(ActionTypes.SetQuoteRequestStatePending), - setQuoteRequestStateFailure: () => createAction(ActionTypes.SetQuoteRequestStateFailure), - setErrorMessage: (errorMessage: string) => createAction(ActionTypes.SetErrorMessage, errorMessage), - hideError: () => createAction(ActionTypes.HideError), - clearError: () => createAction(ActionTypes.ClearError), - resetAmount: () => createAction(ActionTypes.ResetAmount), - openStandardSlidingPanel: (content: StandardSlidingPanelContent) => - createAction(ActionTypes.OpenStandardSlidingPanel, content), - closeStandardSlidingPanel: () => createAction(ActionTypes.CloseStandardSlidingPanel), - updateBaseCurrency: (baseCurrency: BaseCurrency) => createAction(ActionTypes.UpdateBaseCurrency, baseCurrency), -}; diff --git a/packages/instant/src/redux/analytics_middleware.ts b/packages/instant/src/redux/analytics_middleware.ts deleted file mode 100644 index 4b4d30213..000000000 --- a/packages/instant/src/redux/analytics_middleware.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { AssetProxyId } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; -import { Middleware } from 'redux'; - -import { ETH_DECIMALS } from '../constants'; -import { AccountState, StandardSlidingPanelContent } from '../types'; -import { analytics, AnalyticsEventOptions } from '../util/analytics'; - -import { Action, ActionTypes } from './actions'; - -import { State } from './reducer'; - -export const analyticsMiddleware: Middleware = store => next => middlewareAction => { - const prevState = store.getState() as State; - const prevAccount = prevState.providerState.account; - - const nextAction = next(middlewareAction) as Action; - - const curState = store.getState() as State; - const curAccount = curState.providerState.account; - - switch (nextAction.type) { - case ActionTypes.SetAccountStateReady: - if (curAccount.state === AccountState.Ready) { - const didJustTurnReady = prevAccount.state !== AccountState.Ready; - const didJustUpdateAddress = - prevAccount.state === AccountState.Ready && prevAccount.address !== curAccount.address; - const ethAddress = curAccount.address; - if (didJustTurnReady) { - analytics.trackAccountReady(ethAddress); - analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); - analytics.addEventProperties({ ethAddress }); - } else if (didJustUpdateAddress) { - analytics.trackAccountAddressChanged(ethAddress); - analytics.addUserProperties({ lastKnownEthAddress: ethAddress }); - analytics.addEventProperties({ ethAddress }); - } - } - break; - case ActionTypes.SetAccountStateLocked: - if (prevAccount.state !== AccountState.Locked && curAccount.state === AccountState.Locked) { - // if we are moving from account not locked to account locked, track `Account - Locked` - analytics.trackAccountLocked(); - } - break; - case ActionTypes.UpdateAccountEthBalance: - if ( - curAccount.state === AccountState.Ready && - curAccount.ethBalanceInWei && - !_.isEqual(curAccount, prevAccount) - ) { - const ethBalanceInUnitAmount = Web3Wrapper.toUnitAmount( - curAccount.ethBalanceInWei, - ETH_DECIMALS, - ).toString(); - analytics.addUserProperties({ lastEthBalanceInUnitAmount: ethBalanceInUnitAmount }); - analytics.addEventProperties({ ethBalanceInUnitAmount }); - } - break; - case ActionTypes.UpdateSelectedAsset: - const selectedAsset = curState.selectedAsset; - if (selectedAsset) { - const assetName = selectedAsset.metaData.name; - const assetData = selectedAsset.assetData; - analytics.trackTokenSelectorChose({ - assetName, - assetData, - }); - - const selectedAssetEventProperties: AnalyticsEventOptions = { - selectedAssetName: assetName, - selectedAssetData: assetData, - }; - if (selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20) { - selectedAssetEventProperties.selectedAssetDecimals = selectedAsset.metaData.decimals; - selectedAssetEventProperties.selectedAssetSymbol = selectedAsset.metaData.symbol; - } - analytics.addEventProperties(selectedAssetEventProperties); - } - break; - case ActionTypes.SetAvailableAssets: - const availableAssets = curState.availableAssets; - if (availableAssets) { - analytics.addEventProperties({ - numberAvailableAssets: availableAssets.length, - }); - } - break; - case ActionTypes.OpenStandardSlidingPanel: - const openSlidingContent = curState.standardSlidingPanelSettings.content; - if (openSlidingContent === StandardSlidingPanelContent.InstallWallet) { - analytics.trackInstallWalletModalOpened(); - } - break; - case ActionTypes.CloseStandardSlidingPanel: - const closeSlidingContent = curState.standardSlidingPanelSettings.content; - if (closeSlidingContent === StandardSlidingPanelContent.InstallWallet) { - analytics.trackInstallWalletModalClosed(); - } - break; - case ActionTypes.UpdateBaseCurrency: - analytics.trackBaseCurrencyChanged(curState.baseCurrency); - analytics.addEventProperties({ baseCurrency: curState.baseCurrency }); - } - - return nextAction; -}; diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts deleted file mode 100644 index f20fe319f..000000000 --- a/packages/instant/src/redux/async_data.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { AssetProxyId } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; -import { Dispatch } from 'redux'; - -import { BIG_NUMBER_ZERO } from '../constants'; -import { AccountState, BaseCurrency, ERC20Asset, OrderProcessState, ProviderState, QuoteFetchOrigin } from '../types'; -import { analytics } from '../util/analytics'; -import { assetUtils } from '../util/asset'; -import { buyQuoteUpdater } from '../util/buy_quote_updater'; -import { coinbaseApi } from '../util/coinbase_api'; -import { errorFlasher } from '../util/error_flasher'; -import { errorReporter } from '../util/error_reporter'; - -import { actions } from './actions'; -import { State } from './reducer'; - -export const asyncData = { - fetchEthPriceAndDispatchToStore: async (dispatch: Dispatch) => { - try { - const ethUsdPrice = await coinbaseApi.getEthUsdPrice(); - dispatch(actions.updateEthUsdPrice(ethUsdPrice)); - } catch (e) { - const errorMessage = 'Error fetching ETH/USD price'; - errorFlasher.flashNewErrorMessage(dispatch, errorMessage); - dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO)); - dispatch(actions.updateBaseCurrency(BaseCurrency.ETH)); - errorReporter.report(e); - analytics.trackUsdPriceFailed(); - } - }, - fetchAvailableAssetDatasAndDispatchToStore: async (state: State, dispatch: Dispatch) => { - const { providerState, assetMetaDataMap, network } = state; - const assetBuyer = providerState.assetBuyer; - try { - const assetDatas = await assetBuyer.getAvailableAssetDatasAsync(); - const deduplicatedAssetDatas = _.uniq(assetDatas); - const assets = assetUtils.createAssetsFromAssetDatas(deduplicatedAssetDatas, assetMetaDataMap, network); - dispatch(actions.setAvailableAssets(assets)); - } catch (e) { - const errorMessage = 'Could not find any assets'; - errorFlasher.flashNewErrorMessage(dispatch, errorMessage); - // On error, just specify that none are available - dispatch(actions.setAvailableAssets([])); - errorReporter.report(e); - } - }, - fetchAccountInfoAndDispatchToStore: async ( - providerState: ProviderState, - dispatch: Dispatch, - shouldAttemptUnlock: boolean = false, - shouldSetToLoading: boolean = false, - ) => { - const web3Wrapper = providerState.web3Wrapper; - const provider = providerState.provider; - if (shouldSetToLoading && providerState.account.state !== AccountState.Loading) { - dispatch(actions.setAccountStateLoading()); - } - let availableAddresses: string[]; - try { - // TODO(bmillman): Add support at the web3Wrapper level for calling `eth_requestAccounts` instead of calling enable here - const isPrivacyModeEnabled = !_.isUndefined((provider as any).enable); - availableAddresses = - isPrivacyModeEnabled && shouldAttemptUnlock - ? await (provider as any).enable() - : await web3Wrapper.getAvailableAddressesAsync(); - } catch (e) { - analytics.trackAccountUnlockDenied(); - dispatch(actions.setAccountStateLocked()); - return; - } - if (!_.isEmpty(availableAddresses)) { - const activeAddress = availableAddresses[0]; - dispatch(actions.setAccountStateReady(activeAddress)); - // tslint:disable-next-line:no-floating-promises - asyncData.fetchAccountBalanceAndDispatchToStore(activeAddress, providerState.web3Wrapper, dispatch); - } else { - dispatch(actions.setAccountStateLocked()); - } - }, - fetchAccountBalanceAndDispatchToStore: async (address: string, web3Wrapper: Web3Wrapper, dispatch: Dispatch) => { - try { - const ethBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(address); - dispatch(actions.updateAccountEthBalance({ address, ethBalanceInWei })); - } catch (e) { - errorReporter.report(e); - // leave balance as is - return; - } - }, - fetchCurrentBuyQuoteAndDispatchToStore: async ( - state: State, - dispatch: Dispatch, - fetchOrigin: QuoteFetchOrigin, - options: { updateSilently: boolean }, - ) => { - const { buyOrderState, providerState, selectedAsset, selectedAssetUnitAmount, affiliateInfo } = state; - const assetBuyer = providerState.assetBuyer; - if ( - !_.isUndefined(selectedAssetUnitAmount) && - !_.isUndefined(selectedAsset) && - selectedAssetUnitAmount.isGreaterThan(BIG_NUMBER_ZERO) && - buyOrderState.processState === OrderProcessState.None && - selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20 - ) { - await buyQuoteUpdater.updateBuyQuoteAsync( - assetBuyer, - dispatch, - selectedAsset as ERC20Asset, - selectedAssetUnitAmount, - fetchOrigin, - { - setPending: !options.updateSilently, - dispatchErrors: !options.updateSilently, - affiliateInfo, - }, - ); - } - }, -}; diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts deleted file mode 100644 index 0d8bb4b05..000000000 --- a/packages/instant/src/redux/reducer.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { BuyQuote } from '@0x/asset-buyer'; -import { AssetProxyId, ObjectMap } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; - -import { LOADING_ACCOUNT, LOCKED_ACCOUNT } from '../constants'; -import { assetMetaDataMap } from '../data/asset_meta_data_map'; -import { - Account, - AccountReady, - AccountState, - AffiliateInfo, - Asset, - AssetMetaData, - AsyncProcessState, - BaseCurrency, - DisplayStatus, - Network, - OrderProcessState, - OrderState, - ProviderState, - StandardSlidingPanelContent, - StandardSlidingPanelSettings, -} from '../types'; - -import { Action, ActionTypes } from './actions'; - -// State that is required and we have defaults for, before props are passed in -export interface DefaultState { - network: Network; - assetMetaDataMap: ObjectMap; - buyOrderState: OrderState; - latestErrorDisplayStatus: DisplayStatus; - quoteRequestState: AsyncProcessState; - standardSlidingPanelSettings: StandardSlidingPanelSettings; - baseCurrency: BaseCurrency; -} - -// State that is required but needs to be derived from the props -interface PropsDerivedState { - providerState: ProviderState; -} - -// State that is optional -interface OptionalState { - selectedAsset: Asset; - availableAssets: Asset[]; - selectedAssetUnitAmount: BigNumber; - ethUsdPrice: BigNumber; - latestBuyQuote: BuyQuote; - latestErrorMessage: string; - affiliateInfo: AffiliateInfo; - walletDisplayName: string; -} - -export type State = DefaultState & PropsDerivedState & Partial; - -export const DEFAULT_STATE: DefaultState = { - network: Network.Mainnet, - assetMetaDataMap, - buyOrderState: { processState: OrderProcessState.None }, - latestErrorDisplayStatus: DisplayStatus.Hidden, - quoteRequestState: AsyncProcessState.None, - standardSlidingPanelSettings: { - animationState: 'none', - content: StandardSlidingPanelContent.None, - }, - baseCurrency: BaseCurrency.USD, -}; - -export const createReducer = (initialState: State) => { - const reducer = (state: State = initialState, action: Action): State => { - switch (action.type) { - case ActionTypes.SetAccountStateLoading: - return reduceStateWithAccount(state, LOADING_ACCOUNT); - case ActionTypes.SetAccountStateLocked: - return reduceStateWithAccount(state, LOCKED_ACCOUNT); - case ActionTypes.SetAccountStateReady: { - const address = action.data; - let newAccount: AccountReady = { - state: AccountState.Ready, - address, - }; - const currentAccount = state.providerState.account; - if (currentAccount.state === AccountState.Ready && currentAccount.address === address) { - newAccount = { - ...newAccount, - ethBalanceInWei: currentAccount.ethBalanceInWei, - }; - } - return reduceStateWithAccount(state, newAccount); - } - case ActionTypes.UpdateAccountEthBalance: { - const { address, ethBalanceInWei } = action.data; - const currentAccount = state.providerState.account; - if (currentAccount.state !== AccountState.Ready || currentAccount.address !== address) { - return state; - } else { - const newAccount: AccountReady = { - ...currentAccount, - ethBalanceInWei, - }; - return reduceStateWithAccount(state, newAccount); - } - } - case ActionTypes.UpdateEthUsdPrice: - return { - ...state, - ethUsdPrice: action.data, - }; - case ActionTypes.UpdateSelectedAssetUnitAmount: - return { - ...state, - selectedAssetUnitAmount: action.data, - }; - case ActionTypes.UpdateLatestBuyQuote: - const newBuyQuoteIfExists = action.data; - const shouldUpdate = - _.isUndefined(newBuyQuoteIfExists) || doesBuyQuoteMatchState(newBuyQuoteIfExists, state); - if (shouldUpdate) { - return { - ...state, - latestBuyQuote: newBuyQuoteIfExists, - quoteRequestState: AsyncProcessState.Success, - }; - } else { - return state; - } - case ActionTypes.SetQuoteRequestStatePending: - return { - ...state, - latestBuyQuote: undefined, - quoteRequestState: AsyncProcessState.Pending, - }; - case ActionTypes.SetQuoteRequestStateFailure: - return { - ...state, - latestBuyQuote: undefined, - quoteRequestState: AsyncProcessState.Failure, - }; - case ActionTypes.SetBuyOrderStateNone: - return { - ...state, - buyOrderState: { processState: OrderProcessState.None }, - }; - case ActionTypes.SetBuyOrderStateValidating: - return { - ...state, - buyOrderState: { processState: OrderProcessState.Validating }, - }; - case ActionTypes.SetBuyOrderStateProcessing: - const processingData = action.data; - const { startTimeUnix, expectedEndTimeUnix } = processingData; - return { - ...state, - buyOrderState: { - processState: OrderProcessState.Processing, - txHash: processingData.txHash, - progress: { - startTimeUnix, - expectedEndTimeUnix, - }, - }, - }; - case ActionTypes.SetBuyOrderStateFailure: - const failureTxHash = action.data; - if ('txHash' in state.buyOrderState) { - if (state.buyOrderState.txHash === failureTxHash) { - const { txHash, progress } = state.buyOrderState; - return { - ...state, - buyOrderState: { - processState: OrderProcessState.Failure, - txHash, - progress, - }, - }; - } - } - return state; - case ActionTypes.SetBuyOrderStateSuccess: - const successTxHash = action.data; - if ('txHash' in state.buyOrderState) { - if (state.buyOrderState.txHash === successTxHash) { - const { txHash, progress } = state.buyOrderState; - return { - ...state, - buyOrderState: { - processState: OrderProcessState.Success, - txHash, - progress, - }, - }; - } - } - return state; - case ActionTypes.SetErrorMessage: - return { - ...state, - latestErrorMessage: action.data, - latestErrorDisplayStatus: DisplayStatus.Present, - }; - case ActionTypes.HideError: - return { - ...state, - latestErrorDisplayStatus: DisplayStatus.Hidden, - }; - case ActionTypes.ClearError: - return { - ...state, - latestErrorMessage: undefined, - latestErrorDisplayStatus: DisplayStatus.Hidden, - }; - case ActionTypes.UpdateSelectedAsset: - return { - ...state, - selectedAsset: action.data, - }; - case ActionTypes.ResetAmount: - return { - ...state, - latestBuyQuote: undefined, - quoteRequestState: AsyncProcessState.None, - buyOrderState: { processState: OrderProcessState.None }, - selectedAssetUnitAmount: undefined, - }; - case ActionTypes.SetAvailableAssets: - return { - ...state, - availableAssets: action.data, - }; - case ActionTypes.OpenStandardSlidingPanel: - return { - ...state, - standardSlidingPanelSettings: { - content: action.data, - animationState: 'slidIn', - }, - }; - case ActionTypes.CloseStandardSlidingPanel: - return { - ...state, - standardSlidingPanelSettings: { - content: state.standardSlidingPanelSettings.content, - animationState: 'slidOut', - }, - }; - case ActionTypes.UpdateBaseCurrency: - return { - ...state, - baseCurrency: action.data, - }; - default: - return state; - } - }; - return reducer; -}; - -const reduceStateWithAccount = (state: State, account: Account) => { - const oldProviderState = state.providerState; - const newProviderState: ProviderState = { - ...oldProviderState, - account, - }; - return { - ...state, - providerState: newProviderState, - }; -}; - -const doesBuyQuoteMatchState = (buyQuote: BuyQuote, state: State): boolean => { - const selectedAssetIfExists = state.selectedAsset; - const selectedAssetUnitAmountIfExists = state.selectedAssetUnitAmount; - // if no selectedAsset or selectedAssetAmount exists on the current state, return false - if (_.isUndefined(selectedAssetIfExists) || _.isUndefined(selectedAssetUnitAmountIfExists)) { - return false; - } - // if buyQuote's assetData does not match that of the current selected asset, return false - if (selectedAssetIfExists.assetData !== buyQuote.assetData) { - return false; - } - // if ERC20 and buyQuote's assetBuyAmount does not match selectedAssetAmount, return false - // if ERC721, return true - const selectedAssetMetaData = selectedAssetIfExists.metaData; - if (selectedAssetMetaData.assetProxyId === AssetProxyId.ERC20) { - const selectedAssetAmountBaseUnits = Web3Wrapper.toBaseUnitAmount( - selectedAssetUnitAmountIfExists, - selectedAssetMetaData.decimals, - ); - const doesAssetAmountMatch = selectedAssetAmountBaseUnits.eq(buyQuote.assetBuyAmount); - return doesAssetAmountMatch; - } else { - return true; - } -}; diff --git a/packages/instant/src/redux/store.ts b/packages/instant/src/redux/store.ts deleted file mode 100644 index 11bba3876..000000000 --- a/packages/instant/src/redux/store.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as _ from 'lodash'; -import { applyMiddleware, createStore, Store as ReduxStore } from 'redux'; -import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly'; - -import { analyticsMiddleware } from './analytics_middleware'; -import { createReducer, State } from './reducer'; - -export type Store = ReduxStore; - -export const store = { - create: (initialState: State): Store => { - const reducer = createReducer(initialState); - return createStore(reducer, initialState, composeWithDevTools(applyMiddleware(analyticsMiddleware))); - }, -}; diff --git a/packages/instant/src/style/fonts.ts b/packages/instant/src/style/fonts.ts deleted file mode 100644 index 92450502d..000000000 --- a/packages/instant/src/style/fonts.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const fonts = { - include: () => { - // Inject the inter-ui font into the page - const appendTo = document.head || document.getElementsByTagName('head')[0] || document.body; - const style = document.createElement('style'); - style.type = 'text/css'; - style.appendChild(document.createTextNode(`@import url('https://rsms.me/inter/inter-ui.css')`)); - appendTo.appendChild(style); - }, -}; diff --git a/packages/instant/src/style/media.ts b/packages/instant/src/style/media.ts deleted file mode 100644 index bbf376694..000000000 --- a/packages/instant/src/style/media.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { InterpolationValue } from 'styled-components'; - -import { css } from './theme'; - -export enum ScreenWidths { - Sm = 40, - Md = 52, - Lg = 64, -} - -export const generateMediaWrapper = (screenWidth: ScreenWidths) => (...args: any[]) => css` - @media (max-width: ${screenWidth}em) { - ${css.apply(css, args)}; - } -`; - -export const media = { - small: generateMediaWrapper(ScreenWidths.Sm), - medium: generateMediaWrapper(ScreenWidths.Md), - large: generateMediaWrapper(ScreenWidths.Lg), -}; - -export interface ScreenSpecification { - default: T; - sm?: T; - md?: T; - lg?: T; -} -export type OptionallyScreenSpecific = T | ScreenSpecification; -export type MediaChoice = OptionallyScreenSpecific; -/** - * Given a css property name and a OptionallyScreenSpecific value, - * generates css properties with screen-specific viewport styling - */ -export function stylesForMedia( - cssPropertyName: string, - choice: OptionallyScreenSpecific, -): InterpolationValue[] { - if (typeof choice === 'object') { - return css` - ${cssPropertyName}: ${choice.default}; - ${choice.lg && media.large`${cssPropertyName}: ${choice.lg}`} - ${choice.md && media.medium`${cssPropertyName}: ${choice.md}`} - ${choice.sm && media.small`${cssPropertyName}: ${choice.sm}`} - `; - } else { - return css` - ${cssPropertyName}: ${choice}; - `; - } -} diff --git a/packages/instant/src/style/theme.ts b/packages/instant/src/style/theme.ts deleted file mode 100644 index 49f3c81e6..000000000 --- a/packages/instant/src/style/theme.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as styledComponents from 'styled-components'; - -const { - default: styled, - css, - keyframes, - withTheme, - createGlobalStyle, - ThemeConsumer, - ThemeProvider, -} = styledComponents; - -export type Theme = { [key in ColorOption]: string }; -// tslint:disable:enum-naming -export enum ColorOption { - primaryColor = 'primaryColor', - black = 'black', - lightGrey = 'lightGrey', - grey = 'grey', - feintGrey = 'feintGrey', - lightestGrey = 'lightestGrey', - darkGrey = 'darkGrey', - white = 'white', - lightOrange = 'lightOrange', - darkOrange = 'darkOrange', - green = 'green', - red = 'red', - darkBlue = 'darkBlue', - lightBlue = 'lightBlue', -} - -export const theme: Theme = { - primaryColor: '#333', - black: 'black', - lightGrey: '#999999', - grey: '#666666', - feintGrey: '#DEDEDE', - lightestGrey: '#EEEEEE', - darkGrey: '#333333', - white: 'white', - lightOrange: '#FFF8F2', - darkOrange: '#F7A24F', - green: '#3CB34F', - red: '#D00000', - darkBlue: '#135df6', - lightBlue: '#F2F7FF', -}; - -export const transparentWhite = 'rgba(255,255,255,0.3)'; -export const completelyTransparent = 'rga(0, 0, 0, 0)'; - -export const generateOverlayBlack = (opacity = 0.6) => { - return `rgba(0, 0, 0, ${opacity})`; -}; - -export { styled, css, keyframes, withTheme, createGlobalStyle, ThemeConsumer, ThemeProvider }; diff --git a/packages/instant/src/style/util.ts b/packages/instant/src/style/util.ts deleted file mode 100644 index 3e38c4a7d..000000000 --- a/packages/instant/src/style/util.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ObjectMap } from '@0x/types'; -import * as _ from 'lodash'; - -export const cssRuleIfExists = (props: ObjectMap, rule: string): string => { - const camelCaseRule = _.camelCase(rule); - const ruleValueIfExists = props[camelCaseRule]; - if (!_.isUndefined(ruleValueIfExists)) { - return `${rule}: ${ruleValueIfExists};`; - } - return ''; -}; diff --git a/packages/instant/src/style/z_index.ts b/packages/instant/src/style/z_index.ts deleted file mode 100644 index ba2d27a17..000000000 --- a/packages/instant/src/style/z_index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const zIndex = { - errorPopBehind: 10, - mainContainer: 20, - dropdownItems: 30, - panel: 40, - containerOverlay: 45, - errorPopup: 50, - overlayDefault: 100, -}; diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts deleted file mode 100644 index 606294c93..000000000 --- a/packages/instant/src/types.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { AssetBuyer, BigNumber } from '@0x/asset-buyer'; -import { AssetProxyId, ObjectMap, SignedOrder } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { Provider } from 'ethereum-types'; - -// Reusable -export type Omit = Pick>; -export type Maybe = T | undefined; -export enum AsyncProcessState { - None = 'NONE', - Pending = 'PENDING', - Success = 'SUCCESS', - Failure = 'FAILURE', -} - -export enum OrderProcessState { - None = 'NONE', - Validating = 'VALIDATING', - Processing = 'PROCESSING', - Success = 'SUCCESS', - Failure = 'FAILURE', -} - -export enum QuoteFetchOrigin { - Manual = 'Manual', - Heartbeat = 'Heartbeat', -} - -export enum BaseCurrency { - USD = 'USD', // tslint:disable-line:enum-naming - ETH = 'ETH', // tslint:disable-line:enum-naming -} - -export interface SimulatedProgress { - startTimeUnix: number; - expectedEndTimeUnix: number; -} - -interface OrderStatePreTx { - processState: OrderProcessState.None | OrderProcessState.Validating; -} -interface OrderStatePostTx { - processState: OrderProcessState.Processing | OrderProcessState.Success | OrderProcessState.Failure; - txHash: string; - progress: SimulatedProgress; -} -export type OrderState = OrderStatePreTx | OrderStatePostTx; - -export enum DisplayStatus { - Present, - Hidden, -} - -export type FunctionType = (...args: any[]) => any; -export type ActionCreatorsMapObject = ObjectMap; -export type ActionsUnion = ReturnType; - -export interface ERC20AssetMetaData { - assetProxyId: AssetProxyId.ERC20; - decimals: number; - primaryColor?: string; - symbol: string; - name: string; - iconUrl?: string; -} - -export interface ERC721AssetMetaData { - assetProxyId: AssetProxyId.ERC721; - name: string; - imageUrl?: string; - primaryColor?: string; -} - -export type AssetMetaData = ERC20AssetMetaData | ERC721AssetMetaData; - -export interface ERC20Asset { - assetData: string; - metaData: ERC20AssetMetaData; -} - -export interface ERC721Asset { - assetData: string; - metaData: ERC721AssetMetaData; -} - -export interface Asset { - assetData: string; - metaData: AssetMetaData; -} - -export enum Network { - Kovan = 42, - Mainnet = 1, -} - -export enum ZeroExInstantError { - AssetMetaDataNotAvailable = 'ASSET_META_DATA_NOT_AVAILABLE', - InsufficientETH = 'INSUFFICIENT_ETH', // tslint:disable-line:enum-naming - CouldNotSubmitTransaction = 'COULD_NOT_SUBMIT_TRANSACTION', -} - -export type SimpleHandler = () => void; - -export interface AffiliateInfo { - feeRecipient: string; - feePercentage: number; -} - -export interface ProviderState { - name: string; - displayName: string; - provider: Provider; - assetBuyer: AssetBuyer; - web3Wrapper: Web3Wrapper; - account: Account; -} - -export enum AccountState { - None = 'NONE,', - Loading = 'LOADING', - Ready = 'READY', - Locked = 'LOCKED', -} - -export interface AccountReady { - state: AccountState.Ready; - address: string; - ethBalanceInWei?: BigNumber; -} -export interface AccountNotReady { - state: AccountState.None | AccountState.Loading | AccountState.Locked; -} - -export type Account = AccountReady | AccountNotReady; - -export type OrderSource = string | SignedOrder[]; - -export interface AddressAndEthBalanceInWei { - address: string; - ethBalanceInWei: BigNumber; -} - -export type SlideAnimationState = 'slidIn' | 'slidOut' | 'none'; - -export enum StandardSlidingPanelContent { - None = 'NONE', - InstallWallet = 'INSTALL_WALLET', -} - -export interface StandardSlidingPanelSettings { - animationState: SlideAnimationState; - content: StandardSlidingPanelContent; -} - -export enum Browser { - Chrome = 'CHROME', - Firefox = 'FIREFOX', - Opera = 'OPERA', - Safari = 'SAFARI', - Edge = 'EDGE', - Other = 'OTHER', -} - -export enum WalletSuggestion { - CoinbaseWallet = 'Coinbase Wallet', - MetaMask = 'MetaMask', -} - -export enum OperatingSystem { - Android = 'ANDROID', - iOS = 'IOS', // tslint:disable-line:enum-naming - Mac = 'MAC', - Windows = 'WINDOWS', - WindowsPhone = 'WINDOWS_PHONE', - Linux = 'LINUX', - Other = 'OTHER', -} - -export enum ProviderType { - Parity = 'PARITY', - MetaMask = 'META_MASK', - Mist = 'MIST', - CoinbaseWallet = 'COINBASE_WALLET', - Cipher = 'CIPHER', - TrustWallet = 'TRUST_WALLET', - Opera = 'OPERA', - Fallback = 'FALLBACK', -} - -export interface ZeroExInstantRequiredBaseConfig { - orderSource: OrderSource; -} - -export interface ZeroExInstantOptionalBaseConfig { - provider: Provider; - walletDisplayName: string; - availableAssetDatas: string[]; - defaultAssetBuyAmount: number; - defaultSelectedAssetData: string; - additionalAssetMetaDataMap: ObjectMap; - networkId: Network; - affiliateInfo: AffiliateInfo; - shouldDisableAnalyticsTracking: boolean; -} - -export type ZeroExInstantBaseConfig = ZeroExInstantRequiredBaseConfig & Partial; diff --git a/packages/instant/src/util/address.ts b/packages/instant/src/util/address.ts deleted file mode 100644 index b21863a8e..000000000 --- a/packages/instant/src/util/address.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Web3Wrapper } from '@0x/web3-wrapper'; - -export const getBestAddress = async (web3Wrapper: Web3Wrapper): Promise => { - const addresses = await web3Wrapper.getAvailableAddressesAsync(); - return addresses[0]; -}; diff --git a/packages/instant/src/util/analytics.ts b/packages/instant/src/util/analytics.ts deleted file mode 100644 index fa8a72a2c..000000000 --- a/packages/instant/src/util/analytics.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { BuyQuote } from '@0x/asset-buyer'; -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { GIT_SHA, HEAP_ENABLED, INSTANT_DISCHARGE_TARGET, NODE_ENV, NPM_PACKAGE_VERSION } from '../constants'; -import { - AffiliateInfo, - Asset, - BaseCurrency, - Network, - OrderProcessState, - OrderSource, - ProviderState, - QuoteFetchOrigin, - WalletSuggestion, -} from '../types'; - -import { EventProperties, heapUtil } from './heap'; - -let isDisabledViaConfig = false; -export const disableAnalytics = (shouldDisableAnalytics: boolean) => { - isDisabledViaConfig = shouldDisableAnalytics; -}; -export const evaluateIfEnabled = (fnCall: () => void) => { - if (isDisabledViaConfig) { - return; - } - if (HEAP_ENABLED) { - fnCall(); - } -}; - -enum EventNames { - InstantOpened = 'Instant - Opened', - InstantClosed = 'Instant - Closed', - AccountLocked = 'Account - Locked', - AccountReady = 'Account - Ready', - AccountUnlockRequested = 'Account - Unlock Requested', - AccountUnlockDenied = 'Account - Unlock Denied', - AccountAddressChanged = 'Account - Address Changed', - BaseCurrencyChanged = 'Base Currency - Changed', - PaymentMethodDropdownOpened = 'Payment Method - Dropdown Opened', - PaymentMethodOpenedEtherscan = 'Payment Method - Opened Etherscan', - PaymentMethodCopiedAddress = 'Payment Method - Copied Address', - BuyNotEnoughEth = 'Buy - Not Enough Eth', - BuyStarted = 'Buy - Started', - BuySignatureDenied = 'Buy - Signature Denied', - BuySimulationFailed = 'Buy - Simulation Failed', - BuyUnknownError = 'Buy - Unknown Error', - BuyTxSubmitted = 'Buy - Tx Submitted', - BuyTxSucceeded = 'Buy - Tx Succeeded', - BuyTxFailed = 'Buy - Tx Failed', - UsdPriceFetchFailed = 'USD Price - Fetch Failed', - InstallWalletClicked = 'Install Wallet - Clicked', - InstallWalletModalOpened = 'Install Wallet - Modal - Opened', - InstallWalletModalClickedExplanation = 'Install Wallet - Modal - Clicked Explanation', - InstallWalletModalClickedGet = 'Install Wallet - Modal - Clicked Get', - InstallWalletModalClosed = 'Install Wallet - Modal - Closed', - TokenSelectorOpened = 'Token Selector - Opened', - TokenSelectorClosed = 'Token Selector - Closed', - TokenSelectorChose = 'Token Selector - Chose', - TokenSelectorSearched = 'Token Selector - Searched', - TransactionViewed = 'Transaction - Viewed', - QuoteFetched = 'Quote - Fetched', - QuoteError = 'Quote - Error', -} - -const track = (eventName: EventNames, eventProperties: EventProperties = {}): void => { - evaluateIfEnabled(() => { - heapUtil.evaluateHeapCall(heap => heap.track(eventName, eventProperties)); - }); -}; -function trackingEventFnWithoutPayload(eventName: EventNames): () => void { - return () => { - track(eventName); - }; -} -// tslint:disable-next-line:no-unused-variable -function trackingEventFnWithPayload(eventName: EventNames): (eventProperties: EventProperties) => void { - return (eventProperties: EventProperties) => { - track(eventName, eventProperties); - }; -} - -const buyQuoteEventProperties = (buyQuote: BuyQuote) => { - const assetBuyAmount = buyQuote.assetBuyAmount.toString(); - const assetEthAmount = buyQuote.worstCaseQuoteInfo.assetEthAmount.toString(); - const feeEthAmount = buyQuote.worstCaseQuoteInfo.feeEthAmount.toString(); - const totalEthAmount = buyQuote.worstCaseQuoteInfo.totalEthAmount.toString(); - const feePercentage = !_.isUndefined(buyQuote.feePercentage) ? buyQuote.feePercentage.toString() : 0; - const hasFeeOrders = !_.isEmpty(buyQuote.feeOrders) ? 'true' : 'false'; - return { - assetBuyAmount, - assetEthAmount, - feeEthAmount, - totalEthAmount, - feePercentage, - hasFeeOrders, - }; -}; - -export interface AnalyticsUserOptions { - lastKnownEthAddress?: string; - lastEthBalanceInUnitAmount?: string; -} -export interface AnalyticsEventOptions { - embeddedHost?: string; - embeddedUrl?: string; - ethBalanceInUnitAmount?: string; - ethAddress?: string; - networkId?: number; - providerName?: string; - providerDisplayName?: string; - gitSha?: string; - npmVersion?: string; - instantEnvironment?: string; - orderSource?: string; - affiliateAddress?: string; - affiliateFeePercent?: number; - numberAvailableAssets?: number; - selectedAssetName?: string; - selectedAssetSymbol?: string; - selectedAssetData?: string; - selectedAssetDecimals?: number; - baseCurrency?: string; -} -export enum TokenSelectorClosedVia { - ClickedX = 'Clicked X', // tslint:disable-line:enum-naming - TokenChose = 'Token Chose', -} -export const analytics = { - addUserProperties: (properties: AnalyticsUserOptions): void => { - evaluateIfEnabled(() => { - heapUtil.evaluateHeapCall(heap => heap.addUserProperties(properties)); - }); - }, - addEventProperties: (properties: AnalyticsEventOptions): void => { - evaluateIfEnabled(() => { - heapUtil.evaluateHeapCall(heap => heap.addEventProperties(properties)); - }); - }, - generateEventProperties: ( - network: Network, - orderSource: OrderSource, - providerState: ProviderState, - window: Window, - selectedAsset?: Asset, - affiliateInfo?: AffiliateInfo, - baseCurrency?: BaseCurrency, - ): AnalyticsEventOptions => { - const affiliateAddress = affiliateInfo ? affiliateInfo.feeRecipient : 'none'; - const affiliateFeePercent = affiliateInfo ? parseFloat(affiliateInfo.feePercentage.toFixed(4)) : 0; - const orderSourceName = typeof orderSource === 'string' ? orderSource : 'provided'; - const eventOptions: AnalyticsEventOptions = { - embeddedHost: window.location.host, - embeddedUrl: window.location.href, - networkId: network, - providerName: providerState.name, - providerDisplayName: providerState.displayName, - gitSha: GIT_SHA, - npmVersion: NPM_PACKAGE_VERSION, - orderSource: orderSourceName, - affiliateAddress, - affiliateFeePercent, - selectedAssetName: selectedAsset ? selectedAsset.metaData.name : 'none', - selectedAssetData: selectedAsset ? selectedAsset.assetData : 'none', - instantEnvironment: INSTANT_DISCHARGE_TARGET || `Local ${NODE_ENV}`, - baseCurrency, - }; - return eventOptions; - }, - trackInstantOpened: trackingEventFnWithoutPayload(EventNames.InstantOpened), - trackInstantClosed: trackingEventFnWithoutPayload(EventNames.InstantClosed), - trackAccountLocked: trackingEventFnWithoutPayload(EventNames.AccountLocked), - trackAccountReady: (address: string) => trackingEventFnWithPayload(EventNames.AccountReady)({ address }), - trackAccountUnlockRequested: trackingEventFnWithoutPayload(EventNames.AccountUnlockRequested), - trackAccountUnlockDenied: trackingEventFnWithoutPayload(EventNames.AccountUnlockDenied), - trackAccountAddressChanged: (address: string) => - trackingEventFnWithPayload(EventNames.AccountAddressChanged)({ address }), - trackBaseCurrencyChanged: (currencyChangedTo: BaseCurrency) => - trackingEventFnWithPayload(EventNames.BaseCurrencyChanged)({ currencyChangedTo }), - trackPaymentMethodDropdownOpened: trackingEventFnWithoutPayload(EventNames.PaymentMethodDropdownOpened), - trackPaymentMethodOpenedEtherscan: trackingEventFnWithoutPayload(EventNames.PaymentMethodOpenedEtherscan), - trackPaymentMethodCopiedAddress: trackingEventFnWithoutPayload(EventNames.PaymentMethodCopiedAddress), - trackBuyNotEnoughEth: (buyQuote: BuyQuote) => - trackingEventFnWithPayload(EventNames.BuyNotEnoughEth)(buyQuoteEventProperties(buyQuote)), - trackBuyStarted: (buyQuote: BuyQuote) => - trackingEventFnWithPayload(EventNames.BuyStarted)(buyQuoteEventProperties(buyQuote)), - trackBuySignatureDenied: (buyQuote: BuyQuote) => - trackingEventFnWithPayload(EventNames.BuySignatureDenied)(buyQuoteEventProperties(buyQuote)), - trackBuySimulationFailed: (buyQuote: BuyQuote) => - trackingEventFnWithPayload(EventNames.BuySimulationFailed)(buyQuoteEventProperties(buyQuote)), - trackBuyUnknownError: (buyQuote: BuyQuote, errorMessage: string) => - trackingEventFnWithPayload(EventNames.BuyUnknownError)({ - ...buyQuoteEventProperties(buyQuote), - errorMessage, - }), - trackBuyTxSubmitted: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => - trackingEventFnWithPayload(EventNames.BuyTxSubmitted)({ - ...buyQuoteEventProperties(buyQuote), - txHash, - expectedTxTimeMs: expectedEndTimeUnix - startTimeUnix, - }), - trackBuyTxSucceeded: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => - trackingEventFnWithPayload(EventNames.BuyTxSucceeded)({ - ...buyQuoteEventProperties(buyQuote), - txHash, - expectedTxTimeMs: expectedEndTimeUnix - startTimeUnix, - actualTxTimeMs: new Date().getTime() - startTimeUnix, - }), - trackBuyTxFailed: (buyQuote: BuyQuote, txHash: string, startTimeUnix: number, expectedEndTimeUnix: number) => - trackingEventFnWithPayload(EventNames.BuyTxFailed)({ - ...buyQuoteEventProperties(buyQuote), - txHash, - expectedTxTimeMs: expectedEndTimeUnix - startTimeUnix, - actualTxTimeMs: new Date().getTime() - startTimeUnix, - }), - trackInstallWalletClicked: (walletSuggestion: WalletSuggestion) => - trackingEventFnWithPayload(EventNames.InstallWalletClicked)({ walletSuggestion }), - trackInstallWalletModalClickedExplanation: trackingEventFnWithoutPayload( - EventNames.InstallWalletModalClickedExplanation, - ), - trackInstallWalletModalClickedGet: trackingEventFnWithoutPayload(EventNames.InstallWalletModalClickedGet), - trackInstallWalletModalOpened: trackingEventFnWithoutPayload(EventNames.InstallWalletModalOpened), - trackInstallWalletModalClosed: trackingEventFnWithoutPayload(EventNames.InstallWalletModalClosed), - trackTokenSelectorOpened: trackingEventFnWithoutPayload(EventNames.TokenSelectorOpened), - trackTokenSelectorClosed: (closedVia: TokenSelectorClosedVia) => - trackingEventFnWithPayload(EventNames.TokenSelectorClosed)({ closedVia }), - trackTokenSelectorChose: (payload: { assetName: string; assetData: string }) => - trackingEventFnWithPayload(EventNames.TokenSelectorChose)(payload), - trackTokenSelectorSearched: (searchText: string) => - trackingEventFnWithPayload(EventNames.TokenSelectorSearched)({ searchText }), - trackTransactionViewed: (orderProcesState: OrderProcessState) => - trackingEventFnWithPayload(EventNames.TransactionViewed)({ orderState: orderProcesState }), - trackQuoteFetched: (buyQuote: BuyQuote, fetchOrigin: QuoteFetchOrigin) => - trackingEventFnWithPayload(EventNames.QuoteFetched)({ - ...buyQuoteEventProperties(buyQuote), - fetchOrigin, - }), - trackQuoteError: (errorMessage: string, assetBuyAmount: BigNumber, fetchOrigin: QuoteFetchOrigin) => { - trackingEventFnWithPayload(EventNames.QuoteError)({ - errorMessage, - assetBuyAmount: assetBuyAmount.toString(), - fetchOrigin, - }); - }, - trackUsdPriceFailed: trackingEventFnWithoutPayload(EventNames.UsdPriceFetchFailed), -}; diff --git a/packages/instant/src/util/assert.ts b/packages/instant/src/util/assert.ts deleted file mode 100644 index 971c1eb96..000000000 --- a/packages/instant/src/util/assert.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { assert as sharedAssert } from '@0x/assert'; -import { schemas } from '@0x/json-schemas'; -import { assetDataUtils } from '@0x/order-utils'; -import { AssetProxyId, ObjectMap, SignedOrder } from '@0x/types'; -import * as _ from 'lodash'; - -import { AffiliateInfo, AssetMetaData } from '../types'; - -export const assert = { - ...sharedAssert, - isValidOrderSource(variableName: string, orderSource: string | SignedOrder[]): void { - if (_.isString(orderSource)) { - sharedAssert.isUri(variableName, orderSource); - return; - } - sharedAssert.doesConformToSchema(variableName, orderSource, schemas.signedOrdersSchema); - }, - areValidAssetDatas(variableName: string, assetDatas: string[]): void { - _.forEach(assetDatas, (assetData, index) => assert.isHexString(`${variableName}[${index}]`, assetData)); - }, - isValidAssetMetaDataMap(variableName: string, metaDataMap: ObjectMap): void { - _.forEach(metaDataMap, (metaData, assetData) => { - assert.isHexString(`key ${assetData} of ${variableName}`, assetData); - assert.isValidAssetMetaData(`${variableName}.${assetData}`, metaData); - const assetDataProxyId = assetDataUtils.decodeAssetProxyId(assetData); - assert.assert( - metaData.assetProxyId === assetDataProxyId, - `Expected meta data for assetData ${assetData} to have asset proxy id of ${assetDataProxyId}, but instead got ${ - metaData.assetProxyId - }`, - ); - }); - }, - isValidAssetMetaData(variableName: string, metaData: AssetMetaData): void { - assert.isHexString(`${variableName}.assetProxyId`, metaData.assetProxyId); - if (!_.isUndefined(metaData.primaryColor)) { - assert.isString(`${variableName}.primaryColor`, metaData.primaryColor); - } - if (metaData.assetProxyId === AssetProxyId.ERC20) { - assert.isNumber(`${variableName}.decimals`, metaData.decimals); - assert.isString(`${variableName}.symbol`, metaData.symbol); - } else if (metaData.assetProxyId === AssetProxyId.ERC721) { - assert.isString(`${variableName}.name`, metaData.name); - assert.isUri(`${variableName}.imageUrl`, metaData.imageUrl); - } - }, - isValidAffiliateInfo(variableName: string, affiliateInfo: AffiliateInfo): void { - assert.isETHAddressHex(`${variableName}.recipientAddress`, affiliateInfo.feeRecipient); - assert.isNumber(`${variableName}.percentage`, affiliateInfo.feePercentage); - assert.assert( - affiliateInfo.feePercentage >= 0 && affiliateInfo.feePercentage <= 0.05, - `Expected ${variableName}.percentage to be between 0 and 0.05, but is ${affiliateInfo.feePercentage}`, - ); - }, -}; diff --git a/packages/instant/src/util/asset.ts b/packages/instant/src/util/asset.ts deleted file mode 100644 index b5c97913d..000000000 --- a/packages/instant/src/util/asset.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { AssetBuyerError, InsufficientAssetLiquidityError } from '@0x/asset-buyer'; -import { AssetProxyId, ObjectMap } from '@0x/types'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; - -import { BIG_NUMBER_ZERO, DEFAULT_UNKOWN_ASSET_NAME } from '../constants'; -import { assetDataNetworkMapping } from '../data/asset_data_network_mapping'; -import { Asset, AssetMetaData, ERC20Asset, Network, ZeroExInstantError } from '../types'; - -export const assetUtils = { - createAssetsFromAssetDatas: ( - assetDatas: string[], - assetMetaDataMap: ObjectMap, - network: Network, - ): Asset[] => { - const arrayOfAssetOrUndefined = _.map(assetDatas, assetData => - assetUtils.createAssetFromAssetDataIfExists(assetData, assetMetaDataMap, network), - ); - return _.compact(arrayOfAssetOrUndefined); - }, - createAssetFromAssetDataIfExists: ( - assetData: string, - assetMetaDataMap: ObjectMap, - network: Network, - ): Asset | undefined => { - const metaData = assetUtils.getMetaDataIfExists(assetData, assetMetaDataMap, network); - if (_.isUndefined(metaData)) { - return; - } - return { - assetData: assetData.toLowerCase(), - metaData, - }; - }, - createAssetFromAssetDataOrThrow: ( - assetData: string, - assetMetaDataMap: ObjectMap, - network: Network, - ): Asset => { - return { - assetData: assetData.toLowerCase(), - metaData: assetUtils.getMetaDataOrThrow(assetData, assetMetaDataMap, network), - }; - }, - getMetaDataOrThrow: (assetData: string, metaDataMap: ObjectMap, network: Network): AssetMetaData => { - const metaDataIfExists = assetUtils.getMetaDataIfExists(assetData, metaDataMap, network); - if (_.isUndefined(metaDataIfExists)) { - throw new Error(ZeroExInstantError.AssetMetaDataNotAvailable); - } - return metaDataIfExists; - }, - getMetaDataIfExists: ( - assetData: string, - metaDataMap: ObjectMap, - network: Network, - ): AssetMetaData | undefined => { - let mainnetAssetData: string | undefined = assetData; - if (network !== Network.Mainnet) { - const mainnetAssetDataIfExists = assetUtils.getAssociatedAssetDataIfExists( - assetData.toLowerCase(), - network, - ); - // Just so we don't fail in the case where we are on a non-mainnet network, - // but pass in a valid mainnet assetData. - mainnetAssetData = mainnetAssetDataIfExists || assetData; - } - if (_.isUndefined(mainnetAssetData)) { - return; - } - const metaData = metaDataMap[mainnetAssetData.toLowerCase()]; - if (_.isUndefined(metaData)) { - return; - } - return metaData; - }, - bestNameForAsset: (asset?: Asset, defaultName: string = DEFAULT_UNKOWN_ASSET_NAME): string => { - if (_.isUndefined(asset)) { - return defaultName; - } - const metaData = asset.metaData; - switch (metaData.assetProxyId) { - case AssetProxyId.ERC20: - return metaData.symbol.toUpperCase(); - case AssetProxyId.ERC721: - return metaData.name; - } - }, - formattedSymbolForAsset: (asset?: ERC20Asset, defaultName: string = '???'): string => { - if (_.isUndefined(asset)) { - return defaultName; - } - const symbol = asset.metaData.symbol; - if (symbol.length <= 5) { - return symbol; - } - return `${symbol.slice(0, 3)}…`; - }, - getAssociatedAssetDataIfExists: (assetData: string, network: Network): string | undefined => { - const assetDataGroupIfExists = _.find(assetDataNetworkMapping, value => value[network] === assetData); - if (_.isUndefined(assetDataGroupIfExists)) { - return; - } - return assetDataGroupIfExists[Network.Mainnet]; - }, - getERC20AssetsFromAssets: (assets: Asset[]): ERC20Asset[] => { - const erc20sOrUndefined = _.map(assets, asset => - asset.metaData.assetProxyId === AssetProxyId.ERC20 ? (asset as ERC20Asset) : undefined, - ); - return _.compact(erc20sOrUndefined); - }, - assetBuyerErrorMessage: (asset: ERC20Asset, error: Error): string | undefined => { - if (error.message === AssetBuyerError.InsufficientAssetLiquidity) { - const assetName = assetUtils.bestNameForAsset(asset, 'of this asset'); - if ( - error instanceof InsufficientAssetLiquidityError && - error.amountAvailableToFill.isGreaterThan(BIG_NUMBER_ZERO) - ) { - const unitAmountAvailableToFill = Web3Wrapper.toUnitAmount( - error.amountAvailableToFill, - asset.metaData.decimals, - ); - const roundedUnitAmountAvailableToFill = unitAmountAvailableToFill.decimalPlaces( - 2, - BigNumber.ROUND_DOWN, - ); - - if (roundedUnitAmountAvailableToFill.isGreaterThan(BIG_NUMBER_ZERO)) { - return `There are only ${roundedUnitAmountAvailableToFill} ${assetName} available to buy`; - } - } - - return `Not enough ${assetName} available`; - } else if (error.message === AssetBuyerError.InsufficientZrxLiquidity) { - return 'Not enough ZRX available'; - } else if ( - error.message === AssetBuyerError.StandardRelayerApiError || - error.message.startsWith(AssetBuyerError.AssetUnavailable) - ) { - const assetName = assetUtils.bestNameForAsset(asset, 'This asset'); - return `${assetName} is currently unavailable`; - } - - return undefined; - }, -}; diff --git a/packages/instant/src/util/asset_buyer_factory.ts b/packages/instant/src/util/asset_buyer_factory.ts deleted file mode 100644 index 5ba46223c..000000000 --- a/packages/instant/src/util/asset_buyer_factory.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AssetBuyer, AssetBuyerOpts } from '@0x/asset-buyer'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { Network, OrderSource } from '../types'; - -export const assetBuyerFactory = { - getAssetBuyer: (provider: Provider, orderSource: OrderSource, network: Network): AssetBuyer => { - const assetBuyerOptions: Partial = { - networkId: network, - }; - const assetBuyer = _.isString(orderSource) - ? AssetBuyer.getAssetBuyerForStandardRelayerAPIUrl(provider, orderSource, assetBuyerOptions) - : AssetBuyer.getAssetBuyerForProvidedOrders(provider, orderSource, assetBuyerOptions); - return assetBuyer; - }, -}; diff --git a/packages/instant/src/util/buy_quote_updater.ts b/packages/instant/src/util/buy_quote_updater.ts deleted file mode 100644 index 37974e71c..000000000 --- a/packages/instant/src/util/buy_quote_updater.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { AssetBuyer, BuyQuote } from '@0x/asset-buyer'; -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; -import { Dispatch } from 'redux'; -import { oc } from 'ts-optchain'; - -import { SLIPPAGE_PERCENTAGE } from '../constants'; -import { Action, actions } from '../redux/actions'; -import { AffiliateInfo, ERC20Asset, QuoteFetchOrigin } from '../types'; -import { analytics } from '../util/analytics'; -import { assetUtils } from '../util/asset'; -import { errorFlasher } from '../util/error_flasher'; -import { errorReporter } from '../util/error_reporter'; - -export const buyQuoteUpdater = { - updateBuyQuoteAsync: async ( - assetBuyer: AssetBuyer, - dispatch: Dispatch, - asset: ERC20Asset, - assetUnitAmount: BigNumber, - fetchOrigin: QuoteFetchOrigin, - options: { - setPending: boolean; - dispatchErrors: boolean; - affiliateInfo?: AffiliateInfo; - }, - ): Promise => { - // get a new buy quote. - const baseUnitValue = Web3Wrapper.toBaseUnitAmount(assetUnitAmount, asset.metaData.decimals); - if (options.setPending) { - // mark quote as pending - dispatch(actions.setQuoteRequestStatePending()); - } - const feePercentage = oc(options.affiliateInfo).feePercentage(); - let newBuyQuote: BuyQuote | undefined; - const slippagePercentage = SLIPPAGE_PERCENTAGE; - try { - newBuyQuote = await assetBuyer.getBuyQuoteAsync(asset.assetData, baseUnitValue, { - feePercentage, - slippagePercentage, - }); - } catch (error) { - const errorMessage = assetUtils.assetBuyerErrorMessage(asset, error); - - errorReporter.report(error); - analytics.trackQuoteError(error.message ? error.message : 'other', baseUnitValue, fetchOrigin); - - if (options.dispatchErrors) { - dispatch(actions.setQuoteRequestStateFailure()); - errorFlasher.flashNewErrorMessage(dispatch, errorMessage || 'Error fetching price, please try again'); - } - return; - } - // We have a successful new buy quote - errorFlasher.clearError(dispatch); - // invalidate the last buy quote. - dispatch(actions.updateLatestBuyQuote(newBuyQuote)); - analytics.trackQuoteFetched(newBuyQuote, fetchOrigin); - }, -}; diff --git a/packages/instant/src/util/coinbase_api.ts b/packages/instant/src/util/coinbase_api.ts deleted file mode 100644 index faac8d82d..000000000 --- a/packages/instant/src/util/coinbase_api.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { BigNumber, fetchAsync } from '@0x/utils'; - -import { COINBASE_API_BASE_URL } from '../constants'; - -export const coinbaseApi = { - getEthUsdPrice: async (): Promise => { - const res = await fetchAsync(`${COINBASE_API_BASE_URL}/prices/ETH-USD/buy`); - const resJson = await res.json(); - return new BigNumber(resJson.data.amount); - }, -}; diff --git a/packages/instant/src/util/env.ts b/packages/instant/src/util/env.ts deleted file mode 100644 index 7d4f836ff..000000000 --- a/packages/instant/src/util/env.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as bowser from 'bowser'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { PROVIDER_TYPE_TO_NAME } from '../constants'; -import { Browser, OperatingSystem, ProviderType } from '../types'; - -export const envUtil = { - getBrowser(): Browser { - if (bowser.chrome) { - return Browser.Chrome; - } else if (bowser.firefox) { - return Browser.Firefox; - } else if (bowser.opera) { - return Browser.Opera; - } else if (bowser.msedge) { - return Browser.Edge; - } else if (bowser.safari) { - return Browser.Safari; - } else { - return Browser.Other; - } - }, - isMobileOperatingSystem(): boolean { - return bowser.mobile; - }, - getOperatingSystem(): OperatingSystem { - if (bowser.android) { - return OperatingSystem.Android; - } else if (bowser.ios) { - return OperatingSystem.iOS; - } else if (bowser.mac) { - return OperatingSystem.Mac; - } else if (bowser.windows) { - return OperatingSystem.Windows; - } else if (bowser.windowsphone) { - return OperatingSystem.WindowsPhone; - } else if (bowser.linux) { - return OperatingSystem.Linux; - } else { - return OperatingSystem.Other; - } - }, - getProviderType(provider: Provider): ProviderType | undefined { - const anyProvider = provider as any; - if (provider.constructor.name === 'EthereumProvider') { - return ProviderType.Mist; - } else if (anyProvider.isTrust) { - return ProviderType.TrustWallet; - } else if (anyProvider.isParity) { - return ProviderType.Parity; - } else if (anyProvider.isMetaMask) { - return ProviderType.MetaMask; - } else if (!_.isUndefined(_.get(window, 'SOFA'))) { - return ProviderType.CoinbaseWallet; - } else if (!_.isUndefined(_.get(window, '__CIPHER__'))) { - return ProviderType.Cipher; - } else if (envUtil.getBrowser() === Browser.Opera && !anyProvider.isMetaMask) { - return ProviderType.Opera; - } - return; - }, - getProviderName(provider: Provider): string { - const providerTypeIfExists = envUtil.getProviderType(provider); - if (_.isUndefined(providerTypeIfExists)) { - return provider.constructor.name; - } - return PROVIDER_TYPE_TO_NAME[providerTypeIfExists]; - }, - getProviderDisplayName(provider: Provider): string { - const providerTypeIfExists = envUtil.getProviderType(provider); - if (_.isUndefined(providerTypeIfExists)) { - return 'Wallet'; - } - return PROVIDER_TYPE_TO_NAME[providerTypeIfExists]; - }, -}; diff --git a/packages/instant/src/util/error_flasher.ts b/packages/instant/src/util/error_flasher.ts deleted file mode 100644 index 068c12fe2..000000000 --- a/packages/instant/src/util/error_flasher.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Dispatch } from 'redux'; - -import { Action, actions } from '../redux/actions'; - -class ErrorFlasher { - private _timeoutId?: number; - public flashNewErrorMessage(dispatch: Dispatch, errorMessage?: string, delayMs: number = 7000): void { - this._clearTimeout(); - // dispatch new message - dispatch(actions.setErrorMessage(errorMessage || 'Something went wrong...')); - this._timeoutId = window.setTimeout(() => { - dispatch(actions.hideError()); - }, delayMs); - } - public clearError(dispatch: Dispatch): void { - this._clearTimeout(); - dispatch(actions.hideError()); - } - private _clearTimeout(): void { - if (this._timeoutId) { - window.clearTimeout(this._timeoutId); - } - } -} - -export const errorFlasher = new ErrorFlasher(); diff --git a/packages/instant/src/util/error_reporter.ts b/packages/instant/src/util/error_reporter.ts deleted file mode 100644 index 8d7481684..000000000 --- a/packages/instant/src/util/error_reporter.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { logUtils } from '@0x/utils'; -import * as _ from 'lodash'; - -import { - GIT_SHA, - HOST_DOMAINS_EXTERNAL, - HOST_DOMAINS_LOCAL, - INSTANT_DISCHARGE_TARGET, - NODE_ENV, - ROLLBAR_CLIENT_TOKEN, - ROLLBAR_ENABLED, -} from '../constants'; - -// Import version of Rollbar designed for embedded components -// See https://docs.rollbar.com/docs/using-rollbarjs-inside-an-embedded-component -// tslint:disable-next-line:no-var-requires -const Rollbar = require('rollbar/dist/rollbar.noconflict.umd'); - -const getRollbarHostDomains = (): string[] => { - if (NODE_ENV === 'development') { - return HOST_DOMAINS_EXTERNAL.concat(HOST_DOMAINS_LOCAL); - } else { - return HOST_DOMAINS_EXTERNAL; - } -}; - -let rollbar: any; -// Configures rollbar and sets up error catching -export const setupRollbar = (): any => { - if (_.isUndefined(rollbar) && ROLLBAR_CLIENT_TOKEN && ROLLBAR_ENABLED) { - const hostDomains = getRollbarHostDomains(); - rollbar = new Rollbar({ - accessToken: ROLLBAR_CLIENT_TOKEN, - captureUncaught: true, - captureUnhandledRejections: true, - enabled: true, - itemsPerMinute: 10, - maxItems: 500, - payload: { - environment: INSTANT_DISCHARGE_TARGET || `Local ${NODE_ENV}`, - client: { - javascript: { - source_map_enabled: true, - code_version: GIT_SHA, - guess_uncaught_frames: true, - }, - }, - }, - hostWhiteList: hostDomains, - uncaughtErrorLevel: 'error', - ignoredMessages: [ - // Errors from the third-party scripts - 'Script error', - // Network errors or ad-blockers - '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')", - // Source: http://stackoverflow.com/questions/43399818/securityerror-from-facebook-and-cross-domain-messaging - 'SecurityError (DOM Exception 18)', - ], - }); - } -}; - -export const errorReporter = { - report(err: Error): void { - if (!rollbar) { - logUtils.log('Not reporting to rollbar because not configured', err); - return; - } - - rollbar.error(err, (rollbarErr: Error) => { - if (rollbarErr) { - logUtils.log(`Error reporting to rollbar, ignoring: ${rollbarErr}`); - } - }); - }, -}; diff --git a/packages/instant/src/util/etherscan.ts b/packages/instant/src/util/etherscan.ts deleted file mode 100644 index f9bf82827..000000000 --- a/packages/instant/src/util/etherscan.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as _ from 'lodash'; - -import { Network } from '../types'; - -const etherscanPrefix = (networkId: number): string | undefined => { - switch (networkId) { - case Network.Kovan: - return 'kovan.'; - case Network.Mainnet: - return ''; - } - return ''; -}; - -export const etherscanUtil = { - getEtherScanTxnAddressIfExists: (txHash: string, networkId: number) => { - const prefix = etherscanPrefix(networkId); - if (_.isUndefined(prefix)) { - return; - } - return `https://${prefix}etherscan.io/tx/${txHash}`; - }, - getEtherScanEthAddressIfExists: (ethAddress: string, networkId: number) => { - const prefix = etherscanPrefix(networkId); - if (_.isUndefined(prefix)) { - return; - } - return `https://${prefix}etherscan.io/address/${ethAddress}`; - }, -}; diff --git a/packages/instant/src/util/format.ts b/packages/instant/src/util/format.ts deleted file mode 100644 index 61aeb839f..000000000 --- a/packages/instant/src/util/format.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import * as _ from 'lodash'; - -import { BIG_NUMBER_ZERO, ETH_DECIMALS } from '../constants'; - -export const format = { - ethBaseUnitAmount: ( - ethBaseUnitAmount?: BigNumber, - decimalPlaces: number = 4, - defaultText: React.ReactNode = '0 ETH', - ): React.ReactNode => { - if (_.isUndefined(ethBaseUnitAmount)) { - return defaultText; - } - const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseUnitAmount, ETH_DECIMALS); - return format.ethUnitAmount(ethUnitAmount, decimalPlaces); - }, - ethUnitAmount: ( - ethUnitAmount?: BigNumber, - decimalPlaces: number = 4, - defaultText: React.ReactNode = '0 ETH', - minUnitAmountToDisplay: BigNumber = new BigNumber('0.00001'), - ): React.ReactNode => { - if (_.isUndefined(ethUnitAmount)) { - return defaultText; - } - let roundedAmount = ethUnitAmount.decimalPlaces(decimalPlaces).precision(decimalPlaces); - - if (roundedAmount.eq(BIG_NUMBER_ZERO) && ethUnitAmount.isGreaterThan(BIG_NUMBER_ZERO)) { - // Sometimes for small ETH amounts (i.e. 0.000045) the amount rounded to 4 decimalPlaces is 0 - // If that is the case, show to 1 significant digit - roundedAmount = new BigNumber(ethUnitAmount.toPrecision(1)); - } - - const displayAmount = - roundedAmount.isGreaterThan(BIG_NUMBER_ZERO) && roundedAmount.isLessThan(minUnitAmountToDisplay) - ? `< ${minUnitAmountToDisplay.toString()}` - : roundedAmount.toString(); - - return `${displayAmount} ETH`; - }, - ethBaseUnitAmountInUsd: ( - ethBaseUnitAmount?: BigNumber, - ethUsdPrice?: BigNumber, - decimalPlaces: number = 2, - defaultText: React.ReactNode = '$0.00', - minUnitAmountToDisplay: BigNumber = new BigNumber('0.00001'), - ): React.ReactNode => { - if (_.isUndefined(ethBaseUnitAmount) || _.isUndefined(ethUsdPrice)) { - return defaultText; - } - const ethUnitAmount = Web3Wrapper.toUnitAmount(ethBaseUnitAmount, ETH_DECIMALS); - return format.ethUnitAmountInUsd(ethUnitAmount, ethUsdPrice, decimalPlaces, minUnitAmountToDisplay); - }, - ethUnitAmountInUsd: ( - ethUnitAmount?: BigNumber, - ethUsdPrice?: BigNumber, - decimalPlaces: number = 2, - defaultText: React.ReactNode = '$0.00', - ): React.ReactNode => { - if (_.isUndefined(ethUnitAmount) || _.isUndefined(ethUsdPrice)) { - return defaultText; - } - const rawUsdPrice = ethUnitAmount.multipliedBy(ethUsdPrice); - const roundedUsdPrice = rawUsdPrice.toFixed(decimalPlaces); - if (roundedUsdPrice === '0.00' && rawUsdPrice.gt(BIG_NUMBER_ZERO)) { - return '<$0.01'; - } else { - return `$${roundedUsdPrice}`; - } - }, - ethAddress: (address: string): string => { - return `0x${address.slice(2, 7)}…${address.slice(-5)}`; - }, -}; diff --git a/packages/instant/src/util/gas_price_estimator.ts b/packages/instant/src/util/gas_price_estimator.ts deleted file mode 100644 index 9792b60ba..000000000 --- a/packages/instant/src/util/gas_price_estimator.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { BigNumber, fetchAsync } from '@0x/utils'; - -import { - DEFAULT_ESTIMATED_TRANSACTION_TIME_MS, - DEFAULT_GAS_PRICE, - ETH_GAS_STATION_API_BASE_URL, - GWEI_IN_WEI, -} from '../constants'; - -import { errorReporter } from './error_reporter'; - -interface EthGasStationResult { - average: number; - fastestWait: number; - fastWait: number; - fast: number; - safeLowWait: number; - blockNum: number; - avgWait: number; - block_time: number; - speed: number; - fastest: number; - safeLow: number; -} - -interface GasInfo { - gasPriceInWei: BigNumber; - estimatedTimeMs: number; -} - -const fetchFastAmountInWeiAsync = async (): Promise => { - const res = await fetchAsync(`${ETH_GAS_STATION_API_BASE_URL}/json/ethgasAPI.json`); - const gasInfo = (await res.json()) as EthGasStationResult; - // Eth Gas Station result is gwei * 10 - const gasPriceInGwei = new BigNumber(gasInfo.fast / 10); - // Time is in minutes - const estimatedTimeMs = gasInfo.fastWait * 60 * 1000; // Minutes to MS - return { gasPriceInWei: gasPriceInGwei.multipliedBy(GWEI_IN_WEI), estimatedTimeMs }; -}; - -export class GasPriceEstimator { - private _lastFetched?: GasInfo; - public async getGasInfoAsync(): Promise { - let fetchedAmount: GasInfo | undefined; - try { - fetchedAmount = await fetchFastAmountInWeiAsync(); - } catch (e) { - fetchedAmount = undefined; - errorReporter.report(e); - } - - if (fetchedAmount) { - this._lastFetched = fetchedAmount; - } - - return ( - fetchedAmount || - this._lastFetched || { - gasPriceInWei: DEFAULT_GAS_PRICE, - estimatedTimeMs: DEFAULT_ESTIMATED_TRANSACTION_TIME_MS, - } - ); - } -} -export const gasPriceEstimator = new GasPriceEstimator(); diff --git a/packages/instant/src/util/heap.ts b/packages/instant/src/util/heap.ts deleted file mode 100644 index 279ff3059..000000000 --- a/packages/instant/src/util/heap.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { ObjectMap } from '@0x/types'; -import { logUtils } from '@0x/utils'; -import * as _ from 'lodash'; - -import { HEAP_ANALYTICS_ID } from '../constants'; - -import { AnalyticsEventOptions, AnalyticsUserOptions } from './analytics'; -import { errorReporter } from './error_reporter'; - -export type EventProperties = ObjectMap; - -export interface HeapAnalytics { - loaded: boolean; - appid: string; - identify(id: string, idType: string): void; - track(eventName: string, eventProperties?: EventProperties): void; - resetIdentity(): void; - addUserProperties(properties: AnalyticsUserOptions): void; - addEventProperties(properties: AnalyticsEventOptions): void; - removeEventProperty(property: string): void; - clearEventProperties(): void; -} -interface ModifiedWindow { - heap?: HeapAnalytics; - zeroExInstantLoadedHeap?: boolean; -} -const getWindow = (): ModifiedWindow => { - return window as ModifiedWindow; -}; - -const setupZeroExInstantHeap = () => { - if (_.isUndefined(HEAP_ANALYTICS_ID)) { - return; - } - - const curWindow = getWindow(); - // Set property to specify that this is zeroEx's heap - curWindow.zeroExInstantLoadedHeap = true; - - // Typescript-compatible version of https://docs.heapanalytics.com/docs/installation - /* tslint:disable */ - ((window as any).heap = (window as any).heap || []), - ((window as any).heap.load = function(e: any, t: any) { - ((window as any).heap.appid = e), ((window as any).heap.config = t = t || {}); - var r = t.forceSSL || 'https:' === (document.location as Location).protocol, - a = document.createElement('script'); - (a.type = 'text/javascript'), - (a.async = !0), - (a.src = (r ? 'https:' : 'http:') + '//cdn.heapanalytics.com/js/heap-' + e + '.js'); - var n = document.getElementsByTagName('script')[0]; - (n.parentNode as Node).insertBefore(a, n); - for ( - var o = function(e: any) { - return function() { - (window as any).heap.push([e].concat(Array.prototype.slice.call(arguments, 0))); - }; - }, - p = [ - 'addEventProperties', - 'addUserProperties', - 'clearEventProperties', - 'identify', - 'resetIdentity', - 'removeEventProperty', - 'setEventProperties', - 'track', - 'unsetEventProperty', - ], - c = 0; - c < p.length; - c++ - ) - (window as any).heap[p[c]] = o(p[c]); - }); - (window as any).heap.load(HEAP_ANALYTICS_ID); - /* tslint:enable */ - - return curWindow.heap as HeapAnalytics; -}; - -export const heapUtil = { - getHeap: (): HeapAnalytics | undefined => { - const curWindow = getWindow(); - const hasOtherExistingHeapIntegration = curWindow.heap && !curWindow.zeroExInstantLoadedHeap; - if (hasOtherExistingHeapIntegration) { - return undefined; - } - - const zeroExInstantHeapIntegration = curWindow.zeroExInstantLoadedHeap && curWindow.heap; - if (zeroExInstantHeapIntegration) { - return zeroExInstantHeapIntegration; - } - - return setupZeroExInstantHeap(); - }, - evaluateHeapCall: (heapFunctionCall: (heap: HeapAnalytics) => void): void => { - if (_.isUndefined(HEAP_ANALYTICS_ID)) { - return; - } - - const curHeap = heapUtil.getHeap(); - if (curHeap) { - try { - if (curHeap.appid !== HEAP_ANALYTICS_ID) { - // Integrator has included heap after us and reset the app id - return; - } - heapFunctionCall(curHeap); - } catch (e) { - // We never want analytics to crash our React component - logUtils.log('Analytics error', e); - errorReporter.report(e); - } - } - }, -}; diff --git a/packages/instant/src/util/heartbeater.ts b/packages/instant/src/util/heartbeater.ts deleted file mode 100644 index e700d489e..000000000 --- a/packages/instant/src/util/heartbeater.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { intervalUtils } from '@0x/utils'; -import * as _ from 'lodash'; - -type HeartbeatableFunction = () => Promise; -export class Heartbeater { - private _intervalId?: NodeJS.Timer; - private readonly _performImmediatelyOnStart: boolean; - private readonly _performFunction: HeartbeatableFunction; - - public constructor(performingFunctionAsync: HeartbeatableFunction, performImmediatelyOnStart: boolean) { - this._performFunction = performingFunctionAsync; - this._performImmediatelyOnStart = performImmediatelyOnStart; - } - - public start(intervalTimeMs: number): void { - if (!_.isUndefined(this._intervalId)) { - throw new Error('Heartbeat is running, please stop before restarting'); - } - - if (this._performImmediatelyOnStart) { - // tslint:disable-next-line:no-floating-promises - this._performFunction(); - } - - // tslint:disable-next-line:no-unbound-method - this._intervalId = intervalUtils.setAsyncExcludingInterval(this._performFunction, intervalTimeMs, _.noop); - } - - public stop(): void { - if (this._intervalId) { - intervalUtils.clearInterval(this._intervalId); - } - this._intervalId = undefined; - } -} diff --git a/packages/instant/src/util/heartbeater_factory.ts b/packages/instant/src/util/heartbeater_factory.ts deleted file mode 100644 index cf29bf3ea..000000000 --- a/packages/instant/src/util/heartbeater_factory.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { asyncData } from '../redux/async_data'; -import { Store } from '../redux/store'; -import { QuoteFetchOrigin } from '../types'; - -import { Heartbeater } from './heartbeater'; - -export interface HeartbeatFactoryOptions { - store: Store; - shouldPerformImmediatelyOnStart: boolean; -} -export const generateAccountHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => { - const { store, shouldPerformImmediatelyOnStart } = options; - return new Heartbeater(async () => { - await asyncData.fetchAccountInfoAndDispatchToStore(store.getState().providerState, store.dispatch, false); - }, shouldPerformImmediatelyOnStart); -}; - -export const generateBuyQuoteHeartbeater = (options: HeartbeatFactoryOptions): Heartbeater => { - const { store, shouldPerformImmediatelyOnStart } = options; - return new Heartbeater(async () => { - await asyncData.fetchCurrentBuyQuoteAndDispatchToStore( - store.getState(), - store.dispatch, - QuoteFetchOrigin.Heartbeat, - { - updateSilently: true, - }, - ); - }, shouldPerformImmediatelyOnStart); -}; diff --git a/packages/instant/src/util/maybe_big_number.ts b/packages/instant/src/util/maybe_big_number.ts deleted file mode 100644 index f48473389..000000000 --- a/packages/instant/src/util/maybe_big_number.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import * as _ from 'lodash'; - -import { Maybe } from '../types'; - -export const maybeBigNumberUtil = { - // converts a string to a Maybe - // if string is a NaN, considered undefined - stringToMaybeBigNumber: (stringValue: string): Maybe => { - let validBigNumber: BigNumber; - try { - validBigNumber = new BigNumber(stringValue); - } catch { - return undefined; - } - - return validBigNumber.isNaN() ? undefined : validBigNumber; - }, - areMaybeBigNumbersEqual: (val1: Maybe, val2: Maybe): boolean => { - if (!_.isUndefined(val1) && !_.isUndefined(val2)) { - return val1.isEqualTo(val2); - } - return _.isUndefined(val1) && _.isUndefined(val2); - }, -}; diff --git a/packages/instant/src/util/provider_factory.ts b/packages/instant/src/util/provider_factory.ts deleted file mode 100644 index 603f7674d..000000000 --- a/packages/instant/src/util/provider_factory.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { EmptyWalletSubprovider, RPCSubprovider, Web3ProviderEngine } from '@0x/subproviders'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { BLOCK_POLLING_INTERVAL_MS, ETHEREUM_NODE_URL_BY_NETWORK } from '../constants'; -import { Maybe, Network } from '../types'; - -export const providerFactory = { - getInjectedProviderIfExists: (): Maybe => { - const injectedProviderIfExists = (window as any).ethereum; - if (!_.isUndefined(injectedProviderIfExists)) { - return injectedProviderIfExists; - } - const injectedWeb3IfExists = (window as any).web3; - if (!_.isUndefined(injectedWeb3IfExists) && !_.isUndefined(injectedWeb3IfExists.currentProvider)) { - return injectedWeb3IfExists.currentProvider; - } - return undefined; - }, - getFallbackNoSigningProvider: (network: Network): Provider => { - const providerEngine = new Web3ProviderEngine({ - pollingInterval: BLOCK_POLLING_INTERVAL_MS, - }); - // Intercept calls to `eth_accounts` and always return empty - providerEngine.addProvider(new EmptyWalletSubprovider()); - // Construct an RPC subprovider, all data based requests will be sent via the RPCSubprovider - // TODO(bmillman): make this more resilient to infura failures - const rpcUrl = ETHEREUM_NODE_URL_BY_NETWORK[network]; - providerEngine.addProvider(new RPCSubprovider(rpcUrl)); - // // Start the Provider Engine - providerEngine.start(); - return providerEngine; - }, -}; diff --git a/packages/instant/src/util/provider_state_factory.ts b/packages/instant/src/util/provider_state_factory.ts deleted file mode 100644 index bd2d6dad5..000000000 --- a/packages/instant/src/util/provider_state_factory.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { Provider } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { LOADING_ACCOUNT, NO_ACCOUNT } from '../constants'; -import { Maybe, Network, OrderSource, ProviderState } from '../types'; -import { envUtil } from '../util/env'; - -import { assetBuyerFactory } from './asset_buyer_factory'; -import { providerFactory } from './provider_factory'; - -export const providerStateFactory = { - getInitialProviderState: ( - orderSource: OrderSource, - network: Network, - provider?: Provider, - walletDisplayName?: string, - ): ProviderState => { - if (!_.isUndefined(provider)) { - return providerStateFactory.getInitialProviderStateFromProvider( - orderSource, - network, - provider, - walletDisplayName, - ); - } - const providerStateFromWindowIfExits = providerStateFactory.getInitialProviderStateFromWindowIfExists( - orderSource, - network, - walletDisplayName, - ); - if (providerStateFromWindowIfExits) { - return providerStateFromWindowIfExits; - } else { - return providerStateFactory.getInitialProviderStateFallback(orderSource, network, walletDisplayName); - } - }, - getInitialProviderStateFromProvider: ( - orderSource: OrderSource, - network: Network, - provider: Provider, - walletDisplayName?: string, - ): ProviderState => { - const providerState: ProviderState = { - name: envUtil.getProviderName(provider), - displayName: walletDisplayName || envUtil.getProviderDisplayName(provider), - provider, - web3Wrapper: new Web3Wrapper(provider), - assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network), - account: LOADING_ACCOUNT, - }; - return providerState; - }, - getInitialProviderStateFromWindowIfExists: ( - orderSource: OrderSource, - network: Network, - walletDisplayName?: string, - ): Maybe => { - const injectedProviderIfExists = providerFactory.getInjectedProviderIfExists(); - if (!_.isUndefined(injectedProviderIfExists)) { - const providerState: ProviderState = { - name: envUtil.getProviderName(injectedProviderIfExists), - displayName: walletDisplayName || envUtil.getProviderDisplayName(injectedProviderIfExists), - provider: injectedProviderIfExists, - web3Wrapper: new Web3Wrapper(injectedProviderIfExists), - assetBuyer: assetBuyerFactory.getAssetBuyer(injectedProviderIfExists, orderSource, network), - account: LOADING_ACCOUNT, - }; - return providerState; - } else { - return undefined; - } - }, - getInitialProviderStateFallback: ( - orderSource: OrderSource, - network: Network, - walletDisplayName?: string, - ): ProviderState => { - const provider = providerFactory.getFallbackNoSigningProvider(network); - const providerState: ProviderState = { - name: 'Fallback', - displayName: walletDisplayName || envUtil.getProviderDisplayName(provider), - provider, - web3Wrapper: new Web3Wrapper(provider), - assetBuyer: assetBuyerFactory.getAssetBuyer(provider, orderSource, network), - account: NO_ACCOUNT, - }; - return providerState; - }, -}; diff --git a/packages/instant/src/util/time.ts b/packages/instant/src/util/time.ts deleted file mode 100644 index bfe69cad5..000000000 --- a/packages/instant/src/util/time.ts +++ /dev/null @@ -1,39 +0,0 @@ -const secondsToMinutesAndRemainingSeconds = (seconds: number): { minutes: number; remainingSeconds: number } => { - const minutes = Math.floor(seconds / 60); - const remainingSeconds = seconds - minutes * 60; - - return { - minutes, - remainingSeconds, - }; -}; - -const padZero = (aNumber: number): string => { - return aNumber < 10 ? `0${aNumber}` : aNumber.toString(); -}; - -export const timeUtil = { - // converts seconds to human readable version of seconds or minutes - secondsToHumanDescription: (seconds: number): string => { - const { minutes, remainingSeconds } = secondsToMinutesAndRemainingSeconds(seconds); - - if (minutes === 0) { - const suffix = seconds > 1 ? 's' : ''; - return `${seconds} second${suffix}`; - } - - const minuteSuffix = minutes > 1 ? 's' : ''; - const minuteText = `${minutes} minute${minuteSuffix}`; - - const secondsSuffix = remainingSeconds > 1 ? 's' : ''; - const secondsText = remainingSeconds === 0 ? '' : ` ${remainingSeconds} second${secondsSuffix}`; - - return `${minuteText}${secondsText}`; - }, - // converts seconds to stopwatch time (i.e. 05:30 and 00:30) - // only goes up to minutes, not hours - secondsToStopwatchTime: (seconds: number): string => { - const { minutes, remainingSeconds } = secondsToMinutesAndRemainingSeconds(seconds); - return `${padZero(minutes)}:${padZero(remainingSeconds)}`; - }, -}; diff --git a/packages/instant/src/util/util.ts b/packages/instant/src/util/util.ts deleted file mode 100644 index 29b6b1d2b..000000000 --- a/packages/instant/src/util/util.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as _ from 'lodash'; - -export const util = { - boundNoop: _.noop.bind(_), - createOpenUrlInNewWindow: (href: string) => () => window.open(href, '_blank'), -}; diff --git a/packages/instant/test/components/zero_ex_instant.test.tsx b/packages/instant/test/components/zero_ex_instant.test.tsx deleted file mode 100644 index e373bb002..000000000 --- a/packages/instant/test/components/zero_ex_instant.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { configure, shallow } from 'enzyme'; -import * as Adapter from 'enzyme-adapter-react-16'; -import * as React from 'react'; - -configure({ adapter: new Adapter() }); - -// TODO: Write non-trivial tests. -// At time of writing we cannot render ZeroExInstant -// because we are looking for a provider on window. -// But in the future it will be dependency injected. -describe('', () => { - it('runs a test', () => { - shallow(
); - }); -}); diff --git a/packages/instant/test/util/asset.test.ts b/packages/instant/test/util/asset.test.ts deleted file mode 100644 index 402a556d5..000000000 --- a/packages/instant/test/util/asset.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { AssetBuyerError, BigNumber, InsufficientAssetLiquidityError } from '@0x/asset-buyer'; -import { AssetProxyId, ObjectMap } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; - -import { Asset, AssetMetaData, ERC20Asset, ERC20AssetMetaData, Network, ZeroExInstantError } from '../../src/types'; -import { assetUtils } from '../../src/util/asset'; - -const ZRX_ASSET_DATA = '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498'; -const ZRX_ASSET_DATA_KOVAN = '0xf47261b00000000000000000000000002002d3812f58e35f0ea1ffbf80a75a38c32175fa'; -const ZRX_META_DATA: ERC20AssetMetaData = { - assetProxyId: AssetProxyId.ERC20, - symbol: 'zrx', - decimals: 18, - name: '0x', -}; -const ZRX_ASSET: ERC20Asset = { - assetData: ZRX_ASSET_DATA, - metaData: ZRX_META_DATA, -}; -const META_DATA_MAP: ObjectMap = { - [ZRX_ASSET_DATA]: ZRX_META_DATA, -}; -const WAX_ASSET: ERC20Asset = { - assetData: '0xf47261b000000000000000000000000039bb259f66e1c59d5abef88375979b4d20d98022', - metaData: { - assetProxyId: AssetProxyId.ERC20, - decimals: 8, - primaryColor: '#EDB740', - symbol: 'wax', - name: 'WAX', - }, -}; - -describe('assetDataUtil', () => { - describe('bestNameForAsset', () => { - it('should return default string if assetData is undefined', () => { - expect(assetUtils.bestNameForAsset(undefined, 'xyz')).toEqual('xyz'); - }); - it('should return ZRX for ZRX assetData', () => { - expect(assetUtils.bestNameForAsset(ZRX_ASSET, 'mah default')).toEqual('ZRX'); - }); - }); - describe('getMetaDataOrThrow', () => { - it('should return the metaData for the supplied mainnet asset data', () => { - expect(assetUtils.getMetaDataOrThrow(ZRX_ASSET_DATA, META_DATA_MAP, Network.Mainnet)).toEqual( - ZRX_META_DATA, - ); - }); - it('should return the metaData for the supplied non-mainnet asset data', () => { - expect(assetUtils.getMetaDataOrThrow(ZRX_ASSET_DATA_KOVAN, META_DATA_MAP, Network.Kovan)).toEqual( - ZRX_META_DATA, - ); - }); - it('should throw if the metaData for the asset is not available', () => { - expect(() => - assetUtils.getMetaDataOrThrow('asset data we dont have', META_DATA_MAP, Network.Mainnet), - ).toThrowError(ZeroExInstantError.AssetMetaDataNotAvailable); - }); - }); - describe('assetBuyerErrorMessage', () => { - it('should return message for generic InsufficientAssetLiquidity error', () => { - const insufficientAssetError = new Error(AssetBuyerError.InsufficientAssetLiquidity); - expect(assetUtils.assetBuyerErrorMessage(ZRX_ASSET, insufficientAssetError)).toEqual( - 'Not enough ZRX available', - ); - }); - describe('InsufficientAssetLiquidityError', () => { - it('should return custom message for token w/ 18 decimals', () => { - const amountAvailable = Web3Wrapper.toBaseUnitAmount(new BigNumber(20.059), 18); - expect( - assetUtils.assetBuyerErrorMessage(ZRX_ASSET, new InsufficientAssetLiquidityError(amountAvailable)), - ).toEqual('There are only 20.05 ZRX available to buy'); - }); - it('should return custom message for token w/ 18 decimals and small amount available', () => { - const amountAvailable = Web3Wrapper.toBaseUnitAmount(new BigNumber(0.01), 18); - expect( - assetUtils.assetBuyerErrorMessage(ZRX_ASSET, new InsufficientAssetLiquidityError(amountAvailable)), - ).toEqual('There are only 0.01 ZRX available to buy'); - }); - it('should return custom message for token w/ 8 decimals', () => { - const amountAvailable = Web3Wrapper.toBaseUnitAmount(new BigNumber(3), 8); - expect( - assetUtils.assetBuyerErrorMessage(WAX_ASSET, new InsufficientAssetLiquidityError(amountAvailable)), - ).toEqual('There are only 3 WAX available to buy'); - }); - it('should return generic message when amount available rounds to zero', () => { - const amountAvailable = Web3Wrapper.toBaseUnitAmount(new BigNumber(0.002), 18); - expect( - assetUtils.assetBuyerErrorMessage(ZRX_ASSET, new InsufficientAssetLiquidityError(amountAvailable)), - ).toEqual('Not enough ZRX available'); - }); - }); - it('should return message for InsufficientZrxLiquidity', () => { - const insufficientZrxError = new Error(AssetBuyerError.InsufficientZrxLiquidity); - expect(assetUtils.assetBuyerErrorMessage(ZRX_ASSET, insufficientZrxError)).toEqual( - 'Not enough ZRX available', - ); - }); - it('should message for StandardRelayerApiError', () => { - const standardRelayerError = new Error(AssetBuyerError.StandardRelayerApiError); - expect(assetUtils.assetBuyerErrorMessage(ZRX_ASSET, standardRelayerError)).toEqual( - 'ZRX is currently unavailable', - ); - }); - it('should return error for AssetUnavailable error', () => { - const assetUnavailableError = new Error( - `${AssetBuyerError.AssetUnavailable}: For assetData ${ZRX_ASSET_DATA}`, - ); - expect(assetUtils.assetBuyerErrorMessage(ZRX_ASSET, assetUnavailableError)).toEqual( - 'ZRX is currently unavailable', - ); - }); - }); -}); diff --git a/packages/instant/test/util/format.test.ts b/packages/instant/test/util/format.test.ts deleted file mode 100644 index 38bf356ec..000000000 --- a/packages/instant/test/util/format.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { BigNumber } from '@0x/utils'; -import { Web3Wrapper } from '@0x/web3-wrapper'; - -import { ETH_DECIMALS } from '../../src/constants'; -import { format } from '../../src/util/format'; - -const BIG_NUMBER_ONE = new BigNumber(1); -const BIG_NUMBER_DECIMAL = new BigNumber(0.432414); -const BIG_NUMBER_IRRATIONAL = new BigNumber(5.3014059295032); -const ONE_ETH_IN_BASE_UNITS = Web3Wrapper.toBaseUnitAmount(BIG_NUMBER_ONE, ETH_DECIMALS); -const DECIMAL_ETH_IN_BASE_UNITS = Web3Wrapper.toBaseUnitAmount(BIG_NUMBER_DECIMAL, ETH_DECIMALS); -const IRRATIONAL_ETH_IN_BASE_UNITS = Web3Wrapper.toBaseUnitAmount(BIG_NUMBER_IRRATIONAL, ETH_DECIMALS); -const BIG_NUMBER_FAKE_ETH_USD_PRICE = new BigNumber(2.534); - -describe('format', () => { - describe('ethBaseAmount', () => { - it('converts 1 ETH in base units to the string `1 ETH`', () => { - expect(format.ethBaseUnitAmount(ONE_ETH_IN_BASE_UNITS)).toBe('1 ETH'); - }); - it('converts .432414 ETH in base units to the string `.4324 ETH`', () => { - expect(format.ethBaseUnitAmount(DECIMAL_ETH_IN_BASE_UNITS)).toBe('0.4324 ETH'); - }); - it('converts 5.3014059295032 ETH in base units to the string `5.301 ETH`', () => { - expect(format.ethBaseUnitAmount(IRRATIONAL_ETH_IN_BASE_UNITS)).toBe('5.301 ETH'); - }); - it('returns defaultText param when ethBaseAmount is not defined', () => { - const defaultText = 'defaultText'; - expect(format.ethBaseUnitAmount(undefined, 4, defaultText)).toBe(defaultText); - }); - it('it allows for configurable decimal places', () => { - expect(format.ethBaseUnitAmount(DECIMAL_ETH_IN_BASE_UNITS, 2)).toBe('0.43 ETH'); - }); - }); - describe('ethUnitAmount', () => { - it('converts BigNumber(1) to the string `1 ETH`', () => { - expect(format.ethUnitAmount(BIG_NUMBER_ONE)).toBe('1 ETH'); - }); - it('converts BigNumer(.432414) to the string `.4324 ETH`', () => { - expect(format.ethUnitAmount(BIG_NUMBER_DECIMAL)).toBe('0.4324 ETH'); - }); - it('converts BigNumber(5.3014059295032) to the string `5.301 ETH`', () => { - expect(format.ethUnitAmount(BIG_NUMBER_IRRATIONAL)).toBe('5.301 ETH'); - }); - it('shows 1 significant digit when rounded amount would be 0', () => { - expect(format.ethUnitAmount(new BigNumber(0.00003))).toBe('0.00003 ETH'); - expect(format.ethUnitAmount(new BigNumber(0.000034))).toBe('0.00003 ETH'); - expect(format.ethUnitAmount(new BigNumber(0.000035))).toBe('0.00004 ETH'); - }); - it('shows < 0.00001 when hits threshold', () => { - expect(format.ethUnitAmount(new BigNumber(0.000011))).toBe('0.00001 ETH'); - expect(format.ethUnitAmount(new BigNumber(0.00001))).toBe('0.00001 ETH'); - expect(format.ethUnitAmount(new BigNumber(0.000009))).toBe('< 0.00001 ETH'); - expect(format.ethUnitAmount(new BigNumber(0.0000000009))).toBe('< 0.00001 ETH'); - expect(format.ethUnitAmount(new BigNumber(0))).toBe('0 ETH'); - }); - it('returns defaultText param when ethUnitAmount is not defined', () => { - const defaultText = 'defaultText'; - expect(format.ethUnitAmount(undefined, 4, defaultText)).toBe(defaultText); - expect(format.ethUnitAmount(BIG_NUMBER_ONE, 4, defaultText)).toBe('1 ETH'); - }); - it('it allows for configurable decimal places', () => { - expect(format.ethUnitAmount(BIG_NUMBER_DECIMAL, 2)).toBe('0.43 ETH'); - }); - }); - describe('ethBaseAmountInUsd', () => { - it('correctly formats 1 ETH to usd according to some price', () => { - expect(format.ethBaseUnitAmountInUsd(ONE_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$2.53'); - }); - it('correctly formats .432414 ETH to usd according to some price', () => { - expect(format.ethBaseUnitAmountInUsd(DECIMAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe( - '$1.10', - ); - }); - it('correctly formats 5.3014059295032 ETH to usd according to some price', () => { - expect(format.ethBaseUnitAmountInUsd(IRRATIONAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe( - '$13.43', - ); - }); - it('returns defaultText param when ethBaseAmountInUsd or ethUsdPrice is not defined', () => { - const defaultText = 'defaultText'; - expect(format.ethBaseUnitAmountInUsd(undefined, undefined, 2, defaultText)).toBe(defaultText); - expect(format.ethBaseUnitAmountInUsd(BIG_NUMBER_ONE, undefined, 2, defaultText)).toBe(defaultText); - expect(format.ethBaseUnitAmountInUsd(undefined, BIG_NUMBER_ONE, 2, defaultText)).toBe(defaultText); - }); - it('it allows for configurable decimal places', () => { - expect(format.ethBaseUnitAmountInUsd(DECIMAL_ETH_IN_BASE_UNITS, BIG_NUMBER_FAKE_ETH_USD_PRICE, 4)).toBe( - '$1.0957', - ); - }); - }); - describe('ethUnitAmountInUsd', () => { - it('correctly formats 1 ETH to usd according to some price', () => { - expect(format.ethUnitAmountInUsd(BIG_NUMBER_ONE, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$2.53'); - }); - it('correctly formats .432414 ETH to usd according to some price', () => { - expect(format.ethUnitAmountInUsd(BIG_NUMBER_DECIMAL, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$1.10'); - }); - it('correctly formats 5.3014059295032 ETH to usd according to some price', () => { - expect(format.ethUnitAmountInUsd(BIG_NUMBER_IRRATIONAL, BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$13.43'); - }); - it('correctly formats amount that is less than 1 cent', () => { - expect(format.ethUnitAmountInUsd(new BigNumber(0.000001), BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('<$0.01'); - }); - it('correctly formats exactly 1 cent', () => { - expect(format.ethUnitAmountInUsd(new BigNumber(0.0039), BIG_NUMBER_FAKE_ETH_USD_PRICE)).toBe('$0.01'); - }); - it('returns defaultText param when ethUnitAmountInUsd or ethUsdPrice is not defined', () => { - const defaultText = 'defaultText'; - expect(format.ethUnitAmountInUsd(undefined, undefined, 2, defaultText)).toBe(defaultText); - expect(format.ethUnitAmountInUsd(BIG_NUMBER_ONE, undefined, 2, defaultText)).toBe(defaultText); - expect(format.ethUnitAmountInUsd(undefined, BIG_NUMBER_ONE, 2, defaultText)).toBe(defaultText); - }); - it('it allows for configurable decimal places', () => { - expect(format.ethUnitAmountInUsd(BIG_NUMBER_DECIMAL, BIG_NUMBER_FAKE_ETH_USD_PRICE, 4)).toBe('$1.0957'); - }); - }); -}); diff --git a/packages/instant/test/util/time.test.ts b/packages/instant/test/util/time.test.ts deleted file mode 100644 index fcb4e1875..000000000 --- a/packages/instant/test/util/time.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { timeUtil } from '../../src/util/time'; - -describe('timeUtil', () => { - describe('secondsToHumanDescription', () => { - const numsToResults: { - [aNumber: number]: string; - } = { - 1: '1 second', - 59: '59 seconds', - 60: '1 minute', - 119: '1 minute 59 seconds', - 120: '2 minutes', - 121: '2 minutes 1 second', - 122: '2 minutes 2 seconds', - }; - - const nums = Object.keys(numsToResults); - nums.forEach(aNum => { - const numInt = parseInt(aNum, 10); - it(`should work for ${aNum} seconds`, () => { - const expectedResult = numsToResults[numInt]; - expect(timeUtil.secondsToHumanDescription(numInt)).toEqual(expectedResult); - }); - }); - }); - describe('secondsToStopwatchTime', () => { - const numsToResults: { - [aNumber: number]: string; - } = { - 1: '00:01', - 59: '00:59', - 60: '01:00', - 119: '01:59', - 120: '02:00', - 121: '02:01', - 2701: '45:01', - }; - - const nums = Object.keys(numsToResults); - nums.forEach(aNum => { - const numInt = parseInt(aNum, 10); - it(`should work for ${aNum} seconds`, () => { - const expectedResult = numsToResults[numInt]; - expect(timeUtil.secondsToStopwatchTime(numInt)).toEqual(expectedResult); - }); - }); - }); -}); diff --git a/packages/instant/tsconfig.json b/packages/instant/tsconfig.json deleted file mode 100644 index 2b3c11c9f..000000000 --- a/packages/instant/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../tsconfig", - "compilerOptions": { - "outDir": "lib", - "rootDir": "src", - "jsx": "react", - "noImplicitAny": true, - "allowSyntheticDefaultImports": true, - "declaration": false, - "declarationMap": false, - "composite": false - }, - "include": ["./src/**/*"] -} diff --git a/packages/instant/tslint.json b/packages/instant/tslint.json deleted file mode 100644 index d43ee8da7..000000000 --- a/packages/instant/tslint.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": ["@0x/tslint-config"], - "rules": { - "custom-no-magic-numbers": false, - "semicolon": [true, "always", "ignore-bound-class-methods"], - "max-classes-per-file": false, - "switch-default": false - } -} diff --git a/packages/instant/typedoc-tsconfig.json b/packages/instant/typedoc-tsconfig.json deleted file mode 100644 index c9b0af1ae..000000000 --- a/packages/instant/typedoc-tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../typedoc-tsconfig", - "compilerOptions": { - "outDir": "lib" - }, - "include": ["./src/**/*", "./test/**/*"] -} diff --git a/packages/instant/webpack.config.js b/packages/instant/webpack.config.js deleted file mode 100644 index e74cf36d9..000000000 --- a/packages/instant/webpack.config.js +++ /dev/null @@ -1,176 +0,0 @@ -const childProcess = require('child_process'); -const ip = require('ip'); -const path = require('path'); -const RollbarSourceMapPlugin = require('rollbar-sourcemap-webpack-plugin'); -const webpack = require('webpack'); - -const GIT_SHA = childProcess - .execSync('git rev-parse HEAD') - .toString() - .trim(); - -const DISCHARGE_TARGETS_THAT_REQUIRED_HEAP = ['production', 'staging', 'dogfood']; -const getHeapConfigForDischargeTarget = dischargeTarget => { - return { - heapAnalyticsIdEnvName: - dischargeTarget === 'production' - ? 'INSTANT_HEAP_ANALYTICS_ID_PRODUCTION' - : 'INSTANT_HEAP_ANALYTICS_ID_DEVELOPMENT', - heapAnalyticsIdRequired: DISCHARGE_TARGETS_THAT_REQUIRED_HEAP.includes(dischargeTarget), - }; -}; - -const DISCHARGE_TARGETS_THAT_REQUIRE_ROLLBAR = ['production', 'staging', 'dogfood']; -const getRollbarConfigForDischargeTarget = dischargeTarget => { - if (DISCHARGE_TARGETS_THAT_REQUIRE_ROLLBAR.includes(dischargeTarget)) { - const rollbarSourceMapPublicPath = - dischargeTarget === 'production' - ? 'https://instant.0xproject.com' - : `http://0x-instant-${dischargeTarget}.s3-website-us-east-1.amazonaws.com`; - - return { - rollbarSourceMapPublicPath, - rollbarRequired: true, - }; - } - - return { - rollbarRequired: false, - }; -}; - -const ROLLBAR_CLIENT_TOKEN_ENV_VAR_NAME = 'INSTANT_ROLLBAR_CLIENT_TOKEN'; -const ROLLBAR_PUBLISH_TOKEN_ENV_VAR_NAME = 'INSTANT_ROLLBAR_PUBLISH_TOKEN'; -const getRollbarTokens = (dischargeTarget, rollbarRequired) => { - const clientToken = process.env[ROLLBAR_CLIENT_TOKEN_ENV_VAR_NAME]; - const publishToken = process.env[ROLLBAR_PUBLISH_TOKEN_ENV_VAR_NAME]; - - if (rollbarRequired) { - if (!clientToken) { - throw new Error( - `Rollbar client token required for ${dischargeTarget}, please set env var ${ROLLBAR_CLIENT_TOKEN_ENV_VAR_NAME}`, - ); - } - if (!publishToken) { - throw new Error( - `Rollbar publish token required for ${dischargeTarget}, please set env var ${ROLLBAR_PUBLISH_TOKEN_ENV_VAR_NAME}`, - ); - } - } - - return { clientToken, publishToken }; -}; - -const generateConfig = (dischargeTarget, heapConfigOptions, rollbarConfigOptions, nodeEnv) => { - const outputPath = process.env.WEBPACK_OUTPUT_PATH || 'umd'; - - const { heapAnalyticsIdEnvName, heapAnalyticsIdRequired } = heapConfigOptions; - const heapAnalyticsId = process.env[heapAnalyticsIdEnvName]; - if (heapAnalyticsIdRequired && !heapAnalyticsId) { - throw new Error( - `Must define heap analytics id in ENV var ${heapAnalyticsIdEnvName} when building for ${dischargeTarget}`, - ); - } - const heapEnabled = heapAnalyticsId && (nodeEnv !== 'development' || process.env.INSTANT_HEAP_FORCE_DEVELOPMENT); - - const rollbarTokens = getRollbarTokens(dischargeTarget, rollbarConfigOptions.rollbarRequired); - const rollbarEnabled = - rollbarTokens.clientToken && (nodeEnv !== 'development' || process.env.INSTANT_ROLLBAR_FORCE_DEVELOPMENT); - - let rollbarPlugin; - if (rollbarConfigOptions.rollbarRequired) { - if (!rollbarEnabled || !rollbarTokens.publishToken || !rollbarConfigOptions.rollbarSourceMapPublicPath) { - throw new Error(`Rollbar required for ${dischargeTarget} but not configured`); - } - rollbarPlugin = new RollbarSourceMapPlugin({ - accessToken: rollbarTokens.publishToken, - version: GIT_SHA, - publicPath: rollbarConfigOptions.rollbarSourceMapPublicPath, - }); - } - - const envVars = { - GIT_SHA: JSON.stringify(GIT_SHA), - NPM_PACKAGE_VERSION: JSON.stringify(process.env.npm_package_version), - ROLLBAR_ENABLED: rollbarEnabled, - HEAP_ENABLED: heapEnabled - }; - if (dischargeTarget) { - envVars.INSTANT_DISCHARGE_TARGET = JSON.stringify(dischargeTarget); - } - if (heapAnalyticsId) { - envVars.HEAP_ANALYTICS_ID = JSON.stringify(heapAnalyticsId); - } - if (rollbarTokens.clientToken) { - envVars.ROLLBAR_CLIENT_TOKEN = JSON.stringify(rollbarTokens.clientToken); - } - - const plugins = [ - new webpack.DefinePlugin({ - 'process.env': envVars, - }), - ]; - if (rollbarPlugin) { - plugins.push(rollbarPlugin); - } - - const config = { - entry: { - instant: './src/index.umd.ts', - }, - output: { - filename: '[name].js', - path: path.resolve(__dirname, outputPath), - library: 'zeroExInstant', - libraryTarget: 'umd', - }, - plugins, - devtool: 'source-map', - resolve: { - extensions: ['.js', '.json', '.ts', '.tsx'], - }, - module: { - rules: [ - { - test: /\.(ts|tsx)$/, - loader: 'awesome-typescript-loader', - }, - { - test: /\.svg$/, - loader: 'svg-react-loader', - }, - { - test: /\.js$/, - loader: 'source-map-loader', - exclude: [ - // instead of /\/node_modules\// - path.join(process.cwd(), 'node_modules'), - path.join(process.cwd(), '../..', 'node_modules'), - ], - }, - ], - }, - devServer: { - contentBase: path.join(__dirname, 'public'), - port: 5000, - host: '0.0.0.0', - after: () => { - if (config.devServer.host === '0.0.0.0') { - console.log( - `webpack-dev-server can be accessed externally at: http://${ip.address()}:${ - config.devServer.port - }`, - ); - } - }, - }, - }; - return config; -}; - -module.exports = (env, argv) => { - const dischargeTarget = env ? env.discharge_target : undefined; - const heapConfigOptions = getHeapConfigForDischargeTarget(dischargeTarget); - const rollbarConfigOptions = getRollbarConfigForDischargeTarget(dischargeTarget); - return generateConfig(dischargeTarget, heapConfigOptions, rollbarConfigOptions, argv.mode); -}; -- cgit v1.2.3